无需改造 dubbo sdk,无需更换 dubbo 协议,直接使用 istio 治理 dubbo 流量。这是史上最简单的改造方法。
step 1. 改造 provider
去掉 registry 配置,让 provider 变成一个纯纯的 dubbo 应用。
修改配置,三个false,address 随便写一个字符串(因为他不能为空):
<beans> <dubbo:application name="hello-dubbo-provider"/> <dubbo:protocol name="dubbo" port="20880" /> <dubbo:registry register="false" subscribe="false" check="false" address="none" /> <!--<dubbo:registry address="zookeeper://zk.dubbo:2181" client="curator" />--> <bean id="demoService" class="tencent.demo.provider.DemoServiceImpl"/> <dubbo:service interface="tencent.demo.DemoService" ref="demoService" /> </beans>
先在本地启动它。
step 2. 改造 consumer
去掉 registry 配置,让 consumer 变成一个傻傻的 dubbo 应用。
手工指定 service 的服务地址,当然了,要把他变成你部署在 istio 中的服务名 url="dubbo://hello-dubbo-provider:20880"
。
<beans> <dubbo:application name="demo-consumer"/> <dubbo:registry address="none" register="false" subscribe="false" check="false" /> <!--<dubbo:registry address="zookeeper://zk.dubbo:2181" client="curator" />--> <dubbo:reference id="demoService" check="false" interface="tencent.demo.DemoService" url="dubbo://hello-dubbo-provider:20880" /> </beans>
在 hosts 中映射一下。
127.0.0.1 hello-dubbo-provider
启动 consumer,不出意外,完美运行。
上面的对 dubbo 的改造其实是在使用 dubbo 的调试功能,但他恰恰是 istio 需要的效果。
step 3. 部署到 istio 中
在低版本的 istio 中,控制面无法解析。需要配置 EnvoyFilter。 但配了半天,完全不通 。干脆装个 1.6 玩玩。
经过实验,在 istio 1.6.1 中,基于 tcp 服务治理的 dubbo mesh 直接启动成功。
以下是实验过程:示例中的镜像地址目前是公开可测的。
1 创建 ns
apiVersion: v1 kind: Namespace metadata: name: dubbo labels: istio-injection: enabled spec: finalizers: - kubernetes
2 创建 provider 的部署集
apiVersion: apps/v1 kind: Deployment metadata: name: hello-dubbo-provider namespace: dubbo labels: app: hello-dubbo-provider version: v1 spec: replicas: 1 selector: matchLabels: app: hello-dubbo-provider version: v1 template: metadata: labels: app: hello-dubbo-provider version: v1 spec: containers: - name: hello-dubbo-provider image: tencent-cloud-one-docker.pkg.coding.net/xyz-demo/images/hello-dubbo-provider:1.0.4 command: ["java","-jar","hello-dubbo-provider-fat.jar"] ports: - containerPort: 20880 protocol: TCP --- # 部署 hello-dubbo-provider v2 apiVersion: apps/v1 kind: Deployment metadata: name: hello-dubbo-provider-v2 namespace: dubbo labels: app: hello-dubbo-provider version: v2 spec: replicas: 1 selector: matchLabels: app: hello-dubbo-provider version: v2 template: metadata: labels: app: hello-dubbo-provider version: v2 spec: containers: - name: hello-dubbo-provider image: tencent-cloud-one-docker.pkg.coding.net/xyz-demo/images/hello-dubbo-provider:2.0.0 command: ["java","-jar","hello-dubbo-provider-fat.jar"] ports: - containerPort: 20880 protocol: TCP
3 创建 service
apiVersion: v1 kind: Service metadata: name: hello-dubbo-provider namespace: dubbo labels: name: hello-dubbo-provider spec: ports: - name: dubbo-rpc protocol: TCP port: 20880 targetPort: 20880 selector: app: hello-dubbo-provider
4 创建 consumer 部署
apiVersion: apps/v1 kind: Deployment metadata: name: hello-dubbo-consumer namespace: dubbo labels: app: hello-dubbo-consumer version: v1 spec: replicas: 10 selector: matchLabels: app: hello-dubbo-consumer version: v1 template: metadata: labels: app: hello-dubbo-consumer version: v1 spec: containers: - name: hello-dubbo-consumer image: tencent-cloud-one-docker.pkg.coding.net/xyz-demo/images/hello-dubbo-consumer:1.0.3 command: ["java","-jar","hello-dubbo-consumer-fat.jar"]
5 流量/灰度控制
apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: hello-vs namespace: dubbo spec: hosts: - hello-dubbo-provider tcp: - route: - destination: host: hello-dubbo-provider port: number: 20880 subset: v1 weight: 20 - destination: host: hello-dubbo-provider port: number: 20880 subset: v2 weight: 80 --- apiVersion: networking.istio.io/v1alpha3 kind: DestinationRule metadata: name: hello-subset namespace: dubbo spec: host: hello-dubbo-provider subsets: - name: v1 labels: version: v1 - name: v2 labels: version: v2
测试结果
部署完成,查看 consumer 的各个 pod 的 log。会发现,少量 consumer 打印了 hello-dubbo-provider:v1 的结果。
2020-06-10T10:58:22.870417943Z Hello 哈哈, V1 @ 2020-06-10 10:58:22 @ 172.24.0.136 2020-06-10T10:58:27.872374594Z Hello 哈哈, V1 @ 2020-06-10 10:58:27 @ 172.24.0.136 2020-06-10T10:58:32.874072253Z Hello 哈哈, V1 @ 2020-06-10 10:58:32 @ 172.24.0.136
v2 的结果的比较多:
2020-06-10T11:00:32.625814149Z 你好世界, 版本 2 升级了这个提示 哈哈, V2 @ 2020-06-10 11:00:32 @ 172.24.0.7 2020-06-10T11:00:37.638914148Z 你好世界, 版本 2 升级了这个提示 哈哈, V2 @ 2020-06-10 11:00:37 @ 172.24.0.7 2020-06-10T11:00:42.635862572Z 你好世界, 版本 2 升级了这个提示 哈哈, V2 @ 2020-06-10 11:00:42 @ 172.24.0.7
调整 vs 的百分比,重启 pod(因为长连接,所以重启),看看他是不是按照指挥来调度。
另外可以使用如下的命令多次执行 consumer 进行验证:
kubectl exec -n dubbo hello-dubbo-consumer-855fcb7878-5qcb4 -- java -jar hello-dubbo-consumer-fat.jar
在 kiali 中,也能看到流量的监控图表。
more: 改造成 http 协议
dubbo 可以通过简单的注册文件的修改,就可以完成通信协议的改变。
依赖包大概需要增加:
<dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>4.0.1</version> </dependency> <dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-core</artifactId> <version>9.0.36</version> </dependency> <dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-server</artifactId> <version>9.4.29.v20200521</version> </dependency> <dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-servlet</artifactId> <version>9.4.29.v20200521</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>5.2.6.RELEASE</version> </dependency> <dependency> <groupId>com.github.briandilley.jsonrpc4j</groupId> <artifactId>jsonrpc4j</artifactId> <version>1.2.0</version> </dependency>
provider 的配置修改
<dubbo:protocol name="http" id="http" port="20880" server="jetty"/>
consumer 的配置修改
<dubbo:reference id="demoService" check="false" interface="tencent.demo.DemoService" url="http://hello-dubbo-provider:20880" />
修改通信协议之后,程序的行为基本不变,只是每次访问改成了 http,会每次重新连接。
而对于 istio,现在可以通过 接口名称 来进行流量治理了。因为,他的服务的接口名现在放在 url 中了。
下面就是一个访问的示例:
http://hello-dubbo-provider:20880/tencent.demo.DemoService?application=demo-consumer&check=false&init=false&interface=tencent.demo.DemoService&pid=74873®ister.ip=192.168.1.15&remote.application=&side=consumer&sticky=false
在 VirtualService 中,即可 通过 uri 匹配 "tencent.demo.DemoService" 来进行服务治理了。
附:dubbo 的 java 代码
Provider。版本 1 和 2 分别打印了不同的内容。
public String sayHello(String name) { String myHost = ""; try { InetAddress inetAddress = InetAddress.getLocalHost(); myHost = inetAddress.getHostAddress(); } catch (UnknownHostException e) { e.printStackTrace(); } Date date = new Date(); DateFormat format = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); String str = format.format(date); return "你好世界, 版本 2 升级了这个提示 " + name + ", V2 @ " + str + " @ " + myHost ; }
consumer 每 5 秒调用一次:
public static void main(String[] args) throws Exception { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"META-INF/spring/consumer.xml"}); context.start(); DemoService demoService = (DemoService)context.getBean("demoService"); while(true) { String hello = demoService.sayHello("哈哈"); System.out.println(hello); Thread.sleep(5 * 1000); } }
总结
使用了最简单的方法,将 dubbo 的服务发现和治理功能去掉,保留了他的 rpc 功能,并通过与 istio 一致的部署方法进行服务部署和 TCP 流量操控。
但现在基于 istio 本身的调用链还没有看到,基于内容的流量操控还待继续探索。
参考:
dubbo:registry
dubbo:reference
合智互联客户成功服务热线:400-1565-661
留言评论
暂无留言