测试准备

介绍

以下介绍是摘自 Dubbo 官网,Dubbo 是一款 RPC 服务开发框架,用于解决微服务架构下的服务治理与通信问题,官方提供了 Java、Golang 等多语言 SDK 实现。使用 Dubbo 开发的微服务原生具备相互之间的远程地址发现与通信能力, 利用 Dubbo 提供的丰富服务治理特性,可以实现诸如服务发现、负载均衡、流量调度等服务治理诉求。在云原生时代,Dubbo 相继衍生出了 Dubbo3、Proxyless Mesh 等架构与解决方案,在易用性、超大规模微服务实践、云原生基础设施适配、安全性等几大方向上进行了全面升级。

Dubbo 框架支持多种通信协议:基于 HTTP/2 的 Triple 协议 和 基于 TCP 的 Dubbo2 协议。除此之外,Dubbo 框架支持任意第三方通信协议,如官方支持的 gRPC、Thrift、REST、JsonRPC、Hessian2 等,更多协议可以通过自定义扩展实现。Dubbo2 的用户一般使用 dubbo 协议,单一长连接,进行的是 NIO 异步通信,基于 hessian 作为序列化协议。Dubbo3 默认使用 Triple 协议,默认仅支持 Protobuf 序列化,对于 Java 语言中的多参数以及方法重载无法支持,但 Triple 有具备跨语言交互的能力、更完善的请求模型、完全兼容 grpc 等优点。

关于详细的概念与架构介绍,可参考 dubbo 概念与架构

这里基于官网文档和 github 示例,测试了 dubbo 多种部署场景,分别是原始 dubo 接入不同的注册中心、dubbo 结合 spring boot、dubbo 接入服务网格。

前置准备

本地是用的 k3s 单节点集群,安装 istio 过程在之前博客 Istio 安装和示例实践,下面是创建测试用的命名空间。 需要提前安装好环境:

  • kubernetes(这里是 k3s 安装的单节点)
  • docker
  • kubens
  • istio

kubens 在 ubuntu 上可以使用下面命令安装:

1
2
3
4
# ubuntu 安装 kubectx 和 kubens
snap install kubectx --classic
# 获取 dubbo 测试代码
git clone https://github.com/apache/dubbo-samples.git

dubbo 接入多注册中心

这里直接使用 dubbo 微服务开发框架,测试接入不同的注册中心,来了解使用不同的注册中心时具体的配置差异,测试代码来源于 dubbo 的 github 示例项目 dubbo-samples

dubbo 接入 zookeeper

此例是 dubbo 框架直接使用 zookeeper 做为注册中心,没有接入 k8s 和服务网格。进入测试代码目录,其目录结构为:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
cd 3-extensions/registry/dubbo-samples-zookeeper
tree -L 10
.
├── pom.xml
├── src
│   ├── main
│   │   ├── java
│   │   │   └── org
│   │   │       └── apache
│   │   │           └── dubbo
│   │   │               └── samples
│   │   │                   ├── ConsumerBootstrap.java
│   │   │                   ├── ProviderBootstrap.java
│   │   │                   ├── action
│   │   │                   │   └── GreetingServiceConsumer.java
│   │   │                   ├── api
│   │   │                   │   └── GreetingService.java
│   │   │                   └── impl
│   │   │                       └── AnnotatedGreetingService.java
│   │   └── resources
│   │       ├── log4j.properties
│   │       └── spring
│   │           ├── dubbo-consumer.properties
│   │           └── dubbo-provider.properties

provider 的 dubbo-provider.properties 配置为:

1
2
3
4
5
dubbo.application.name=zookeeper-demo-provider
dubbo.registry.address=zookeeper://${zookeeper.address:localhost}:${zookeeper.port:2181}
dubbo.protocol.name=dubbo
dubbo.protocol.port=20880
dubbo.provider.token=true

consumer 的 dubbo-consumer.properties 配置为:

1
2
3
dubbo.application.name=zookeeper-demo-consumer
dubbo.registry.address=zookeeper://${zookeeper.address:localhost}:${zookeeper.port:2181}
dubbo.consumer.timeout=3000

查看 consumer 中调用 api 的代码,greetingService 没有指定具体的 bean,这里是使用 DubboReference 自动注入 AnnotatedGreetingService 的:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
@Component("annotatedConsumer")
public class GreetingServiceConsumer {

    @DubboReference(version = "1.0.0")
    private GreetingService greetingService;

    public String doSayHello(String name) {
        return greetingService.sayHello(name);
    }

}

执行以下命令部署测试:

1
2
3
4
5
docker run --name some-zookeeper -p 2181:2181 --restart always -d zookeeper
# 部署 provider
./mvnw clean compile exec:java -pl 3-extensions/registry/dubbo-samples-zookeeper -Dexec.mainClass="org.apache.dubbo.samples.ProviderBootstrap"
# 部署 consumer
./mvnw clean compile exec:java -pl 3-extensions/registry/dubbo-samples-zookeeper -Dexec.mainClass="org.apache.dubbo.samples.ConsumerBootstrap"

dubbo 接入 consul

此例是 dubbo 框架直接使用 consul 做为注册中心,没有接入 k8s 和服务网格。进入测试代码目录,其目录结构为:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
cd 3-extensions/registry/dubbo-samples-consul
tree -L 10
.
├── pom.xml
└── src
    ├── main
    │   ├── java
    │   │   └── org
    │   │       └── apache
    │   │           └── dubbo
    │   │               └── samples
    │   │                   └── consul
    │   │                       ├── ConsulConsumer.java
    │   │                       ├── ConsulProvider.java
    │   │                       ├── api
    │   │                       │   └── DemoService.java
    │   │                       └── impl
    │   │                           └── DemoServiceImpl.java
    │   └── resources
    │       ├── log4j.properties
    │       └── spring
    │           ├── dubbo-demo-consumer.xml
    │           └── dubbo-demo-provider.xml

provider 的 dubbo-demo-provider.xml 配置为:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
       xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
       http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
    <context:property-placeholder/>

    <dubbo:application name="consul-provider-demo"/>

    <dubbo:registry address="consul://${consul.address:127.0.0.1}:8500"/>

    <dubbo:provider token="true"/>

    <bean id="demoService" class="org.apache.dubbo.samples.consul.impl.DemoServiceImpl"/>

    <dubbo:service interface="org.apache.dubbo.samples.consul.api.DemoService" ref="demoService"/>

</beans>

consumer 的 dubbo-demo-consumer.xml 配置为:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
       xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
       http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
    <context:property-placeholder/>

    <dubbo:application name="consul-consumer-demo"/>

    <dubbo:registry address="consul://${consul.address:127.0.0.1}:8500"/>

    <dubbo:reference scope="remote" id="demoService" check="true" interface="org.apache.dubbo.samples.consul.api.DemoService"/>

</beans>

查看 consumer 中调用 api 的代码,ConsulConsumer 中是通过 xml 配置文件,指定的 demoService 为 DemoServiceImpl:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
public class ConsulConsumer {

    public static void main(String[] args) {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring/dubbo-demo-consumer.xml");
        context.start();
        DemoService demoService = (DemoService) context.getBean("demoService");
        String hello = demoService.sayHello("consul");
        System.out.println(hello);
    }
}

执行以下命令部署测试:

1
2
3
4
5
docker run -p8500:8500 consul:latest
# 部署 provider
./mvnw clean compile exec:java -pl 3-extensions/registry/dubbo-samples-consul -Dexec.mainClass="org.apache.dubbo.samples.ConsulProvider"
# 部署 consumer
./mvnw clean compile exec:java -pl 3-extensions/registry/dubbo-samples-consul -Dexec.mainClass="org.apache.dubbo.samples.ConsulConsumer"

dubbo 接入 nacos

此例是 dubbo 框架直接使用 nacos 做为注册中心,没有接入 k8s 和服务网格。进入测试代码目录,其目录结构为:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
cd 3-extensions/registry/dubbo-samples-nacos/dubbo-samples-nacos-registry
tree -L 10
.
├── pom.xml
├── src
│   ├── main
│   │   ├── java
│   │   │   └── org
│   │   │       └── apache
│   │   │           └── dubbo
│   │   │               └── samples
│   │   │                   ├── ConsumerBootstrap.java
│   │   │                   ├── ProviderBootstrap.java
│   │   │                   ├── action
│   │   │                   │   └── GreetingServiceConsumer.java
│   │   │                   ├── api
│   │   │                   │   └── GreetingService.java
│   │   │                   └── impl
│   │   │                       └── AnnotatedGreetingService.java
│   │   └── resources
│   │       ├── log4j.properties
│   │       └── spring
│   │           ├── dubbo-consumer.properties
│   │           └── dubbo-provider.properties

provider 的 dubbo-provider.properties 配置为:

1
2
3
4
5
dubbo.application.name=nacos-registry-demo-provider
dubbo.registry.address=nacos://${nacos.address:localhost}:8848?username=nacos&password=nacos
dubbo.protocol.name=dubbo
dubbo.protocol.port=20880
dubbo.provider.token=true

consumer 的 dubbo-consumer.properties 配置为:

1
2
3
dubbo.application.name=nacos-registry-demo-consumer
dubbo.registry.address=nacos://${nacos.address:localhost}:8848?username=nacos&password=nacos
dubbo.consumer.timeout=3000

查看 consumer 中调用 api 的代码,greetingService 没有指定具体的 bean,这里是使用 DubboReference 自动注入 AnnotatedGreetingService 的:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
@Component("annotatedConsumer")
public class GreetingServiceConsumer {

    @DubboReference(version = "1.0.0")
    private GreetingService greetingService;

    public String doSayHello(String name) {
        return greetingService.sayHello(name);
    }

}

执行以下命令部署测试:

1
2
3
4
5
docker run --name some-zookeeper -p 2181:2181 --restart always -d zookeeper
# 部署 provider
./mvnw clean compile exec:java -pl 3-extensions/registry/dubbo-samples-nacos/dubbo-samples-nacos-registry -Dexec.mainClass="org.apache.dubbo.samples.ProviderBootstrap"
# 部署 consumer
./mvnw clean compile exec:java -pl 3-extensions/registry/dubbo-samples-nacos/dubbo-samples-nacos-registry -Dexec.mainClass="org.apache.dubbo.samples.ConsumerBootstrap"

dubbo 接入 kubernetes

dubbo 可以直接以 api-server 为注册中心,将 Dubbo 应用部署到 Kubernetes 并复用 Kubernetes Native Service,用例来自 部署到 Kubernetes

服务发现配置说明

provider 的配置文件为如下 dubbo-provider.properties:

1
2
3
4
5
6
7
8
9
dubbo.application.name=dubbo-samples-apiserver-provider  # 当前应用名称
# 应用级服务发现 metadata 为 local,即从 provider 获取时,MetadataService 服务所用的端口号
dubbo.application.metadataServicePort=20885
dubbo.registry.address=N/A  # 注册中心地址设置为 k8s
dubbo.protocol.name=tri     # dubbo 协议
dubbo.protocol.port=20880   # 服务端口
dubbo.application.qosEnable=true    # 是否启用 qos 运维端口
dubbo.application.qosAcceptForeignIp=true   # 是否接收除 localhost 本机访问之外的外部请求
dubbo.provider.token=true   # 令牌验证为 true,表示随机生成动态令牌

consumer 的配置文件 dubbo-consumer.properties 如下:

1
2
3
4
5
6
dubbo.application.name=dubbo-samples-apiserver-consumer
dubbo.application.metadataServicePort=20885
dubbo.registry.address=kubernetes://DEFAULT_MASTER_HOST?registry-type=service&duplicate=false&namespace=dubbo-demo&trustCerts=true&subscribed-services=dubbo-samples-apiserver-provider
dubbo.consumer.timeout=3000
dubbo.application.qosEnable=true
dubbo.application.qosAcceptForeignIp=true

部署测试 demo

Dubbo 项目要访问 apiserver,需要设置对应的权限,这里创建了 Role、RoleBinding、ServiceAccount:

1
2
3
4
5
cd dubbo-samples
# 初始化命名空间和账号
kubectl apply -f 3-extensions/registry/dubbo-samples-kubernetes/dubbo-samples-apiserver-provider/src/main/resources/k8s/ServiceAccount.yml
# 切换命名空间
kubens dubbo-demo

部署 provider:

1
2
3
4
# 部署 Service
kubectl apply -f 3-extensions/registry/dubbo-samples-kubernetes/dubbo-samples-apiserver-provider/src/main/resources/k8s/Service.yml
# 部署 Deployment
kubectl apply -f 3-extensions/registry/dubbo-samples-kubernetes/dubbo-samples-apiserver-provider/src/main/resources/k8s/Deployment.yml

部署 consumer:

1
2
3
4
# 部署 Service
kubectl apply -f 3-extensions/registry/dubbo-samples-kubernetes/dubbo-samples-apiserver-consumer/src/main/resources/k8s/Service.yml
# 部署 Deployment
kubectl apply -f 3-extensions/registry/dubbo-samples-kubernetes/dubbo-samples-apiserver-consumer/src/main/resources/k8s/Deployment.yml

这是分别查看 consumer 和 provider 的日志,可以看到:

1
2
3
4
5
6
# provider
4.0.32:36986 -> /10.44.0.30:20880 is established., dubbo version: 3.1.0, current host: 10.44.0.30
greeting service received: Kubernetes Api Server
# consumer
[16/02/23 06:47:03:003 UTC] main  INFO deploy.DefaultApplicationDeployer:  [DUBBO] Dubbo Application[1.1](dubbo-samples-apiserver-consumer) is ready., dubbo version: 3.1.0, current host: 10.44.0.32
result: hello, Kubernetes Api Server

dubbo 结合 spring boot 使用

Dubbo 的 SPI(Service Provider Interface),用于根据名称获取 Interface 接口的实现类,根据条件激活 Interface 接口的实现类集合,即一组实现类,这是根据 JAVA SPI 扩展而来。这里使用 spring boot 和 zookeeper 注册中心,来简单测试接口方式调用其他服务。

进入测试代码目录,其目录结构为:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
cd dubbo-samples
cd 1-basic/dubbo-samples-spring-boot
tree -L 12
.
├── dubbo-samples-spring-boot-consumer
│   ├── pom.xml
│   ├── src
│   │   ├── main
│   │   │   ├── java
│   │   │   │   └── org
│   │   │   │       └── apache
│   │   │   │           └── dubbo
│   │   │   │               └── springboot
│   │   │   │                   └── demo
│   │   │   │                       └── consumer
│   │   │   │                           ├── ConsumerApplication.java
│   │   │   │                           └── Task.java
│   │   │   └── resources
│   │   │       └── application.yml
├── dubbo-samples-spring-boot-interface
│   ├── pom.xml
│   ├── src
│   │   └── main
│   │       └── java
│   │           └── org
│   │               └── apache
│   │                   └── dubbo
│   │                       └── springboot
│   │                           └── demo
│   │                               └── DemoService.java
├── dubbo-samples-spring-boot-provider
│   ├── pom.xml
│   ├── src
│   │   └── main
│   │       ├── java
│   │       │   └── org
│   │       │       └── apache
│   │       │           └── dubbo
│   │       │               └── springboot
│   │       │                   └── demo
│   │       │                       └── provider
│   │       │                           ├── DemoServiceImpl.java
│   │       │                           └── ProviderApplication.java
│   │       └── resources
│   │           └── application.yml
├── pom.xml

provider 的 application.yml 配置为:

1
2
3
4
5
6
7
8
dubbo:
  application:
    name: dubbo-springboot-demo-provider
  protocol:
    name: dubbo
    port: -1
  registry:
    address: zookeeper://${zookeeper.address:127.0.0.1}:2181

consumer 的 application.yml 配置为:

1
2
3
4
5
6
7
8
dubbo:
  application:
    name: dubbo-springboot-demo-consumer
  protocol:
    name: dubbo
    port: -1
  registry:
    address: zookeeper://${zookeeper.address:127.0.0.1}:2181

查看 consumer 中调用 api 的代码,demoService 没有指定具体的 bean,这里是使用 DubboReference 自动注入 DemoServiceImpl 的:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@Component
public class Task implements CommandLineRunner {
    @DubboReference
    private DemoService demoService;

    @Override
    public void run(String... args) throws Exception {
        String result = demoService.sayHello("world");
        System.out.println("Receive result ======> " + result);

        new Thread(()-> {
            while (true) {
                try {
                    Thread.sleep(1000);
                    System.out.println(new Date() + " Receive result ======> " + demoService.sayHello("world"));
                } catch (InterruptedException e) {
                    e.printStackTrace();
                    Thread.currentThread().interrupt();
                }
            }
        }).start();
    }
}

执行以下命令部署测试:

1
2
3
4
5
6
7
docker run --name some-zookeeper -p 2181:2181 --restart always -d zookeeper
./mvnw clean install -pl 1-basic/dubbo-samples-spring-boot
./mvnw clean install -pl 1-basic/dubbo-samples-spring-boot/dubbo-samples-spring-boot-interface
# 部署 provider
./mvnw clean compile exec:java -pl 1-basic/dubbo-samples-spring-boot/dubbo-samples-spring-boot-provider -Dexec.mainClass="org.apache.dubbo.springboot.demo.provider.ProviderApplication"
# 部署 consumer
./mvnw clean compile exec:java -pl 1-basic/dubbo-samples-spring-boot/dubbo-samples-spring-boot-consumer -Dexec.mainClass="org.apache.dubbo.springboot.demo.consumer.ConsumerApplication"

Dubbo 接入服务网格

Dubbo3 原生支持 mesh 部署,dubbo 应用实例作为数据面组件,支持两种部署模式:

  • Proxy 模式。Dubbo 进程与 Envoy 部署在同一 pod,进出 Dubbo 的流量都经 Envoy 代理拦截,由 Envoy 执行流量管控。
  • Proxyless 模式。Dubbo 进程独立部署,进程间直接通信,通过 xDS 协议与控制面直接交互。

Dubbo proxy 部署

Dubbo 提供了 ThinSDK 的部署模式,在此模式下,Dubbo ThinSDK 将只提供面向业务应用的编程 API、RPC 传输通信能力,其余服务治理 包括地址发现、负载均衡、路由寻址等都统一下沉到 Sidecar,Sidecar 负责与控制面直接通信并接收各种流量管控规则。

服务发现配置说明

provider 的配置文件 dubbo-provider.properties 内容如下,具体字段说明可以在 配置项参考手册 中找到。

1
2
3
4
5
6
7
8
dubbo.application.name=dubbo-samples-mesh-provider  # 当前应用名称
# 应用级服务发现 metadata 为 local,即从 provider 获取时,MetadataService 服务所用的端口号
dubbo.application.metadataServicePort=20885
dubbo.registry.address=N/A  # 注册中心地址,N/A 没有注册到注册中心
dubbo.protocol.name=tri     # triple 协议
dubbo.protocol.port=50052   # 服务端口
dubbo.application.qosEnable=true    # 是否启用 qos 运维端口
dubbo.application.qosAcceptForeignIp=true   # 是否接收除 localhost 本机访问之外的外部请求

consumer 的配置文件 dubbo-consumer.properties 如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
dubbo.application.name=dubbo-samples-mesh-consumer
dubbo.application.metadataServicePort=20885
dubbo.registry.address=N/A
dubbo.protocol.name=tri
dubbo.protocol.port=50052
dubbo.consumer.timeout=30000    # 远程服务调用超时时间(毫秒)
dubbo.application.qosEnable=true
dubbo.application.qosAcceptForeignIp=true
# Dubbo Mesh 模式的开关。开启后,可适配 SideCar 模式,将 Dubbo 服务调用转换为 K8S 标准调用。仅支持 Triple 协议,兼容 GRPC。设置为 true 后,原生对接 K8S,无需第三方注册中心,设置 dubbo.registry.address=N/A 即可
dubbo.consumer.meshEnable=true

部署测试 demo

创建命名空间:

1
2
3
4
# 初始化命名空间 并开启自动注入
kubectl apply -f 3-extensions/registry/dubbo-samples-mesh-k8s/deploy/Namespace.yml
# 切换命名空间
kubens dubbo-demo

部署 provider:

1
2
3
4
# 部署 Service
kubectl apply -f 3-extensions/registry/dubbo-samples-mesh-k8s/deploy/provider/Service.yml
# 部署 Deployment
kubectl apply -f 3-extensions/registry/dubbo-samples-mesh-k8s/deploy/provider/Deployment.yml

部署 consumer:

1
2
3
4
# 部署 Service
kubectl apply -f 3-extensions/registry/dubbo-samples-mesh-k8s/deploy/consumer/Service.yml
# 部署 Deployment
kubectl apply -f 3-extensions/registry/dubbo-samples-mesh-k8s/deploy/consumer/Deployment.yml

查看 consumer pods 的日志:

1
2
3
4
5
[16/02/23 07:52:45:045 UTC] main  INFO deploy.DefaultApplicationDeployer:  [DUBBO] Dubbo Application[1.1](dubbo-samples-mesh-consumer) is ready., dubbo version: 3.1.0, current host: 10.44.0.35
==================== dubbo unary invoke loop started ====================
[16/02/23 07:52:50:050 UTC] main  INFO action.GreetingServiceConsumer: consumer Unary reply <-message: "hello,service mesh, response from provider-v1: 10.44.0.34:50052, client: 10.44.0.34, local: dubbo-samples-mesh-provider, remote: null, isProviderSide: true"

==================== dubbo unary invoke 0 end ====================

此时 consumer sidecar 的日志如下,可以看到 envoy 匹配到了名为“outbound|50052||dubbo-samples-mesh-provider.dubbo-demo.svc.cluster.local”:

1
{"response_code_details":"via_upstream","upstream_cluster":"outbound|50052||dubbo-samples-mesh-provider.dubbo-demo.svc.cluster.local","start_time":"2023-02-16T07:52:50.557Z","authority":"dubbo-samples-mesh-provider.dubbo-demo.svc.cluster.local:50052","method":"POST","downstream_local_address":"10.45.207.12:50052","request_id":"31f42e7a-05c0-4750-b554-b297f76e91fc","user_agent":null,"route_name":"default","downstream_remote_address":"10.44.0.35:55540","bytes_received":19,"connection_termination_details":null,"response_flags":"-","upstream_transport_failure_reason":null,"response_code":200,"upstream_local_address":"10.44.0.35:35986","upstream_service_time":"230","duration":274,"path":"/org.apache.dubbo.samples.Greeter/greet","x_forwarded_for":null,"bytes_sent":163,"requested_server_name":null,"protocol":"HTTP/2","upstream_host":"10.44.0.34:50052"}

查看 provider pod 的日志:

1
2
3
[16/02/23 07:28:49:049 UTC] main  INFO deploy.DefaultApplicationDeployer:  [DUBBO] Dubbo Application[1.1](dubbo-samples-mesh-provider) is ready., dubbo version: 3.1.0, current host: 10.44.0.34
=============== dubbo service started ===============
[16/02/23 07:52:50:050 UTC] tri-protocol-50052-thread-1  INFO impl.GreeterImpl: Server test dubbo tri mesh received greet request name: "service mesh"

proto 编译

这个项目中使用的是 triple 协议,triple 协议是 Dubbo3 推出的主力协议,这个协议兼容 gRPC ,以 HTTP2 作为传输层构建新的协议。这里测试将 proto 文件编译为 java 文件,方便项目中查看。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
cd 3-extensions/registry/dubbo-samples-mesh-k8s/dubbo-samples-mesh-provider
mvn clean compile
## 输出
[INFO] --- protobuf-maven-plugin:0.6.1:compile (default) @ dubbo-samples-mesh-provider ---
[INFO] Building protoc plugin: dubbo
[INFO] Compiling 1 proto file(s) to /xx/dubbo-samples/3-extensions/registry/dubbo-samples-mesh-k8s/dubbo-samples-mesh-provider/target/generated-sources/protobuf/java
[INFO]
[INFO] --- protobuf-maven-plugin:0.6.1:compile-custom (default) @ dubbo-samples-mesh-provider ---
[INFO] Building protoc plugin: dubbo
[INFO] Compiling 1 proto file(s) to /xx/dubbo-samples/3-extensions/registry/dubbo-samples-mesh-k8s/dubbo-samples-mesh-provider/target/generated-sources/protobuf/grpc-java

可以看到编译生成的 java 文件在“target/generated-sources/protobuf“,进入此目录后查看:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
➜  protobuf git:(master) ✗ tree -L 6
.
├── grpc-java
│   └── org
│       └── apache
│           └── dubbo
│               └── samples
│                   └── GreeterGrpc.java
└── java
    └── org
        └── apache
            └── dubbo
                └── samples
                    ├── DubboGreeterTriple.java
                    ├── Greeter.java
                    ├── GreeterOuterClass.java
                    ├── GreeterReply.java
                    ├── GreeterReplyOrBuilder.java
                    ├── GreeterRequest.java
                    └── GreeterRequestOrBuilder.java

dubbo Proxyless 部署

Dubbo 3.1 版本添加了 Proxyless Mesh,Proxyless 模式是指 dubbo 直接与 istiod 通信,实现 dubbo 与 Control Plane 的直接通信,进而实现控制面对流量管控、服务治理、可观测性、安全等的统一管控,规避 sidecar 模式带来的性能损耗与部署架构复杂性。

优势和缺点

优势:

  • 没有额外的 Proxy 中转损耗,因此更适用于性能敏感应用
  • 更有利于遗留系统的平滑迁移
  • 架构简单,容易运维部署
  • 适用于几乎所有的部署环境

缺点:

  • 无法获取接口所对应的应用名:需要配置 providedBy 来标记此服务来自哪个应用
  • Istio 认证方式限制:jwtPolicy 需要设置为 first-party-jwt,即没有过期时间,需要安装到所有 pods
  • 只支持 http 协议和 grpc 协议, Proxyless 模式下应用级服务发现通过 Kubernetes Native Service 来进行应用服务发现,由于 istio 的限制,目前只支持 http 协议和 grpc 协议的流量拦截转发

服务发现配置说明

provider 的配置文件为如下 dubbo-provider.properties:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
dubbo.application.name=dubbo-samples-xds-provider   # 当前应用名称
# 应用级服务发现 metadataType 为 local,即从 provider 获取时,MetadataService 服务所用的端口号
dubbo.application.metadataServicePort=20885
# metadataType 配置为 local,则该属性设置 MetadataService 服务所用的通信协议,默认为 dubbo
dubbo.application.metadataServiceProtocol=dubbo
dubbo.registry.address=xds://istiod.istio-system.svc:15012  # 注册中心
dubbo.protocol.name=tri
dubbo.protocol.port=50051
dubbo.application.qosEnable=true
dubbo.application.qosAcceptForeignIp=true

consumer 的配置文件 dubbo-consumer.properties 如下:

1
2
3
4
5
6
7
8
dubbo.application.name=dubbo-samples-xds-consumer
dubbo.application.metadataServicePort=20885
dubbo.application.metadataServiceProtocol=dubbo
dubbo.registry.address=xds://istiod.istio-system.svc:15012
dubbo.consumer.timeout=3000
dubbo.consumer.check=false
dubbo.application.qosEnable=true
dubbo.application.qosAcceptForeignIp=true

参考