Dubbo-互调


  • Dubbo应用
  • Triple协议的流式调用
  • 跨语言调用
    • protobuf
  • 与gRPC互通
  • 与Spring Cloud互通

Dubbo应用

  • 增加依赖
    • dubbo-spring-boot-starter
    • dubbo-rpc-dubbo
    • dubbo-rpc-rest 兼容 rest 协议,支持 http 调用
    • dubbo-rpc-triple
    • dubbo-registry-zookeeper
  • 配置文件
dubbo.application.name=provider-application
dubbo.protocol.name=dubbo
dubbo.protocol.port=20880
# 兼容 rest 协议
dubbo.protocols.p2.name=rest 
dubbo.protocols.p2.port=8082 
dubbo.registry.address=zookeeper://127.0.0.1:2181
  • @EnableDubbo(scanBasePackages = "com.xx.service") 开启
  • @DubboService 提供服务
    • 如果一个service接口名在多个不同的应用上定义了,dubbo只能注册一个
    • 返回的实体类需要实现 Serializable 接口,否则报错
    • 兼容 rest 协议
      • @Path("/user") 指定 url(类和方法都要标注)
      • @Produces(MediaType.APPLICATION_JSON) 方法返回 json 类型数据
      • 类上也要标注 @Produces
  • @DubboReference 引入一个 Dubbo 服务

Triple协议的流式调用

  • Triple 协议的 Stream 对于消费者来说是阻塞的
    • 生产者可以onNext分批发送,但是消费者按照发送顺序全部接收完后,才能分批处理,而不是即时处理
      • 代码设计问题,有一个标志位
    • grpc 可以即时处理
  • UNARY,就是正常的调用方法
  • SERVER_STREAM
// 服务提供者
public void sayHelloServerStream(String name, StreamObserver<String> response) { 
  response.onNext(name + " hello");
  response.onNext(name + " world");
  response.onCompleted();
}
// 服务消费者 
@DubboReference
private UserService userService;
userService.sayHelloServerStream("zhouyu", new StreamObserver<String>() { 
  @Override
  public void onNext(String data) { 
    // 服务端返回的数据
    System.out.println(data);
  }
  @Override
  public void onError(Throwable throwable) {} 
  @Override
  public void onCompleted() {
    System.out.println("complete"); 
  }
});
  • CLIENT_STREAM
    • BI_STREAM 和 CLIENT_STREAM 一样
// 服务提供者
public StreamObserver<String> sayHelloStream(StreamObserver<String> response) { 
  return new StreamObserver<String>() {
    @Override
    public void onNext(String data) {
      // 接收客户端发送过来的数据,然后返回数据给客户端 
      response.onNext("result:" + data);
    }
    @Override
    public void onError(Throwable throwable) {}  
    @Override
    public void onCompleted() {
      System.out.println("completed");
    }
  };
}
// 服务消费者 
@DubboReference
private UserService userService;
StreamObserver<String> streamObserver = userService.sayHelloStream(new StreamObserver<String>() {
   @Override
   public void onNext(String data) {
     System.out.println("接收到响应数据:"+ data); 
   }
   @Override
   public void onError(Throwable throwable) {} 
   @Override
   public void onCompleted() {
     System.out.println("接收到响应数据完毕"); 
   }
});
// 发送数据
streamObserver.onNext("request zhouyu hello"); 
streamObserver.onNext("request zhouyu world"); 
streamObserver.onCompleted();

跨语言调用

  • 与Java实现的Dubbo服务互调的条件
    • 该语言有 Dubbo 框架可以用
    • 使用 protobuf 技术,并且需要 protobuf 也支持该语言
  • userservice.proto
syntax = "proto3";
 
package api;
 
option go_package = "./;api";
 
option java_multiple_files = true;
option java_package = "com.xx";
option java_outer_classname = "UserServiceProto";
 
service UserService {
  rpc GetUser (UserRequest) returns (User) {}
}
 
// The response message containing the greetings 
message UserRequest {
  string uid = 1;
}
 
// The response message containing the greetings 
message User {
  string uid = 1;
  string username = 2;
}
  • 编译成 Java:maven -> compile
    • protobuf-maven-plugin
      • dubbo-compiler
  • @DubboService 标注 UserService 的实现类
  • 编译成 go
    • 安装 protoc
go env -w GO111MODULE=on 
go env -w GOPROXY=https://goproxy.cn,direct

go get -u github.com/dubbogo/tools/cmd/protoc-gen-go-triple
go install github.com/golang/protobuf/protoc-gen-go
go install github.com/dubbogo/tools/cmd/protoc-gen-go-triple
 
protoc -I. userservice.proto --go_out=../api --go-triple_out=../api

# 下载依赖
go mod tidy
  • 然后就可以写 go 语言的服务消费者了
  • 新建conf/dubbogo.yml,用来配置注册中心
    • 使用 tri 协议(Triple)

Triple与gRPC互通

  • tri 协议在发送请求和发送响应时,都是按照grpc的格式来发送的
    • 比如在请求头和响应头中设置grpc能识别的信息
  • gRPC 可以直接调 tri 协议的 Dubbo
  • Dubbo 调用 gRPC 服务
@DubboReference(protocol = "tri", url = "tri://localhost:8008", 
     proxy = CommonConstants.NATIVE_STUB)
private UserService userService;

与Spring Cloud互通

  • 要调用Spring Cloud的服务,得用http协议
    • 用tri协议去调用另外一个服务时,并不能去指定controller地址,得用rest协议,底层也是http协议
  • 指定controller地址
@Path("/")
@Consumes
public interface HelloService { 
  @GET @Path("hello")
  String hello();
}
// 调用 localhost:7070 上的 /hello
@DubboReference(url = "rest://localhost:7070", protocol = "rest")
private HelloService helloService; 
  • 如果Dubbo服务支持rest协议调用
    • SpringCloud应用就不需要引入Dubbo的依赖,直接使用Feign就可以完成调用
    • 其他情况要引入Dubbo依赖通过@DubboReference来使用
@DubboService(protocol = "rest")
@Produces @Path("/")
public class HelloServiceImpl implements HelloService{ 
  @Override
  @GET @Path("hello")
  public String hello() {
    return "dubbo hello";
  }
}
@FeignClient(name = "dubbo-provider-application", url = "localhost:20881") 
public interface HelloService {
  @RequestMapping(value = "/hello", method = RequestMethod.GET)
  public String hello();
}

文章作者: 钱不寒
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 钱不寒 !
  目录