Dubbo的多注册中心(一)
Dubbo是什么?
Dubbo是阿里巴巴SOA服务化治理方案的核心框架,致力于提供高性能和透明化的RPC远程服务调用方案,以及SOA服务治理方案。
- 远程通讯: 提供对多种基于长连接的NIO框架抽象封装,包括多种线程模型,序列化,以及“请求-响应”模式的信息交换方式。
- 集群容错: 提供基于接口方法的透明远程过程调用,包括多协议支持,以及软负载均衡,失败容错,地址路由,动态配置等集群支持。
- 自动发现: 基于注册中心目录服务,使服务消费方能动态的查找服务提供方,使地址透明,使服务提供方可以平滑增加或减少机器。
Dubbo能做什么?
- 服务治理框架
- 服务的监控
- 服务的注册发现
- 服务的通信
- 服务的容错
- 服务的负载均衡
下图是从官网上截取的Dubbo的架构图 http://dubbo.apache.org/zh-cn/;
节点角色说明:
依赖关系
图例说明:
- 图中小方块 Protocol, Cluster, Proxy, Service, Container, Registry, Monitor 代表层或模块,蓝色的表示与业务有交互,绿色的表示只对 Dubbo 内部交互。
- 图中背景方块 Consumer, Provider, Registry, Monitor 代表部署逻辑拓扑节点。
- 图中蓝色虚线为初始化时调用,红色虚线为运行时异步调用,红色实线为运行时同步调用。
- 图中只包含 RPC 的层,不包含 Remoting 的层,Remoting 整体都隐含在 Protocol 中。
Dubbo的使用,基本通信的建立
首先我们建立doubbo-server服务端项目,并在里面建立两个子项目
服务端写完了我们建立客户端,并在客户端引入服务端的api包文件
下面我们要进行的就是服务间的通信,为完成通信那我们要把服务进行发布,发布服务我们要引用下面的doubbo包
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo</artifactId>
<version>2.7.8</version>
</dependency>
在客户端和服务端添加完这个包后我们,在dubbo-service服务中配置application.xml文件
配置完成后启动dubbo-service的app进行发布服务,服务器启动后我们得到了一个URL路径
拿到这个URL路径后我们去配置dubbo-user的application.xml文件
配置完成后启动dubbo-user的app文件,通过打印台我们会看到我们通信成功
引入注册中心(zookeeper)
在引入zookeeper之前启动虚拟机下载zookeeper镜像,关于虚拟机如何搭建及建立镜像请参考我在博客中发表的虚拟机文章
1.下载Zookeeper镜像
docker pull zookeeper
2.启动容器并添加映射
docker run --privileged=true -d --name zookeeper --publish 2181:2181 -d zookeeper:latest
3.查看容器是否启动
docker ps
启动容器后我们修改dubbo-service服务的application.xml配置
并在对应的pom文件引入dubbo-dependencies-zookeeper包
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-dependencies-zookeeper</artifactId>
<version>2.7.8</version>
</dependency>
我们对dubbo-user服务也做一样的处理引入dubbo-dependencies-zookeeper包然后在application.xml修改配置
启动app发现我们调用成功
Dubbo Spring cloud(nacos注册中心)
前面讲解了spring中怎么用dubbo,现在我们来讲下spring cloud怎么集成dubbo的,我们先建立一个maven项目和两个springboot项目,我们在api中写接口,在spring项目中引用
这里项目到时候会发布,其实里面内容和上面项目内容一样,只是换种方式而已,为了用到nacos注册中心,我们用docker pull nacos/nacos-server命令下载镜像;下载下来后通过docker images查看是否下载成功,如果成功运行
docker run -d --name nacos-server-8848 -p 8848:8848 -e MODE=standalone -e PREFER_HOST_MODE=hostname nacos/nacos-server启动
父pom也很简单
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.ghy</groupId> <artifactId>cloud-dubbo</artifactId> <packaging>pom</packaging> <version>1.0-SNAPSHOT</version> <modules> <module>cloud-dubbo-api</module> <module>cloud-dubbo-server</module> <module>cloud-dubbo-user</module> </modules> <name>cloud-dubbo</name> <properties> <java.version>1.8</java.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <spring-boot.version>2.3.0.RELEASE</spring-boot.version> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>${spring-boot.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <build> <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) --> <plugins> <!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle --> <plugin> <artifactId>maven-clean-plugin</artifactId> <version>3.1.0</version> </plugin> <!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging --> <plugin> <artifactId>maven-resources-plugin</artifactId> <version>3.0.2</version> </plugin> <plugin> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.0</version> </plugin> <plugin> <artifactId>maven-surefire-plugin</artifactId> <version>2.22.1</version> </plugin> <plugin> <artifactId>maven-jar-plugin</artifactId> <version>3.0.2</version> </plugin> <plugin> <artifactId>maven-install-plugin</artifactId> <version>2.5.2</version> </plugin> <plugin> <artifactId>maven-deploy-plugin</artifactId> <version>2.8.2</version> </plugin> <!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle --> <plugin> <artifactId>maven-site-plugin</artifactId> <version>3.7.1</version> </plugin> <plugin> <artifactId>maven-project-info-reports-plugin</artifactId> <version>3.0.0</version> </plugin> </plugins> </pluginManagement> </build> </project>
cloud-dubbo-api工程pom文件
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <artifactId>cloud-dubbo</artifactId> <groupId>com.ghy</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>cloud-dubbo-api</artifactId> <name>cloud-dubbo-api</name> <!-- FIXME change it to the project's website --> <url>http://www.example.com</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.7</maven.compiler.source> <maven.compiler.target>1.7</maven.compiler.target> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency> </dependencies> <build> <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) --> <plugins> <!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle --> <plugin> <artifactId>maven-clean-plugin</artifactId> <version>3.1.0</version> </plugin> <!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging --> <plugin> <artifactId>maven-resources-plugin</artifactId> <version>3.0.2</version> </plugin> <plugin> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.0</version> </plugin> <plugin> <artifactId>maven-surefire-plugin</artifactId> <version>2.22.1</version> </plugin> <plugin> <artifactId>maven-jar-plugin</artifactId> <version>3.0.2</version> </plugin> <plugin> <artifactId>maven-install-plugin</artifactId> <version>2.5.2</version> </plugin> <plugin> <artifactId>maven-deploy-plugin</artifactId> <version>2.8.2</version> </plugin> <!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle --> <plugin> <artifactId>maven-site-plugin</artifactId> <version>3.7.1</version> </plugin> <plugin> <artifactId>maven-project-info-reports-plugin</artifactId> <version>3.0.0</version> </plugin> </plugins> </pluginManagement> </build> </project>
然后在cloud-dubbo-api工程建一个抽象类GhyService类
public interface GhyService { String ghyServer(String str); }
服务提供者pom
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <artifactId>cloud-dubbo</artifactId> <groupId>com.ghy</groupId> <version>1.0-SNAPSHOT</version> </parent> <!--<modelVersion>4.0.0</modelVersion>--> <groupId>com.ghy</groupId> <artifactId>cloud-dubbo-server</artifactId> <version>0.0.1-SNAPSHOT</version> <name>cloud-dubbo-server</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>com.ghy</groupId> <artifactId>cloud-dubbo-api</artifactId> <version>1.0-SNAPSHOT</version> </dependency> <!--项目的发布--> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-dubbo</artifactId> <version>2.2.1.RELEASE</version> </dependency> <!--服务注册--> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> <version>2.2.1.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.1</version> <configuration> <source>1.8</source> <target>1.8</target> <encoding>UTF-8</encoding> </configuration> </plugin> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <version>2.3.0.RELEASE</version> <configuration> <mainClass>com.ghy.clouddubboserver.CloudDubboServerApplication</mainClass> </configuration> <executions> <execution> <id>repackage</id> <goals> <goal>repackage</goal> </goals> </execution> </executions> </plugin> </plugins> </build> </project>
配置文件
spring: application: name: cloud-dubbo-server cloud: nacos: discovery: server-addr: 192.168.2.102:8848 dubbo: scan: base-packages: com.ghy.clouddubboserver.service protocol: port: 8882 name: dubbo
接口的实现类GhyServiceImpl类
import com.ghy.springcloudapi.GhyService; import org.apache.dubbo.config.annotation.Service; @Service//注意不要引错包了 public class GhyServiceImpl implements GhyService { public String ghyServer(String str) { return "返回的信息是"+str; } }
然后在启动类上加入@EnableDiscoveryClient注解
服务消费者cloud-dubbo-user类的pom文件
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <artifactId>cloud-dubbo</artifactId> <groupId>com.ghy</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <groupId>com.ghy</groupId> <artifactId>cloud-dubbo-user</artifactId> <version>0.0.1-SNAPSHOT</version> <name>cloud-dubbo-user</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-dubbo</artifactId> <version>2.2.1.RELEASE</version> </dependency> <dependency> <groupId>com.ghy</groupId> <artifactId>cloud-dubbo-api</artifactId> <version>1.0-SNAPSHOT</version> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> <version>2.2.1.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.1</version> <configuration> <source>1.8</source> <target>1.8</target> <encoding>UTF-8</encoding> </configuration> </plugin> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <version>2.3.0.RELEASE</version> <configuration> <mainClass>com.ghy.clouddubbouser.CloudDubboUserApplication</mainClass> </configuration> <executions> <execution> <id>repackage</id> <goals> <goal>repackage</goal> </goals> </execution> </executions> </plugin> </plugins> </build> </project>
配置文件
spring: application: name: cloud-dubbo-user cloud: nacos: discovery: server-addr: 192.168.2.102:8848 server: port: 8081
UserController类
import com.ghy.springcloudapi.GhyService; import org.apache.dubbo.config.annotation.Reference; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class UserController { @Reference GhyService ghyService; @GetMapping("/ghy") public String text(){ return ghyService.ghyServer("aaa"); } }
然后启动服务访问接口
Dubbo的多注册中心
有了前面的知识,相信大家对于dubbo在spring及springCloud的注册与发现有了一定的了解,那下面我就关于Dubbo的多注册中心来讲解下,由于springcloud对于dubbo的多注册中心有很多坑在里面,所以我们关于多注册中心讲解还是用springboot项目来讲解,我们还是一样建立三个子项目,项目内容一样,只是换个点配置内容及pom中的包文件,这里的配置文件和上面集成cloud的最大区别就是多注册中心的支持,这里我用把服务注册到nacos和zookeeper中;这是dubbo特有的,springcloud不支持多中心注册,如果要想springclou也支持需要改代码;代码我会传到GIT上,有兴趣的可以下载下来看;因为说这个多注册中心的作用就是想说下Dubbo的应用点有什么,所以就不和以前写springcloud一样详细的写导什么包,一步一步教了,看过我前面写的springcloud体系后的朋友只用下载我这源码然后操作下就懂了,因为这阿里的体系比springcloud体系更简单了
如下图所示,将服务分别注册到zookeeper和nacos中了
然后在启动类上加上注解@DubboComponentScan(basePackages = "com.ghy.spring.dubbo.springbootserver.service")配置好路径,这里配置好后然后看下nacos,监测面板
发现服务被注册上来了,然后用zooInspector的工具看下zooInspector的注册信息,发现也都注册进来 了,这工具我会在源码中一起提供
如果想设置优先级,可以在服务调用端的配置文件中配置如下
#优先选择 dubbo.registries.provider2.preferred=true
也可以通过设置权重的方式来进行分配
#配置权重,多注册中心时服务的负载选择 dubbo.registries.provider1.weight=100 dubbo.registries.provider2.weight=10
还有最后一种区域优先配置
#表示区域优先
dubbo.registries.provider1.zone=provider1
所有配置如下
spring.application.name=spring-boot-user dubbo.registries.provider1.address=zookeeper://192.168.2.102:2181 #超时时间 dubbo.registries.provider1.timeout=10000 #表示区域优先 dubbo.registries.provider1.zone=provider1 #配置权重,多注册中心时服务的负载选择 dubbo.registries.provider1.weight=100 dubbo.registries.provider2.address=nacos://192.168.2.102:8848 dubbo.registries.provider2.weight=10 #优先选择 dubbo.registries.provider2.preferred=true server.port=8888
然后还有一点,在版本更新中,如果想保持老的版本功能不变,然后又引用新的版本,那可以通过@DubboService(registry = {"provider1","provider2"},version = "1.0")指定版本号,下面我是在服务提供端写个两个版本号的服务
//其中version指的是版本的支持,我们在升级中为了保持老版本的功能也能正常使用,所以可以指定版本,在调用时指明被调用的版本就行 //而registry是指注册中心的地址,可以配置多个 @DubboService(registry = {"provider1","provider2"},version = "1.0") public class GhyServiceImpl implements GhyServer { @Override public String ghyServer(String str) { return "1返回的信息是"+str; } }
@DubboService(registry = {"provider1","provider2"},version = "2.0") public class GhyServiceImpl1 implements GhyServer{ @Override public String ghyServer(String str) { return "返回的信息是"+str; } }
然后在服务提供者边调用,下面我是调用版本号为2.0的服务提供者代码
@RestController public class UserController { //指定调用服务端的版本2 @DubboReference(registry = {"provider1","provider2"},version = "2.0") GhyServer ghyServer; @GetMapping("/ghy") public String text() { return ghyServer.ghyServer("LuJiaXing"); } }
另外,springboot支持版本升级保留原功能的注解@DubboReference,在注解中调用端指定版本号version值,那么在调用时会选择对应的版本服务端进行调用,如果指定registry值则会在指定的注册中心找服务资源