大白配小猪 2020-04-20
官网: http://dubbo.apache.org/zh-cn/index.html
Dubbo是阿里巴巴的开源RPC组件,底层使用Hessian和Netty做的序列化和传输。因阿里巴巴的内部原因Dubbo停止更新了一段时间,错失了一段大好的市场推广机会,虽然后面重启了开源维护计划,但是因这段时间其它的RPC组件的不断更新和优化抢占了不少的市场,虽然后面阿里巴巴将Dubbo移交到了Apache开源软件基金会,但是依然感觉后劲不足,阿里巴巴为了完善自己在开源领域的技术设想,逐渐的开源了一系列的组件来为自己在开源领域打气,如Nacos等。值得肯定的是阿里巴巴在最近几年间对外的人员输出和在开源力度上的大力支持,感觉阿里系的开源组件逐渐受到了大众的接收。当然这个也是SpringBoot和SpringCloud开源组件的一些弊端,总结一句话阿里巴巴开源的Dubbo不是为了和Spring系列的开源产品竞争,而是在打造一套符合国内技术特点的开源选择方案。
Dubbo是一个RPC,既然是RPC那就是分布式远程的数据交互,分布式就涉及到了服务的发现和管理,在Dubbo中有这样的几个核心概念,分别是应用发现、服务注册、服务调用。
应用发现:Dubbo提供了3种常见的注册方式Redis、Zookeeper、Nacos,其中大家使用率最高的就是Zookeeper,这个其实也是历史原因,因为当时官网上就提供了Zookeeper的注册说明。当使用Dubbo的应用将服务注册到了Zookeeper上面以后,其它服务既可以通过ZK发现已经注册的服务提供者。
服务注册: 在这个地方我觉得举个例子来讲比较的方便理解,在真是的应用中,例如账户服务的应用提供了一个AccountLoginService的实现,那么Dubbo就会获取到这几个属性信息,1、当前接口所在的应用名称;2当前接口的全限定名称;3这个接口对应的ID(类似AccountLoginService)的一个别名,这个ID必须唯一。这些信息是怎么来的呢,其实很简单,通过包扫描获取到的,Dubbo提供了基于注解和配置XML的方式来显式的声明服务。
服务调用: 服务调用上,Dubbo为了简化调用方式,也做了类似服务注册的这样的工作,也提供了基于注解和显式XML配置的方式来发现服务并调用,服务调用就涉及到了数据的交换,在通过对Dubbo的源码上的分析,Dubbo集成的Hessian序列化功能就是做的这个事情,它将数据对象(一切皆对象)序列化为字节码的码流,通过在ZK上发现了应用上找到对应的服务提供者,然后反序列化(ZK上不只是存储了注册的应用名称,还有当前应用提供的服务,使用KV的形式存储的)。这样就传递了数据。
注意:原则上服务提供者提供的服务的ID是唯一的,但是真实 应用场景中,ID重复的情况时有发生,Dubbo通过应用名称+ID的双重判断来避免这一情况的发生,但是我们在编码过程中应尽力避免ID重复的情况。另外,DUbbo传输的数据对象必须是有序列化的对象。
1) Maven的依赖
<dependency> <groupId>org.apache.curator</groupId> <artifactId>curator-framework</artifactId> </dependency> <dependency> <groupId>org.apache.curator</groupId> <artifactId>curator-recipes</artifactId> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>dubbo</artifactId> </dependency> <dependency> <groupId>org.apache.zookeeper</groupId> <artifactId>zookeeper</artifactId> <exclusions> <exclusion> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> </exclusion> </exclusions> </dependency>
2) JDK
Jdk1.8
3) Zookeeper/NacosServer
安装好Zookeeper或者NacosServer(Ali系的服务发现和治理工具这里面功能很多)
注意:使用NacosServer的用户需要引入依赖:
<dependency> <groupId>org.apache.dubbo</groupId> <artifactId>dubbo-registry-nacos</artifactId> </dependency> <dependency> <groupId>com.alibaba.nacos</groupId> <artifactId>nacos-client</artifactId> </dependency>
因为网上Dubbo和Zookeeper的整合方式已经很完善了,这里就不过多的渲染,主要说和Nacos的整合。另外考虑到在大多数的情况下企业中的项目结构是这样的:
dubbo-demo-parent //顶级的POM项目 dubbo-demo-framework-core //模块依赖 dubbo-demo-service-app1 //真实的应用1 dubbo-demo-service-app2 //真实的应用2
所以我们这次整合主要说一下这样的一个项目结构下我们怎么做的一次配置多个应用都可以使用,又可以按照自己的应用特点去定制一些参数。
<dependency> <groupId>com.alibaba.spring.boot</groupId> <artifactId>dubbo-spring-boot-starter</artifactId> </dependency> <dependency> <groupId>com.101tec</groupId> <artifactId>zkclient</artifactId> </dependency>
在application.yml中的服务提供者的配置一般是这样的
server: port: 8090 dubbo: application: name: shop-boot-console registry: address: nacos://nacos.didispace.com:80 protocol: name: dubbo port: 20881 scan: base-packages: com.shop.console.service.impl
消费者:
server: port: 9099 spring: mvc: date-format: yyyy-MM-dd jackson: date-format: yyyy-MM-dd HH:mm:ss time-zone: GMT+8 dubbo: application: name: shop-boot-portal #生产者专有 protocol: name: dubbo port: 20881 #生产者专有 scan: base-packages: com.shop.portal registry: # address: zookeeper://127.0.0.1:2181 address: nacos://nacos.didispace.com:80 consumer: timeout: 5000
使用服务就需要声明服务,所以申明是这样的:
/** * <p/> * <li>Description: TODO</li> * <li>@author: ChengXiang.Li</li> * <li>Date: 2020/4/14 14:55</li> */ @Service public class SysLoginServiceImpl implements SysLoginService { /** * <li>Description: 管理系统登录接口 </li> * * @param loginDTO 登录入参包装实体 * @return RestfulDTO */ @Override public RestfulDTO login(SysLoginDTO loginDTO) { return null; } /** * <li>Description: 退出登录 </li> */ @Override public void logout() { }
需要注意的是这个@Service注解不是Spring的而是Dubbo框架给我们提供的。
启用Dubbo应用的时候一般是在SpringBoot应用的入口类上加@EnableDubbo注解,服务提供者和消费者都需要加的。
消费服务:
@RestController public class SysLoginController { /** * <li>loginService :Dubbo框架的远程调用-SysLoginService </li> */ @Reference private SysLoginService loginService; /** * <li>Description: 管理系统登录接口 </li> * * @param loginDTO 登录接口的入参 * @return RestfulDTO */ @PostMapping(value = "/login") public RestfulDTO login(@RequestBody SysLoginDTO loginDTO) { return loginService.login(loginDTO); } }
@Reference注解也是Dubbo框架为我们提供的。
这个结果就不说了,一个很简单的Dubbo和SpringBoot的集成,优点是简单,真的简单,相对以前的XML的配置方式确实简单了不少,但是缺点也是非常明显的,在企业中各个应用服务的配置是基本一致的,也就是说没有做到一次配置多处使用的目的(程序员都懒),那么有人就会说我们可以使用配置服务啊。例如SpringCloud的config等,把这些配置全部管理起来就可以实现一次配置多处使用。当然这个方式肯定可行,因为在很多公司都是这样使用的,但是这不是我们需要说的重点,在很多的中小公司,服务器的硬件资源是很金贵的,可能很多的公司都没有自己的一站式配置服务。因为没有资源,在没有资源的情况下我们要做一次配置多处服务,这个就是我们想说的事情了。程序员是万能的。
基于XML的配置方式我们不说,建议以下几篇文章,写的都不差。
1) Maven 依赖
<dependency> <groupId>org.apache.curator</groupId> <artifactId>curator-framework</artifactId> </dependency> <dependency> <groupId>org.apache.curator</groupId> <artifactId>curator-recipes</artifactId> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>dubbo</artifactId> </dependency> <dependency> <groupId>org.apache.dubbo</groupId> <artifactId>dubbo-registry-nacos</artifactId> </dependency> <dependency> <groupId>com.alibaba.nacos</groupId> <artifactId>nacos-client</artifactId> </dependency> 2) NacosServer服务 附上Dubbo官网上的与Nacos集成说明地址 http://dubbo.apache.org/zh-cn/docs/user/references/registry/nacos.html NacosServer下载地址:https://github.com/alibaba/nacos/releases 下载完成以后直接解压然后进入bin目录点击startup.cmd运行即可(依赖JDK环境,1.8最好) 5.3.2 新增依赖项目模块 xxx-xxx-framework-rpc模块 新增 这样的几个注解。 @DubboRegistry注解与下图配置项等价 代码: @Documented @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface DubboRegistry { /** * <li>Description: Dubbo注册类型,默认注册到Zookeeper上。现在提供两种注册方式(Zookeeper,Nacos) </li> * * @return RegistryType */ RegistryType type() default RegistryType.ZOOKEEPER; /** * <li>Description: 默认的注册地址 </li> * * @return String */ String address() default "zookeeper://127.0.0.1:2181"; /** * <li>Description: 通讯协议 </li> * * @return String */ String protocol() default "dubbo"; /** * <li>Description: 通讯端口 </li> * * @return int */ int protocolPort() default 21810; }
@EnableDubboApplication注解,主要是为了标注当前应用使用了Dubbo,与下图这段等价
代码:
@Documented @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface EnableDubboApplication { String name() default ""; /** * <li>Description: 基础扫描包 </li> * * @return String */ String scanPackage() default ""; /** * <li>Description: 服务接口的基类 </li> * * @return String */ String parentClass() default ""; /** * <li>Description: 默认的当前声明应用的全局服务超时时间,5秒 </li> * * @return int */ int timeOut() default 5000; }