Dubbo框架微服务开发
从编程开发的角度来说,Dubbo首先是一款RPC服务框架,它最大的优势在于提供了面向接口代理的服务编程模型,对开发者屏蔽了底层的远程通信细节。同时Dubbo也是一款服务治理框架,它为分布式部署的微服务提供了服务发现、流量调度等服务治理解决方案。
最佳实践概述
本次最佳实践主要基于Apache Dubbo框架开发微服务,及描述Apache Dubbo开发微服务的优势,指导传统服务开发到微服务的改造变得必要。最后将详细描述微服务开发过程,对不同的层面进行字面和代码示例方式,指导基于Apache Dubbo微服务开发。同时选择Nacos为注册中心并融入Nacos的配置管理功能,使微服务功能适应多样化的需求。
最佳实践价值
本次最佳实践基于Nacos为注册中心开发的Dubbo微服务,可以无代码修改的迁移至EDAS。微服务托管至EDAS后,您只需要关注Dubbo应用自身的逻辑,无需关注注册中心、配置中心和元数据中心的搭建和维护。托管后还可以使用EDAS提供的弹性伸缩、限流降级、监控及微服务治理能力,而且整个托管过程对您来说是完全透明的,不会增加理解和开发成本。
Apache Dubbo框架来源
在大规模服务化之前,应用可能只是通过RMI或Hessian等工具,简单的暴露和引用远程服务,通过配置服务的URL地址进行调用,通过F5等硬件进行负载均衡。
当服务越来越多时,服务URL配置管理变得非常困难,F5硬件负载均衡器的单点压力也越来越大。此时需要一个服务注册中心,动态地注册和发现服务,使服务的位置透明。并通过在消费方获取服务提供方地址列表,实现软负载均衡和Failover,降低对F5硬件负载均衡器的依赖,也能减少部分成本。
接着,服务的调用量越来越大,服务的容量问题就暴露出来,这个服务需要多少机器支撑?什么时候该加机器?为了解决这些问题,第一步,要将服务现在每天的调用量,响应时间,都统计出来,作为容量规划的参考指标。其次,要可以动态调整权重,在线上,将某台机器的权重一直加大,并在加大的过程中记录响应时间的变化,直到响应时间到达阈值,记录此时的访问量,再以此访问量乘以机器数反推总容量。
Apache Dubbo是一款高性能的RPC框架。简单来说服务提供者向注册中心注册自己所提供的服务,服务消费者向注册中心订阅自己所需的服务,基于软负载均衡算法向其中一个服务提供者发起服务调用。以上的问题,正是Dubbo设计的源泉,并很好的解决了上述问题。
Apache Dubbo介绍及准备
产品介绍节点角色说明
节点 | 角色说明 |
Provider | 暴露服务的服务提供方 |
Consumer | 调用远程服务的服务消费方 |
Registry | 服务注册与发现的注册中心 |
Monitor | 统计服务的调用次数和调用时间的监控中心 |
Container | 服务运行容器 |
调用关系说明
服务容器负责启动,加载,运行服务提供者。
服务提供者在启动时,向注册中心注册自己提供的服务。
服务消费者在启动时,向注册中心订阅自己所需的服务。
注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。
服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。
服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。
环境准备流程
在进行开发前,需要准备一下基本内容:
JDK基础运行环境:正确安装JDK 7+,正确配置JAVA_HOME环境变量。
Maven环境及构建Apache Dubbo Maven工程;添加打Jar包与Dubbo开发编译依赖。
开发IDE:推荐Eclipse或IDEA。
Eclipse配置:Tomcat插件。
IDEA:配置Tomcat。
注册中心:Apache Dubbo服务的发布与订阅。
微服务开发选用SpringBoot
Spring Boot 是一个真正的游戏改变者。Spring Boot是一个构建在Spring 框架顶部的项目,它提供了一种更简单、更快捷的方式来设置、配置和运行简单的基于Web的应用程序。
在过去Spring框架中,我们需要为应用配置所有的内容,会有许多配置文件,例如XML或元注释,这是Spring Boot解决的主要问题之一,基本无需XML配置了,都使用@注释。
Spring boot巧妙地根据我们选择的依赖配置,可以自动启动我们想要的所有功能,并且只需单击一下即可启动应用程序。此外,它还简化了应用程序的部署过程。
Spring Boot还有很多功能特点:
自动配置:在启动时检测到框架将自动配置,如JDBC。
Starter:帮助项目启动,自动添加启动项目依赖项。
实现微服务:提供REST风格API暴露微服务与客户端交互。
自定义配置:通过配置文件来实现各个组件的基本配置。
模块化:一个Spring Boot应用是一个微服务,相当于一个模块,多模块开发后使用Spring Cloud实现动态访问与监控再使用分布式运行,累计扩大规模。
独立打包:一个Spring Boot应用独立设计,生产级质量的应用,通过简单的配置和部署嵌入式Web服务器。
内嵌服务器:默认是Tomcat,可支持Jetty、undertow。
面向接口代理的透明服务开发框架
我们从Dubbo是一个微服务开发框架这个大家熟知的概念开始。就像 Spring是开发Java应用的基础框架一样,我们经常会选用Dubbo作为开发微服务业的基础框架。
Dubbo 框架的最大优势就在于其面向接口的编程模型,使得开发远程服务调用就像开发本地服务一样。这次示例代码使用Spring Boot开发Dubbo微服务应用。
融入Nacos成为注册中心
Dubbo融合Nacos成为注册中心的操作步骤非常简单,大致步骤可分为“增加Maven依赖”以及“配置注册中心”。
增加Maven依赖,导下面依赖包即可,不需要导dubbo-registry-nacos包。
<dependency> <groupId>com.alibaba.nacos</groupId> <artifactId>nacos-client</artifactId> <version>1.1.1</version> </dependency>
配置注册中心。
dubbo.application.name=dubbo-consumer dubbo.registry.address=nacos://127.0.0.1:8848
创建服务提供者
在创建好的Maven文件中添加所需要的依赖。
<dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>2.0.6.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-actuator</artifactId> </dependency> <dependency> <groupId>org.apache.dubbo</groupId> <artifactId>dubbo-spring-boot-starter</artifactId> <version>2.7.3</version> </dependency> <dependency> <groupId>com.alibaba.nacos</groupId> <artifactId>nacos-client</artifactId> <version>1.1.1</version> </dependency> </dependencies>
开发Dubbo服务提供者。
Dubbo中服务都是以接口的形式提供的。
定义服务接口:
public interface EchoService { String echo(String string); String echoDubboMix(int id); String echoMQConsumer(String str); }
编写接口实现类:
import com.alibaba.dubbo.config.annotation.Service; import com.alibaba.edas.boot.dao.EchoDao; import com.alibaba.edas.boot.rocketmq.SimpleMQConsumer; import com.alibaba.edas.boot.rocketmq.SimpleMQProduce; import com.alibaba.edas.boot.service.EchoService; import org.springframework.beans.factory.annotation.Autowired; @Service public class EchoServiceImpl implements EchoService { @Autowired private EchoDao echoDao; @Autowired private SimpleMQConsumer simpleMQConsumer; @Autowired private SimpleMQProduce simpleMQProduce; public String echo(String str) { return "welcome --" + str; } public String echoDubboMix(int id) { //写消息 simpleMQProduce.sendMsg(id+""); return echoDao.findById(id).getUserName(); } public String echoMQConsumer(String str) { //订阅消息 simpleMQConsumer.receive(); return str; } }
配置Dubbo服务。
dubbo.scan.basePackages=com.alibaba.edas.boot dubbo.application.name=dubbo-provider-demo dubbo.registry.address=nacos://127.0.0.1:8848 dubbo.protocol.name=dubbo dubbo.protocol.port=-1
开发Spring Boot入口类。
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class DubboProviderApplication { public static void main(String[] args) throws InterruptedException { SpringApplication.run(DubboProviderApplication.class, args); } }
创建服务消费者
在创建好的Maven文件中添加所需要的依赖。
<dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>2.0.6.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-actuator</artifactId> </dependency> <dependency> <groupId>org.apache.dubbo</groupId> <artifactId>dubbo-spring-boot-starter</artifactId> <version>2.7.3</version> </dependency> <dependency> <groupId>com.alibaba.nacos</groupId> <artifactId>nacos-client</artifactId> <version>1.1.1</version> </dependency> </dependencies>
开发Dubbo服务消费者。
Dubbo中服务都是以接口的形式提供的。
定义服务接口:
public interface EchoService { String echo(String string); String echoDubboMix(int id); String echoMQConsumer(String str); }
开发Dubbo服务调用。
import com.alibaba.dubbo.config.annotation.Reference; import com.alibaba.edas.boot.service.EchoService; import com.alibaba.edas.boot.service.MiddleService; import com.alibaba.nacos.api.config.annotation.NacosValue; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.web.bind.annotation.*; @RestController @RequestMapping(value = "/poc") @Api(description = "DUBBO-POC功能测试接口") public class ConsumerController { @Reference private EchoService echoService; @Reference private MiddleService middleService; @ApiOperation(value = "获取服务者返回信息 A->C") @RequestMapping(value = "/dubbo-echo-mid", method = RequestMethod.GET) public String echo(@RequestParam("str") String str) { return echoService.echo(str) + "\r\n"; } @ApiOperation(value = "通过ID查询数据库获取返回信息、RocketMQ写信息 A->C") @RequestMapping(value = "/dubbo-echo-mix", method = RequestMethod.GET) public String echoDubboMix(@RequestParam("id") int id) { return echoService.echoDubboMix(id) + "\r\n"; } @ApiOperation(value = "RocketMQ订阅消息 A->C") @RequestMapping(value = "/dubbo-echo-mq", method = RequestMethod.GET) public String echoMQConsumer(@RequestParam("str") String str) { return echoService.echoMQConsumer(str) + "\r\n"; } @ApiOperation(value = "获取版本信息") @RequestMapping(value = "/echo-version", method = RequestMethod.GET) public String echoVersion() { return "This is dubbo spring boot version old" + "\r\n"; } }
在application.properties配置文件中新增一下配置。
#spring.application.name=spring-boot-consumer dubbo.application.name=dubbo-consumer-demo dubbo.registry.address=nacos://127.0.0.1:8848
开发Spring Boot入口类。
import com.alibaba.nacos.spring.context.annotation.config.NacosPropertySource; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class DubboConsumerApplication { public static void main(String[] args) { SpringApplication.run(DubboConsumerApplication.class, args); } }
融入Nacos配置管理功能
在上述consumer工程中的pom.xml添加依赖。
<!-- 导入Nacos配置管理依赖包 --> <dependency> <groupId>com.alibaba.boot</groupId> <artifactId>nacos-config-spring-boot-starter</artifactId> <version>0.2.1</version> </dependency> <dependency> <groupId>com.alibaba.boot</groupId> <artifactId>nacos-config-spring-boot-actuator</artifactId> <version>0.2.1</version> </dependency>
在application.properties中配置Nacos server的地址。
nacos.config.server-addr=127.0.0.1:8848
使用@NacosPropertySource加载dataId为example的配置源,并开启自动更新。
import com.alibaba.nacos.spring.context.annotation.config.NacosPropertySource; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication @NacosPropertySource(dataId = "nacos", autoRefreshed = true) public class DubboConsumerApplication { public static void main(String[] args) { SpringApplication.run(DubboConsumerApplication.class, args); } }
通过Nacos的@NacosValue注解设置属性值。
@RestController @RequestMapping(value = "/poc") @Api(description = "DUBBO-POC功能测试接口") public class ConsumerController { @NacosValue(value = "${useLocalCache:false}", autoRefreshed = true) private String useLocalCache; @ApiOperation(value = "全局参数配置") @RequestMapping(value = "/echo-acm", method = RequestMethod.GET) public String echoAcm() { return "配置文件中的value值:" + useLocalCache + "\r\n"; } }