Dubbo 在跨語言和協議穿透性方向的探索:支援 HTTP/2 gRPC
Dubbo 在跨語言和協議穿透性方向上的探索:支援 HTTP/2 gRPC 和 Protobuf
本文整理自劉軍在 Dubbo 成都 meetup 上分享的《Dubbo 在多語言和協議穿透性方向上的探索》。
本文總體上可分為基礎產品簡介、Dubbo 對 gRPC (HTTP/2) 和 Protobuf 的支援及示例演示三部分,在簡介部分介紹了 Dubbo、HTTP/2、gRPC、Protobuf 的基本概念和特點;第二部分介紹了 Dubbo 為何要支援 gRPC (HTTP/2) 和 Protobuf,以及這種支援為 gRPC 和 Dubbo 開發帶來的好處與不同;第三部分透過兩個例項分別演示了 Dubbo gRPC 和 Dubbo Protobuf 的使用方式。
基本介紹
Dubbo 協議
從協議層面展開,以下是當前 2.7 版本支援的 Dubbo 協議
眾所周知,Dubbo 協議是直接定義在 TCP 傳輸層協議之上,由於 TCP 高可靠全雙工的特點,為 Dubbo 協議的定義提供了最大的靈活性,但同時也正是因為這樣的靈活性,RPC 協議普遍都是定製化的私有協議,Dubbo 同樣也面臨這個問題。在這裡我們著重講一下 Dubbo 在協議通用性方面值得改進的地方,關於協議詳細解析請參見官網部落格
- Dubbo 協議體 Body 中有一個可擴充套件的 attachments 部分,這給 RPC 方法之外額外傳遞附加屬性提供了可能,是一個很好的設計。但是類似的 Header 部分,卻缺少類似的可擴充套件 attachments,這點可參考 HTTP 定義的 Ascii Header 設計,將 Body Attachments 和 Header Attachments 做職責劃分。
- Body 協議體中的一些 RPC 請求定位符如 Service Name、Method Name、Version 等,可以提到 Header 中,和具體的序列化協議解耦,以更好的被網路基礎設施識別或用於流量管控。
- 擴充套件性不夠好,欠缺協議升級方面的設計,如 Header 頭中沒有預留的狀態標識位,或者像 HTTP 有專為協議升級或協商設計的特殊 packet。
- 在 Java 版本的程式碼實現上,不夠精簡和通用。如在鏈路傳輸中,存在一些語言繫結的內容;訊息體中存在冗餘內容,如 Service Name 在 Body 和 Attachments 中都存在。
HTTP/1
相比於直接構建與 TPC 傳輸層的私有 RPC 協議,構建於 HTTP 之上的遠端呼叫解決方案會有更好的通用性,如WebServices 或 REST 架構,使用 HTTP + JSON 可以說是一個事實標準的解決方案。
之所有選擇構建在 HTTP 之上,我認為有兩個最大的優勢:
- HTTP 的語義和可擴充套件效能很好的滿足 RPC 呼叫需求。
- 通用性,HTTP 協議幾乎被網路上的所有裝置所支援,具有很好的協議穿透性。
具體來說,HTTP/1 的優勢和限制是:
- 典型的 Request – Response 模型,一個鏈路上一次只能有一個等待的 Request 請求
- HTTP/1 支援 Keep-Alive 連結,避免了連結重複建立開銷
- Human Readable Headers,使用更通用、更易於人類閱讀的頭部傳輸格式
- 無直接 Server Push 支援,需要使用 Polling Long-Polling 等變通模式
HTTP/2
HTTP/2 保留了 HTTP/1 的所有語義,在保持相容的同時,在通訊模型和傳輸效率上做了很大的改進。
- 支援單條鏈路上的 Multiplexing,相比於 Request - Response 獨佔鏈路,基於 Frame 實現更高效利用鏈路
- Request - Stream 語義,原生支援 Server Push 和 Stream 資料傳輸
- Flow Control,單條 Stream 粒度的和整個鏈路粒度的流量控制
- 頭部壓縮 HPACK
- Binary Frame
- 原生 TLS 支援
gRPC
上面提到了在 HTTP 及 TCP 協議之上構建 RPC 協議各自的優缺點,相比於 Dubbo 構建於 TPC 傳輸層之上,Google 選擇將 gRPC 直接定義在 HTTP/2 協議之上,關於 gRPC 的 基本介紹和 設計願景請參考以上兩篇文章,我這裡僅摘取 設計願景 中幾個能反映 gRPC 設計目的特性來做簡單說明。
- Coverage & Simplicity,協議設計和框架實現要足夠通用和簡單,能執行在任何裝置之上,甚至一些資源首先的如 IoT、Mobile 等裝置。
- Interoperability & Reach,要構建在更通用的協議之上,協議本身要能被網路上幾乎所有的基礎設施所支援。
- General Purpose & Performant,要在場景和效能間做好平衡,首先協議本身要是適用於各種場景的,同時也要儘量有高的效能。
- Payload Agnostic,協議上傳輸的負載要保持語言和平臺中立。
- Streaming,要支援 Request - Response、Request - Stream、Bi-Steam 等通訊模型。
- Flow Control,協議自身具備流量感知和限制的能力。
- Metadata Exchange,在 RPC 服務定義之外,提供額外附加資料傳輸的能力。
總的來說,在這樣的設計理念指導下,gRPC 最終被設計為一個跨語言、跨平臺的、通用的、高效能的、基於 HTTP/2 的 RPC 協議和框架。
Protobuf
Protocol buffers (Protobuf) 是 Google 推出的一個跨平臺、語言中立的結構化資料描述和序列化的產品,它定義了一套結構化資料定義的協議,同時也提供了相應的 Compiler 工具,用來將語言中立的描述轉化為相應語言的具體描述。
它的一些特性包括:
- 跨語言 跨平臺,語言中立的資料描述格式,預設提供了生成多種語言的 Compiler 工具。
- 安全性,由於反序列化的範圍和輸出內容格式都是 Compiler 在編譯時預生成的,因此繞過了類似 Java Deserialization Vulnarability 的問題。
- 二進位制 高效能
- 強型別
- 欄位變更向後相容
message Person {
required string name = 1;
required int32 id = 2;
optional string email = 3;
enum PhoneType {
MOBILE = 0;
HOME = 1;
WORK = 2;
}
message PhoneNumber {
required string number = 1;
optional PhoneType type = 2 [default = HOME];
}
repeated PhoneNumber phone = 4;
}
除了結構化資料描述之外,Protobuf 還支援定義 RPC 服務,它允許我們定義一個 .proto 的服務描述檔案,進而利用 Protobuf Compiler 工具生成特定語言和 RPC 框架的介面和 stub。後續將要具體講到的 gRPC + Protobuf、Dubbo-gRPC + Protobuf 以及 Dubbo + Protobuf 都是透過定製 Compiler 類實現的。
service SearchService {
rpc Search (SearchRequest) returns (SearchResponse);
}
Dubbo 所做的支援
跨語言的服務開發涉及到多個方面,從服務定義、RPC 協議到序列化協議都要做到語言中立,同時還針對每種語言有對應的 SDK 實現。雖然得益於社群的貢獻,現在 Dubbo 在多語言 SDK 實現上逐步有了起色,已經提供了包括 Java, Go, PHP, C#, Python, NodeJs, C 等版本的客戶端或全量實現版本,但在以上提到的跨語言友好型方面,以上三點還是有很多可改進之處。
- 協議,上面我們已經分析過 Dubbo 協議既有的缺點,如果能在 HTTP/2 之上構建應用層協議,則無疑能避免這些弊端,同時最大可能的提高協議的穿透性,避免閘道器等協議轉換元件的存在,更有利於鏈路上的流量管控。考慮到 gRPC 是構建在 HTTP/2 之上,並且已經是雲原生領域推薦的通訊協議,Dubbo 在第一階段選擇了直接支援 gRPC 協議作為當前的 HTTP/2 解決方案。我們也知道 gRPC 框架自身的弊端在於易用性不足以及服務治理能力欠缺(這也是目前絕大多數廠商不會直接裸用 gRPC 框架的原因),透過將其整合進 Dubbo 框架,使用者可以方便的使用 Dubbo 程式設計模型 + Dubbo 服務治理 + gRPC 協議通訊的組合。
- 服務定義,當前 Dubbo 的服務定義和具體的程式語言繫結,沒有提供一種語言中立的服務描述格式,比如 Java 就是定義 Interface 介面,到了其他語言又得重新以另外的格式定義一遍。因此 Dubbo 透過支援 Protobuf 實現了語言中立的服務定義。
- 序列化,Dubbo 當前支援的序列化包括 Json、Hessian2、Kryo、FST、Java 等,而這其中支援跨語言的只有 Json、Hessian2,通用的 Json 有固有的效能問題,而 Hessian2 無論在效率還是多語言 SDK 方面都有所欠缺。為此,Dubbo 透過支援 Protobuf 序列化來提供更高效、易用的跨語言序列化方案。
示例
示例 1,使用 Dubbo 開發 gRPC 服務
gRPC 是 Google 開源的構建在 HTTP/2 之上的一個 PRC 通訊協議。Dubbo 依賴其靈活的協議擴充套件機制,增加了對 gRPC (HTTP/2) 協議的支援。
目前的支援限定在 Dubbo Java 語言版本,後續 Go 語言或其他語言版本將會以類似方式提供支援。下面,透過一個簡單的 示例來演示如何在 Dubbo 中使用 gRPC 協議通訊。
1. 定義服務 IDL
首先,透過標準的 Protobuf 協議定義服務如下:
syntax = "proto3";
option java_multiple_files = true;
option java_package = "io.grpc.examples.helloworld";
option java_outer_classname = "HelloWorldProto";
option objc_class_prefix = "HLW";
package helloworld;
// The greeting service definition.
service Greeter {
// Sends a greeting
rpc SayHello (HelloRequest) returns (HelloReply) {}
}
// The request message containing the user's name.
message HelloRequest {
string name = 1;
}
// The response message containing the greetings
message HelloReply {
string message = 1;
}
在此,我們定義了一個只有一個方法 sayHello 的 Greeter 服務,同時定義了方法的入參和出參,
2. Protobuf Compiler 生成 Stub
- 定義 Maven Protobuf Compiler 外掛工具。這裡我們擴充套件了 Protobuf 的 Compiler 工具,以用來生成 Dubbo 特有的 RPC stub,此當前以 Maven 外掛的形式釋出。
<plugin>
<groupId>org.xolstice.maven.plugins</groupId>
<artifactId>protobuf-maven-plugin</artifactId>
<version>0.5.1</version>
<configuration>
<protocArtifact>com.google.protobuf:protoc:3.7.1:exe:${os.detected.classifier}
</protocArtifact>
<pluginId>dubbo-grpc-java</pluginId>
<pluginArtifact>org.apache.dubbo:protoc-gen-dubbo-java:1.19.0-SNAPSHOT:exe:${os.detected.classifier}</pluginArtifact>
<outputDirectory>build/generated/source/proto/main/java</outputDirectory>
<clearOutputDirectory>false</clearOutputDirectory>
<pluginParameter>grpc</pluginParameter>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>compile-custom</goal>
</goals>
</execution>
</executions>
</plugin>
其中,
pluginArtifact 指定了 Dubbo 定製版本的 Java Protobuf Compiler 外掛,透過這個外掛來在編譯過程中生成 Dubbo 定製版本的 gRPC stub。
<pluginArtifact>org.apache.dubbo:protoc-gen-dubbo-java:1.19.0-SNAPSHOT:exe:${os.detected.classifier}</pluginArtifact>
由於 protoc-gen-dubbo-java 支援 gRPC 和 Dubbo 兩種協議,可生成的 stub 型別,預設值是 gRPC,關於 dubbo 協議的使用可參見 使用 Protobuf 開發 Dubbo 服務。
<pluginParameter>grpc</pluginParameter>
2. 生成 Java Bean 和 Dubbo-gRPC stub
# 執行以下 maven 命令
$ mvn clean compile
生成的 Stub 和訊息類 如下:
重點關注 GreeterGrpc ,包含了所有 gRPC 標準的 stub 類/方法,同時增加了 Dubbo 特定的介面,之後 Provider 端的服務暴露和 Consumer 端的服務呼叫都將依賴這個介面。
/**
* Code generated for Dubbo
*/
public interface IGreeter {
default public io.grpc.examples.helloworld.HelloReply sayHello(io.grpc.examples.helloworld.HelloRequest request) {
throw new UnsupportedOperationException("No need to override this method, extend XxxImplBase and override all methods it allows.");
}
default public com.google.common.util.concurrent.ListenableFuture<io.grpc.examples.helloworld.HelloReply> sayHelloAsync(
io.grpc.examples.helloworld.HelloRequest request) {
throw new UnsupportedOperationException("No need to override this method, extend XxxImplBase and override all methods it allows.");
}
public void sayHello(io.grpc.examples.helloworld.HelloRequest request,
io.grpc.stub.StreamObserver<io.grpc.examples.helloworld.HelloReply> responseObserver);
}
3. 業務邏輯開發
繼承 GreeterGrpc.GreeterImplBase (來自第 2 步),編寫業務邏輯,這點和原生 gRPC 是一致的。
package org.apache.dubbo.samples.basic.impl;
import io.grpc.examples.helloworld.GreeterGrpc;
import io.grpc.examples.helloworld.HelloReply;
import io.grpc.examples.helloworld.HelloRequest;
import io.grpc.stub.StreamObserver;
public class GrpcGreeterImpl extends GreeterGrpc.GreeterImplBase {
@Override
public void sayHello(HelloRequest request, StreamObserver<HelloReply> responseObserver) {
System.out.println("Received request from client.");
System.out.println("Executing thread is " + Thread.currentThread().getName());
HelloReply reply = HelloReply.newBuilder()
.setMessage("Hello " + request.getName()).build();
responseObserver.onNext(reply);
responseObserver.onCompleted();
}
}
- Provider 端暴露 Dubbo 服務
以 Spring XML 為例
<dubbo:application name="demo-provider"/>
<!-- 指定服務暴露協議為 gRPC -->
<dubbo:protocol id="grpc" name="grpc"/>
<dubbo:registry address="zookeeper://${zookeeper.address:127.0.0.1}:2181"/>
<bean id="greeter" class="org.apache.dubbo.samples.basic.impl.GrpcGreeterImpl"/>
<!-- 指定 protoc-gen-dubbo-java 生成的介面 -->
<dubbo:service interface="io.grpc.examples.helloworld.GreeterGrpc$IGreeter" ref="greeter" protocol="grpc"/>
public static void main(String[] args) throws Exception {
ClassPathXmlApplicationContext context =
new ClassPathXmlApplicationContext("spring/dubbo-demo-provider.xml");
context.start();
System.out.println("dubbo service started");
new CountDownLatch(1).await();
}
- 引用 Dubbo 服務
<dubbo:application name="demo-consumer"/>
<dubbo:registry address="zookeeper://${zookeeper.address:127.0.0.1}:2181"/>
<!-- 指定 protoc-gen-dubbo-java 生成的介面 -->
<dubbo:reference id="greeter" interface="io.grpc.examples.helloworld.GreeterGrpc$IGreeter" protocol="grpc"/>
public static void main(String[] args) throws IOException {
ClassPathXmlApplicationContext context =
new ClassPathXmlApplicationContext("spring/dubbo-demo-consumer.xml");
context.start();
GreeterGrpc.IGreeter greeter = (GreeterGrpc.IGreeter) context.getBean("greeter");
HelloReply reply = greeter.sayHello(HelloRequest.newBuilder().setName("world!").build());
System.out.println("Result: " + reply.getMessage());
System.in.read();
}
示例1附:高階用法
一、非同步呼叫
再來看一遍 protoc-gen-dubbo-java 生成的介面:
/**
* Code generated for Dubbo
*/
public interface IGreeter {
default public HelloReply sayHello(HelloRequest request) {
// ......
}
default public ListenableFuture<HelloReply> sayHelloAsync(HelloRequest request) {
// ......
}
public void sayHello(HelloRequest request, StreamObserver<HelloReply> responseObserver);
}
這裡為 sayHello 方法生成了三種型別的過載方法,分別用於同步呼叫、非同步呼叫和流式呼叫,如果消費端要進行非同步呼叫,直接呼叫 sayHelloAsync() 即可:
public static void main(String[] args) throws IOException {
// ...
GreeterGrpc.IGreeter greeter = (GreeterGrpc.IGreeter) context.getBean("greeter");
ListenableFuture<HelloReply> future =
greeter.sayHAsyncello(HelloRequest.newBuilder().setName("world!").build());
// ...
}
二、高階配置
由於當前實現方式是直接整合了 gRPC-java SDK,因此很多配置還沒有和 Dubbo 側對齊,或者還沒有以 Dubbo 的配置形式開放,因此,為了提供最大的靈活性,我們直接把 gRPC-java 的配置介面暴露了出來。
絕大多數場景下,你可能並不會用到以下擴充套件,因為它們更多的是對 gRPC 協議的攔截或者 HTTP/2 層面的配置。同時使用這些擴充套件點可能需要對 HTTP/2 或 gRPC 有基本的瞭解。
擴充套件點
目前支援的擴充套件點如下:
- org.apache.dubbo.rpc.protocol.grpc.interceptors.ClientInterceptor
- org.apache.dubbo.rpc.protocol.grpc.interceptors.GrpcConfigurator
- org.apache.dubbo.rpc.protocol.grpc.interceptors.ServerInterceptor
- org.apache.dubbo.rpc.protocol.grpc.interceptors.ServerTransportFilter
GrpcConfigurator 是最通用的擴充套件點,我們以此為例來說明一下,其基本定義如下:
public interface GrpcConfigurator {
// 用來定製 gRPC NettyServerBuilder
default NettyServerBuilder configureServerBuilder(NettyServerBuilder builder, URL url) {
return builder;
}
// 用來定製 gRPC NettyChannelBuilder
default NettyChannelBuilder configureChannelBuilder(NettyChannelBuilder builder, URL url) {
return builder;
}
// 用來定製 gRPC CallOptions, 定義某個服務在每次請求間傳遞資料
default CallOptions configureCallOptions(CallOptions options, URL url) {
return options;
}
}
以下是一個示例擴充套件實現:
public class MyGrpcConfigurator implements GrpcConfigurator {
private final ExecutorService executor = Executors
.newFixedThreadPool(200, new NamedThreadFactory("Customized-grpc", true));
@Override
public NettyServerBuilder configureServerBuilder(NettyServerBuilder builder, URL url) {
return builder.executor(executor);
}
@Override
public NettyChannelBuilder configureChannelBuilder(NettyChannelBuilder builder, URL url)
{
return builder.flowControlWindow(10);
}
@Override
public CallOptions configureCallOptions(CallOptions options, URL url) {
return options.withOption(CallOptions.Key.create("key"), "value");
}
}
配置為 Dubbo SPI,`resources/META-INF/services 增加配置檔案
default=org.apache.dubbo.samples.basic.comtomize.MyGrpcConfigurator
- 指定 Provider 端執行緒池
預設用的是 Dubbo 的執行緒池,有 fixed (預設)、cached、direct 等型別。以下演示了切換為業務自定義執行緒池。
private final ExecutorService executor = Executors
.newFixedThreadPool(200, new NamedThreadFactory("Customized-grpc", true));
public NettyServerBuilder configureServerBuilder(NettyServerBuilder builder, URL url)
{
return builder.executor(executor);
}
- 指定 Consumer 端限流值
設定 Consumer 限流值為 10
@Override
public NettyChannelBuilder configureChannelBuilder(NettyChannelBuilder builder, URL url)
{
return builder.flowControlWindow(10);
}
- 傳遞附加引數
DemoService 服務呼叫傳遞 key
@Override
public CallOptions configureCallOptions(CallOptions options, URL url) {
if (url.getServiceInterface().equals("xxx.DemoService")) {
return options.withOption(CallOptions.Key.create("key"), "value");
} else {
return options;
}
}
三、雙向流式通訊
程式碼中還提供了一個支援
雙向流式通訊的示例,同時提供了攔截流式呼叫的 Interceptor 擴充套件示例實現。
* MyClientStreamInterceptor,工作在 client 端,攔截髮出的請求流和接收的響應流
* MyServerStreamInterceptor,工作在 server 端,攔截收到的請求流和發出的響應流
四、TLS 配置
配置方式和 Dubbo 提供的通用的 TLS 支援一致,具體請參見 Dubbo 官方文件
示例 2, 使用 Protobuf 開發 Dubbo 服務
下面,我們以一個 具體的示例來看一下基於 Protobuf 的 Dubbo 服務開發流程。
1. 定義服務
透過標準 Protobuf 定義服務
syntax = "proto3";
option java_multiple_files = true;
option java_package = "org.apache.dubbo.demo";
option java_outer_classname = "DemoServiceProto";
option objc_class_prefix = "DEMOSRV";
package demoservice;
// The demo service definition.
service DemoService {
rpc SayHello (HelloRequest) returns (HelloReply) {}
}
// The request message containing the user's name.
message HelloRequest {
string name = 1;
}
// The response message containing the greetings
message HelloReply {
string message = 1;
}
這裡定義了一個 DemoService 服務,服務只包含一個 sayHello 方法,同時定義了方法的入參和出參。
2. Compiler 編譯服務
- 引入 Protobuf Compiler Maven 外掛,同時指定 protoc-gen-dubbo-java RPC 擴充套件
<plugin>
<groupId>org.xolstice.maven.plugins</groupId>
<artifactId>protobuf-maven-plugin</artifactId>
<version>0.5.1</version>
<configuration>
<protocArtifact>com.google.protobuf:protoc:3.7.1:exe:${os.detected.classifier}
</protocArtifact>
<pluginId>dubbo-grpc-java</pluginId>
<pluginArtifact>org.apache.dubbo:protoc-gen-dubbo-java:1.19.0-SNAPSHOT:exe:${os.detected.classifier}</pluginArtifact>
<outputDirectory>build/generated/source/proto/main/java</outputDirectory>
<clearOutputDirectory>false</clearOutputDirectory>
<pluginParameter>dubbo</pluginParameter>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>compile-custom</goal>
</goals>
</execution>
</executions>
</plugin>
注意,這裡與 Dubbo 對 gRPC 支援部分的區別在於: dubbo
- 生成 RPC stub
# 執行以下 maven 命令
$mvn clean compile
生成的 Java 類如下:
DemoServiceDubbo 為 Dubbo 定製的 stub
public final class DemoServiceDubbo {
private static final AtomicBoolean registered = new AtomicBoolean();
private static Class<?> init() {
Class<?> clazz = null;
try {
clazz = Class.forName(DemoServiceDubbo.class.getName());
if (registered.compareAndSet(false, true)) {
org.apache.dubbo.common.serialize.protobuf.support.ProtobufUtils.marshaller(
org.apache.dubbo.demo.HelloRequest.getDefaultInstance());
org.apache.dubbo.common.serialize.protobuf.support.ProtobufUtils.marshaller(
org.apache.dubbo.demo.HelloReply.getDefaultInstance());
}
} catch (ClassNotFoundException e) {
// ignore
}
return clazz;
}
private DemoServiceDubbo() {}
public static final String SERVICE_NAME = "demoservice.DemoService";
/**
* Code generated for Dubbo
*/
public interface IDemoService {
static Class<?> clazz = init();
org.apache.dubbo.demo.HelloReply sayHello(org.apache.dubbo.demo.HelloRequest request);
java.util.concurrent.CompletableFuture<org.apache.dubbo.demo.HelloReply> sayHelloAsync(
org.apache.dubbo.demo.HelloRequest request);
}
}
最值得注意的是 IDemoService 介面,它會作為 Dubbo 服務定義基礎介面。
3. 開發業務邏輯
從這一步開始,所有開發流程就和直接定義 Java 介面一樣了。實現介面定義業務邏輯。
public class DemoServiceImpl implements DemoServiceDubbo.IDemoService {
private static final Logger logger = LoggerFactory.getLogger(DemoServiceImpl.class);
@Override
public HelloReply sayHello(HelloRequest request) {
logger.info("Hello " + request.getName() + ", request from consumer: " + RpcContext.getContext().getRemoteAddress());
return HelloReply.newBuilder()
.setMessage("Hello " + request.getName() + ", response from provider: "
+ RpcContext.getContext().getLocalAddress())
.build();
}
@Override
public CompletableFuture<HelloReply> sayHelloAsync(HelloRequest request) {
return CompletableFuture.completedFuture(sayHello(request));
}
}
4. 配置 Provider
暴露 Dubbo 服務
<dubbo:application name="demo-provider"/>
<dubbo:registry address="zookeeper://127.0.0.1:2181"/>
<dubbo:protocol name="dubbo"/>
<bean id="demoService" class="org.apache.dubbo.demo.provider.DemoServiceImpl"/>
<dubbo:service interface="org.apache.dubbo.demo.DemoServiceDubbo$IDemoService" ref="demoService"/>
public static void main(String[] args) throws Exception {
ClassPathXmlApplicationContext context =
new ClassPathXmlApplicationContext("spring/dubbo-provider.xml");
context.start();
System.in.read();
}
5. 配置 Consumer
引用 Dubbo 服務
<dubbo:application name="demo-consumer"/>
<dubbo:registry address="zookeeper://127.0.0.1:2181"/>
<dubbo:reference id="demoService" check="false" interface="org.apache.dubbo.demo.DemoServiceDubbo$IDemoService"/>
public static void main(String[] args) throws Exception {
ClassPathXmlApplicationContext context =
new ClassPathXmlApplicationContext("spring/dubbo-consumer.xml");
context.start();
IDemoService demoService = context.getBean("demoService", IDemoService.class);
HelloRequest request = HelloRequest.newBuilder().setName("Hello").build();
HelloReply reply = demoService.sayHello(request);
System.out.println("result: " + reply.getMessage());
System.in.read();
}
展望
RPC 協議是實現微服務體系互通的核心元件,通常採用不同的微服務通訊框架則意味著繫結某一個特定的協議,如 Spring Cloud 基於 HTTP、gRPC 提供 gRPC over HTTP/2、Thrift Hessian 等都是自定義私有協議。
Dubbo 自身同樣提供了私有的 Dubbo 協議,這樣你也能基於 Dubbo 協議構建微服務。但除了單一協議之外,和以上所有框架不同的,Dubbo 最大的優勢在於它能同時支援多協議的暴露和消費,再配合 Dubbo 多註冊訂閱的模型,可以讓 Dubbo 成為橋接多種不同協議的微服務體系的開發框架,輕鬆的實現不同微服務體系的互調互通或技術棧遷移。
這篇文章詳細講解了 Dubbo 對 gRPC 協議的支援,再加上 Dubbo 之前已具備的對 REST、Hessian、Thrift 等的支援,使 Dubbo 在協議互調上具備了基礎。我們只需要在服務發現模型上也能實現和這些不同體系的打通,就能解決不同技術棧互調和遷移的問題。關於這部分的具體應用場景以及工作模式,我們將在接下來的文章中來具體分析。
本文為雲棲社群原創內容,未經允許不得轉載。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69949601/viewspace-2666493/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- PowerMock: 支援GRPC協議的 Mock ServerMockRPC協議Server
- gRPC 之流式呼叫原理 http2 協議分析(四)RPCHTTP協議
- 聊聊dubbo協議2協議
- HTTP協議(2)HTTP協議
- Dubbo 支援哪些序列化協議?協議
- HTTP2 協議HTTP協議
- 星海支援 TARS 和 Dubbo 協議啦~協議
- HTTP協議之:HTTP/1.1和HTTP/2HTTP協議
- 瞭解HTTP/2協議HTTP協議
- Dubbo 3.0 前瞻之:常用協議對比及 RPC 協議新形態探索協議RPC
- 【GoLang 那點事】gRPC 之流式呼叫原理 http2 協議分析(四)GolangRPCHTTP協議
- 輕鬆讓你的nginx伺服器支援HTTP2協議Nginx伺服器HTTP協議
- Go Module 支援 HTTP 協議的私有庫方案GoHTTP協議
- Gossip協議和Grpc協議的區別Go協議RPC
- 使用 JSON 協議的 gRPCJSON協議RPC
- 如何在 Apinto 實現 HTTP 與gRPC 的協議轉換 (下)APIHTTPRPC協議
- 如何在 Apinto 實現 HTTP 與gRPC 的協議轉換 (上)APIHTTPRPC協議
- [HTTP 系列] 第 2 篇 —— HTTP 協議那些事HTTP協議
- HTTP協議圖文簡述--HTTP/HTTPS/HTTP2HTTP協議
- 02 前端HTTP協議(圖解HTTP) 之 簡單的HTTP協議前端HTTP協議圖解
- 如何實現IIS 7.0對非HTTP協議的支援HTTP協議
- 真正“搞”懂HTTP協議13之HTTP2HTTP協議
- http協議HTTP協議
- HTTP 協議HTTP協議
- Java9系列第九篇-對HTTP2協議的支援與非阻塞HTTP-APIJavaHTTP協議API
- 協議:SpringCloud VS Dubbo協議SpringGCCloud
- 解密HTTP協議:探索其組成部分與工作原理解密HTTP協議
- HTTP2 協議長文詳解HTTP協議
- 深入理解 Web 協議 (三):HTTP 2Web協議HTTP
- HTTP協議和HTTPS協議的異同點?HTTP協議
- 理解http協議HTTP協議
- http協議分析HTTP協議
- HTTP 協議類HTTP協議
- 小解http協議HTTP協議
- HTTP協議概述HTTP協議
- HTTP協議的特點HTTP協議
- HTTP 協議的前世今生HTTP協議
- dubbo註冊協議(三)協議