随着微服务应用架构的兴起,当前很多用户在开发测试生产上已经采用微服务的理念进行应用的架构设计及部署。常用的框架比如dubbo,springcloud等都已经在大规模进行使用了。当前kubernetes云原生应用的最佳部署平台,如何将线下的微服务应用迁移到kubernetes成为用户的一个难题,本文将以springboot+dubbo为例进行迁移的方案介绍。
1 典型的spring+dubbo例子
1.1 环境及工具
运行环境:JDK 8,Maven 3.3
技术栈:springboot 2.0,dubbo 2.6,zookeeper 3.3
工具:IntelliJ IDEA
1.2 Springboot快速集成dubbo的挂件依赖
Dubbo采用全Spring配置方式,透明化接入应用,对应用没有任何API侵入,只需用Spring加载Dubbo的配置即可,Dubbo基于Spring的Schema扩展进行加载。
本例中dubbo采用zookeeper作为注册中心。Dubbo及zookeeper的安装方式请参考官方指导。
<dependency>
<groupId>com.alibaba.boot</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>0.2.0</version>
</dependency>
1.3 服务提供者和消费者示例代码
1.3.1 dubbo服务注册及消费流程
在使用dubbo的时候需要清除服务提供者(provider)和服务消费者(consumer)。流程如下:
1. 服务提供者在服务启动的时候向注册中心注册自己提供的服务;
2. 服务消费者在启动的时候向注册中心注册自己所需的服务;
3. 注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者;
4. 服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用;
5. 服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。
1.3.2 目录结构
Dubbo-api里面定义了服务接口,由服务提供者和服务消费者共同调用;
Dubbo-consumer中定义了一个提供外部url访问的类,并且在该类中实现了从dubbo中的消费接口。
Dubbo-provider中定义了向dubbo注册的服务。
1.3.3 定义服务接口
定义的服务接口在服务提供者和服务消费者*同使用。
1.3.4 服务提供方
在服务提供方实现服务接口,该接口的实现方式对消费者是隐藏的。简单来说就是将上面接口的实现方法(称之为服务)注册到zookeeper上,并暴露端口供其他消费者消费。@Service里面的一些信息就是服务具体的注册地址。
服务提供方与dubbo的配置如下;
1.3.5 服务消费方
服务消费方主要完成服务接口的调用,调用方式与本地调用是一样的,但是服务的地址来自于注册在dubbo上的远程地址。
服务消费方的配置与服务提供方的配置基本一致:
1.3.6 启动服务提供者和服务消费者
在本示例中,服务提供者接收到调用请求会返回 "Hello, " + 传入的字符串 + " (from Spring Boot)"。服务消费者会提供一个url访问方式,并在url中获取调用服务使用的字符串。
操作:
1、运行dubbo-provider中的DemoServiceImpl和dubbo-consumer中的DemoConsumerController两个类;
2、此时服务消费方提供一个url访问接口,在浏览器中输入http://localhost:9091/sayHello/HelloWorld
2 迁移到kubernetes的方案
2.1 dubbo注册中心部署
dubbo的注册中心有很多种,主流的用法是将zookeeper作为dubbo的注册中心。Dubbo的注册中心可以放在集群内部部署也可以放在集群外部部署。
在这里考虑到注册中心是有状态的服务,我们可以在kubernetes上部署,也可以在集群外的ECS上部署。
2.1.1 在集群外部部署
如果dubbo部署在集群之外,需要集群中的部署的应用(服务提供者和服务消费者)需要能够访问dubbo所在的网络即可。
2.1.2 在集群内部部署
如果dubbo部署在集群内部需要做以下事情:
i. 制作dubbo的相关镜像并部署在kubernetes平台;
ii. 为dubbo应用创建service,可以为clusterIP和LoadBalancer类型,如果用到LoadBalancer类型,可以创建内网slb;
iii. 应用可以通过dubbo的service name、clusterIP或者内网SLB地址进行访问。
2.2 服务提供者和服务消费者全部在集群内调用
应用改造及部署
在该种情况下,应用不需要进行改造,在application.properties文件中需要更改下dubbo.registry.address中dubbo的地址。如下图:
同时在该种情况下,应用不需要关心自己注册到dubbo中的地址,因为在同一个集群中所有的pod地址默认是通的,并且该默认情况下,应用会将pod的地址作为注册地址。
2.3 服务提供者需要提供服务给集群外部的服务消费者
2.3.1 服务提供者与kubernetes集群都部署在阿里云上
2.3.1.1 在同一VPC中
如果服务消费者与kubernetes集群在同一个VPC,那么只需要将将两者放到一个安全组中,保证能够互相访问即可。此时,部署在kubernetes集群上的应用是将pod IP地址注册在dubbo上。
注意,此时pod的IP地址规划不能与其他VPC环境的IP段冲突。2.3.1.2 在不同VPC中或线下IDC
如果服务消费者与kubernetes集群不在同一个VPC中,则需要先打通两者的VPC环境,使两方的应用能够互通即可,显现IDC同理。此时,部署在kubernetes集群上的应用也是将pod IP地址注册在dubbo上。
注意,此时pod的IP地址规划不能与其他VPC环境或者线下IDC环境的IP段冲突。
2.3.2 线下IDC内网(无法与VPC打通)应用改造及部署
首先,在该种情况下,应用不需要进行改造,在application.properties文件中需要更改下dubbo.registry.address中dubbo的地址。如果dubbo部署在集群内,应用应该根据情况填写能够访问到的地址。
其次,在部署应用前,需要先为该应用创建外网LoadBalancer类型的service,以便先获取到外网SLB的地址,在下面注册地址到dubbo的时候需要用。
最后,由于存在集群外部的应用交互调用,所以作为服务提供者不能使用pod地址,需要使用外网LoadBalancer类型service的地址。需要在application.properties中进行注册IP地址的更改。
以上两步如下图所示:参考文档:
本文中使用的代码见GitHub:https://github.com/xiaoze-smirk/dubbo-springboot