使用說明
Triple 協議是 Dubbo3 的主要協議,完全相容 gRPC over HTTP/2,並在協議層級擴展了負載平衡和流量控制相關機制。本文旨在指導使用者正確使用 Triple 協議。
在開始之前,您需要決定服務使用的序列化方式。如果是新服務,建議預設使用 protobuf 作為序列化方式,這樣會有更好的效能和跨語言效果。如果原有服務想要升級協議,Triple 協議已經支援其他序列化方式,例如 Hessian / JSON 等。
Protobuf
編寫 IDL 檔案
syntax = "proto3"; option java_multiple_files = true; option java_package = "org.apache.dubbo.hello"; option java_outer_classname = "HelloWorldProto"; option objc_class_prefix = "HLW"; package helloworld; // The request message containing the user's name. message HelloRequest { string name = 1; } // The response message containing the greetings message HelloReply { string message = 1; }
新增編譯 protobuf 的擴展和插件(以 maven 為例)
<extensions> <extension> <groupId>kr.motd.maven</groupId> <artifactId>os-maven-plugin</artifactId> <version>1.6.1</version> </extension> </extensions> <plugins> <plugin> <groupId>org.xolstice.maven.plugins</groupId> <artifactId>protobuf-maven-plugin</artifactId> <version>0.6.1</version> <configuration> <protocArtifact>com.google.protobuf:protoc:3.7.1:exe:${os.detected.classifier}</protocArtifact> <pluginId>triple-java</pluginId> <outputDirectory>build/generated/source/proto/main/java</outputDirectory> </configuration> <executions> <execution> <goals> <goal>compile</goal> <goal>test-compile</goal> </goals> </execution> </executions> </plugin> </plugins>
建置/編譯以產生 protobuf Message 類別
$ mvn clean install
單向模式
編寫 Java 介面
import org.apache.dubbo.hello.HelloReply; import org.apache.dubbo.hello.HelloRequest; public interface IGreeter { /** * <pre> * Sends a greeting * </pre> */ HelloReply sayHello(HelloRequest request); }
建立 Provider
public static void main(String[] args) throws InterruptedException { ServiceConfig<IGreeter> service = new ServiceConfig<>(); service.setInterface(IGreeter.class); service.setRef(new IGreeter1Impl()); // Here you need to show that the protocol used by the declaration is triple service.setProtocol(new ProtocolConfig(CommonConstants.TRIPLE, 50051)); service.setApplication(new ApplicationConfig("demo-provider")); service.setRegistry(new RegistryConfig("zookeeper://127.0.0.1:2181")); service. export(); System.out.println("dubbo service started"); new CountDownLatch(1). await(); }
建立 Consumer
public static void main(String[] args) throws IOException { ReferenceConfig<IGreeter> ref = new ReferenceConfig<>(); ref. setInterface(IGreeter. class); ref. setCheck(false); ref.setProtocol(CommonConstants.TRIPLE); ref. setLazy(true); ref. setTimeout(100000); ref. setApplication(new ApplicationConfig("demo-consumer")); ref.setRegistry(new RegistryConfig("zookeeper://127.0.0.1:2181")); final IGreeter iGreeter = ref. get(); System.out.println("dubbo ref started"); try { final HelloReply reply = iGreeter.sayHello(HelloRequest.newBuilder() .setName("name") .build()); TimeUnit. SECONDS. sleep(1); System.out.println("Reply:" + reply); } catch (Throwable t) { t. printStackTrace(); } System.in.read(); }
執行 Provider 和 Consumer,您可以看到請求正常返回
回覆:message: “name”
串流模式
- 編寫 Java 介面
import org.apache.dubbo.hello.HelloReply; import org.apache.dubbo.hello.HelloRequest; public interface IGreeter { /** * <pre> * Sends greeting by stream * </pre> */
StreamObserver
}
```
- 編寫實現類別
public class IStreamGreeterImpl implements IStreamGreeter {
@Override public StreamObserver
return new StreamObserver
@Override public void onNext(HelloRequest helloRequest) { System.out.println(“onNext 收到請求名稱:” + helloRequest.getName()); replyList.add(HelloReply.newBuilder() .setMessage(“收到名稱:” + helloRequest.getName()) .build()); }
@Override public void onError(Throwable cause) { System.out.println(“onError”); replyObserver.onError(cause); }
@Override public void onCompleted() { System.out.println(“onComplete 收到請求數量:” + replyList.size()); for (HelloReply reply : replyList) { replyObserver.onNext(reply); } replyObserver.onCompleted(); } }; } }
10. Create a Provider
```java
public class StreamProvider {
public static void main(String[] args) throws InterruptedException {
ServiceConfig<IStreamGreeter> service = new ServiceConfig<>();
service.setInterface(IStreamGreeter.class);
service.setRef(new IStreamGreeterImpl());
service.setProtocol(new ProtocolConfig(CommonConstants.TRIPLE, 50051));
service.setApplication(new ApplicationConfig("stream-provider"));
service.setRegistry(new RegistryConfig("zookeeper://127.0.0.1:2181"));
service. export();
System.out.println("dubbo service started");
new CountDownLatch(1). await();
}
}
建立 Consumer
public class StreamConsumer { public static void main(String[] args) throws InterruptedException, IOException { ReferenceConfig
System.out.println(“dubbo ref started”); try {
StreamObserver
@Override public void onError(Throwable throwable) { System.out.println(“onError:” + throwable.getMessage()); }
@Override public void onCompleted() { System.out.println(“onCompleted”); } });
streamObserver.onNext(HelloRequest.newBuilder().setName(“tony”).build());
streamObserver.onNext(HelloRequest.newBuilder().setName(“nick”).build());
streamObserver.onCompleted(); } catch (Throwable t) { t.printStackTrace(); } System.in.read(); } }
12. Run Provider and Consumer, you can see that the request returns normally
> onNext\
> receive name:tony\
> onNext\
> receive name:nick\
> onCompleted
### Other serialization methods
Omit steps 1-3 above, and specify the protocol used by Provider and Consumer to complete the protocol upgrade.
### Example program
The sample program of this article can be found in [triple-samples](https://github.com/apache/dubbo-samples/tree/master/3-extensions/protocol/dubbo-samples-triple)