Dubbo是Alibaba开源的分布式服务框架,它最大的特点是按照分层的方式来架构,使用这种方式可以使各个层之间解耦合(或者最大限度地松耦合)。从服务模型的角度来看, Dubbo采用的是一种非常简单的模型,要么是提供方提供服务,要么是消费方消费服务,所以基于这一点可以抽象出服务提供方(Provider)和服务消费方(Consumer)两个角色,负责治理调用。
ZooKeeper 是一个分布式的,开放源码的分布式应用程序协调服务。它是一个为分布式应用提供一致性服务的软件,提供的功能包括:配置维护、域名服务、分布式同步、组服务等。(在使用dubbo的时候zookeeper。就是充当注册中心,用来管理注册服务,和消费者引用服务负责注册发现)。
架构图如下(来源:github)
服务的提供者,把服务发布到zookeeper当中(相当于注册中心),而消费者需要服务的时候,不需用直接寻找服务的发布者,而是问注册中心索要服务,注册中心把其所需要的地址列表返回给消费者,这样消费者就可以调用生产者发布的服务。
(1)安装zookeeper为了方便,这里采用dokcer镜像的方式
// ps:因为使用官网的镜像下载速度会很慢,这里采用了阿里云镜像加速 下载版本 3.4.11
[root@localhost ~]# docker pull 37y8py0j.mirror.aliyuncs.com/library/zookeeper:3.4.11
下载完成之后,运行镜像
//先查看 有哪一些镜像
[root@localhost ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
pshk7r7h.mirror.swr.myhuaweicloud.com/library/rabbitmq 3-management c4663bdca2cd 8 days ago 189 MB
37y8py0j.mirror.aliyuncs.com/library/elasticsearch 7.1.0 12ad640a1ec0 4 weeks ago 894 MB
docker.io/tomcat 7 bf7d94e5177f 3 months ago 359 MB
docker.io/mysql 5.7 ee7cbd482336 3 months ago 372 MB
37y8py0j.mirror.aliyuncs.com/library/elasticsearch 5.6.9 5c1e1ecfe33a 12 months ago 486 MB
37y8py0j.mirror.aliyuncs.com/library/zookeeper 3.4.11 56d414270ae3 17 months ago 146 MB
37y8py0j.mirror.aliyuncs.com/library/elasticsearch 2.4.0 83ed90c49472 2 years ago 343 MB
//运行镜像 -p 代表后台运行 2182:2181 把虚拟机的端口 映射到 zookeeper应用的2181端口
[root@localhost ~]# docker run --name zoo01 --restart always -p 2181:2181 -d 56d414270ae3
(2)创建一个工程------服务的生产者provider
在pom.xml
引入相关依赖(我这的spring-boot版本 1.5.21.RELEASE
,要引入dubbo-spring-boot-starter 0.1.0版本
,一开始引入的是0.2.0
版本 ,服务启动发布的时候会报错)
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
<dependency>
<groupId>com.alibaba.bootgroupId>
<artifactId>dubbo-spring-boot-starterartifactId>
<version>0.1.0version>
dependency>
<dependency>
<groupId>com.101tecgroupId>
<artifactId>zkclientartifactId>
<version>0.10version>
dependency>
dependencies>
编写dubbo的相关配置文件
dubbo.application.name=provider
dubbo.registry.address=zookeeper://192.168.25.131:2181
dubbo.scan.base-packages=com.kuake.springboo.servicet
##制定暴露服务的协议 (可以省略)
spring.dubbo.protocol.name=dubbo
###指定暴露服务的端口(可以省略,但是如果生产者都要提供服务,就需要设置不同的端口不然端口会冲突)
spring.dubbo.protocol.port=20880
编写提供的服务代码:
package com.kuake.springboot.service;
/**
* @author hao
* @create 2019-06-12 ${TIM}
*/
public interface ProviderService {
//服务接口
public String providerService();
}
实现类:
package com.kuake.springboot.service.impl;
import com.alibaba.dubbo.config.annotation.Service;
import com.kuake.springboot.service.ProviderService;
import org.springframework.stereotype.Component;
/**
* @author hao
* @create 2019-06-12 ${TIM}
*/
@Component
@Service// 通过注解暴露服务 与下面配置的方式相同(注意:这个是dubbo包下的@Service注解)
/*
*/
public class ProviderServiceImpl implements ProviderService {
@Override
public String providerService() {
return "我来提供服务啦";
}
}
(2)创建一个新工程-----服务的消费者consumer
同样引入相关依赖
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
<dependency>
<groupId>com.alibaba.bootgroupId>
<artifactId>dubbo-spring-boot-starterartifactId>
<version>0.1.0version>
dependency>
<dependency>
<groupId>com.101tecgroupId>
<artifactId>zkclientartifactId>
<version>0.10version>
dependency>
编写配置文件 ,配置dubbo
####应用名称
dubbo.application.name=consumer
### 注册地址
dubbo.registry.address=zookeeper://192.168.25.131:2181
编写消费者的代码:
包结构如下:(注意:服务的接口全限定名要与生生产者那边的权限定名要相同,简单来说就是要放在相同的目录接口下面)
/**
* @author hao
* @create 2019-06-12 ${TIM}
*/
@Service
public class UserService {
/*
/dubbo:registry
*/
@Reference //从注册中心引用服务,与传统配置文件的方法类似
private ProviderService providerService;
public String getService(){
//使用 服务生产者提供的服务
return providerService.providerService();
}
}
测试代码:
package com.kuake.springboot;
import com.kuake.springboot.userservice.UserService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringbootDubboConsumerApplicationTests {
@Autowired
UserService userService;
@Test
public void contextLoads() {
System.out.println("我要获得服务");
String service = userService.getService();
System.out.println(service);
}
}
(1)运行消息的生产者,发布服务:
\instantclient-sqlplus-windows.x64-12.1.0.1.0\instantclient_12_1;C:\Pr;gram Files (x86)\Intel\OpenCL SDK\3.0\bin\x86;C:\Program Files (x86)\Intel\OpenCL SDK\3.0\bin\x64;D:\Git\cmd;D:\SSH_SecureShell;.
2019-06-13 15:22:02.144 INFO 6844 --- [clientConnector] org.apache.zookeeper.ZooKeeper : Client environment:java.io.tmpdir=C:\Users\ADMINI~1\AppData\Local\Temp\
2019-06-13 15:22:02.144 INFO 6844 --- [clientConnector] org.apache.zookeeper.ZooKeeper : Client environment:java.compiler=<NA>
2019-06-13 15:22:02.144 INFO 6844 --- [clientConnector] org.apache.zookeeper.ZooKeeper : Client environment:os.name=Windows 7
2019-06-13 15:22:02.144 INFO 6844 --- [clientConnector] org.apache.zookeeper.ZooKeeper : Client environment:os.arch=amd64
2019-06-13 15:22:02.144 INFO 6844 --- [clientConnector] org.apache.zookeeper.ZooKeeper : Client environment:os.version=6.1
2019-06-13 15:22:02.144 INFO 6844 --- [clientConnector] org.apache.zookeeper.ZooKeeper : Client environment:user.name=Administrator
2019-06-13 15:22:02.144 INFO 6844 --- [clientConnector] org.apache.zookeeper.ZooKeeper : Client environment:user.home=C:\Users\Administrator
2019-06-13 15:22:02.144 INFO 6844 --- [clientConnector] org.apache.zookeeper.ZooKeeper : Client environment:user.dir=F:\ideaworkplace\springboot-dubbo
2019-06-13 15:22:02.145 INFO 6844 --- [clientConnector] org.apache.zookeeper.ZooKeeper : Initiating client connection, connectString=192.168.25.131:2181 sessionTimeout=30000 watcher=org.I0Itec.zkclient.ZkClient@3075b107
2019-06-13 15:22:02.156 INFO 6844 --- [clientConnector] org.I0Itec.zkclient.ZkClient : Waiting for keeper state SyncConnected
2019-06-13 15:22:02.160 INFO 6844 --- [68.25.131:2181)] org.apache.zookeeper.ClientCnxn : Opening socket connection to server 192.168.25.131/192.168.25.131:2181. Will not attempt to authenticate using SASL (unknown error)
2019-06-13 15:22:02.162 INFO 6844 --- [68.25.131:2181)] org.apache.zookeeper.ClientCnxn : Socket connection established to 192.168.25.131/192.168.25.131:2181, initiating session
2019-06-13 15:22:02.178 INFO 6844 --- [68.25.131:2181)] org.apache.zookeeper.ClientCnxn : Session establishment complete on server 192.168.25.131/192.168.25.131:2181, sessionid = 0x1000221ed62000d, negotiated timeout = 30000
2019-06-13 15:22:02.180 INFO 6844 --- [tor-EventThread] org.I0Itec.zkclient.ZkClient : zookeeper state changed (SyncConnected)
2019-06-13 15:22:02.183 INFO 6844 --- [ main] c.a.d.r.zookeeper.ZookeeperRegistry : [DUBBO] Register: dubbo://192.168.21.1:20880/com.kuake.springboot.service.ProviderService?anyhost=true&application=provider&dubbo=2.0.1&generic=false&interface=com.kuake.springboot.service.ProviderService&methods=providerService&pid=6844&side=provider×tamp=1560410521877, dubbo version: 2.0.1, current host: 192.168.21.1
2019-06-13 15:22:02.198 INFO 6844 --- [ main] c.a.d.r.zookeeper.ZookeeperRegistry : [DUBBO] Subscribe: provider://192.168.21.1:20880/com.kuake.springboot.service.ProviderService?anyhost=true&application=provider&category=configurators&check=false&dubbo=2.0.1&generic=false&interface=com.kuake.springboot.service.ProviderService&methods=providerService&pid=6844&side=provider×tamp=1560410521877, dubbo version: 2.0.1, current host: 192.168.21.1
2019-06-13 15:22:02.219 INFO 6844 --- [ main] c.a.d.r.zookeeper.ZookeeperRegistry : [DUBBO] Notify urls for subscribe url provider://192.168.21.1:20880/com.kuake.springboot.service.ProviderService?anyhost=true&application=provider&category=configurators&check=false&dubbo=2.0.1&generic=false&interface=com.kuake.springboot.service.ProviderService&methods=providerService&pid=6844&side=provider×tamp=1560410521877, urls: [empty://192.168.21.1:20880/com.kuake.springboot.service.ProviderService?anyhost=true&application=provider&category=configurators&check=false&dubbo=2.0.1&generic=false&interface=com.kuake.springboot.service.ProviderService&methods=providerService&pid=6844&side=provider×tamp=1560410521877], dubbo version: 2.0.1, current host: 192.168.21.1
2019-06-13 15:22:02.270 INFO 6844 --- [ main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 8080 (http)
2019-06-13 15:22:02.275 INFO 6844 --- [ main] c.k.s.SpringbootDubboProviderApplication : Started SpringbootDubboProviderApplication in 4.762 seconds (JVM running for 6.592)
2019-06-13 15:24:29.233 WARN 6844 --- [ver worker #1-1] c.a.d.remoting.transport.AbstractServer : [DUBBO] All clients has discontected from /192.168.21.1:20880. You can graceful shutdown now., dubbo version: 2.0.1, current host: 192.168.21.1
2019-06-13 15:24:29.234 INFO 6844 --- [:20880-thread-3] c.a.d.rpc.protocol.dubbo.DubboProtocol : [DUBBO] disconected from /192.168.21.1:9130,url:dubbo://192.168.21.1:20880/com.kuake.springboot.service.ProviderService?anyhost=true&application=provider&bind.ip=192.168.21.1&bind.port=20880&channel.readonly.sent=true&codec=dubbo&dubbo=2.0.1&generic=false&heartbeat=60000&interface=com.kuake.springboot.service.ProviderService&methods=providerService&pid=6844&side=provider×tamp=1560410521877, dubbo version: 2.0.1, current host: 192.168.21.1
控制台打印了注册服务成功了url地址
(2)消费者,引用服务进行测试
package com.kuake.springboot;
import com.kuake.springboot.userservice.UserService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringbootDubboConsumerApplicationTests {
@Autowired
UserService userService;
@Test
public void contextLoads() {
System.out.println("我要获得服务");
String service = userService.getService();
System.out.println(service);
}
}
运行上述代码:(控制台打印)
6.657 seconds (JVM running for 8.246)
我要获得服务
我来提供服务啦
2019-06-13 15:24:19.196 INFO 7648 --- [bboShutdownHook] com.alibaba.dubbo.config.AbstractConfig : [DUBBO] Run shutdown hook now., dubbo version: 2.0.1, current host: 192.168.21.1
2019-06-13 15:24:19.197 INFO 7648 --- [bboShutdownHook] c.a.d.r.support.AbstractRegistryFactory : [DUBBO] Close all registries [zookeeper://192.168.25.131:2181/com.alibaba.dubbo.registry.RegistryService?application=consumer&dubbo=2.0.1&interface=com.alibaba.dubbo.registry.RegistryService&pid=7648×tamp=1560410656161], dubbo version: 2.0.1, current host: 192.168.21.1
2019-06-13 15:24:19.197 INFO 7648 --- [bboShutdownHook] c.a.d.r.zookeeper.ZookeeperRegistry : [DUBBO] Destroy registry:zookeeper://192.168.25.131:2181/com.alibaba.dubbo.registry.RegistryService?application=consumer&dubbo=2.0.1&interface=com.alibaba.dubbo.registry.RegistryService&pid=7648×tamp=1560410656161, dubbo version: 2.0.1, current host: 192.168.21.1
2019-06-13 15:24:19.197 INFO 7648 --- [bboShutdownHook] c.a.d.r.zookeeper.ZookeeperRegistry : [DUBBO] Unregister: consumer://192.168.21.1/com.kuake.springboot.service.ProviderService?application=consumer&category=consumers&check=false&dubbo=2.0.1&interface=com.kuake.springboot.service.ProviderService&methods=providerService&pid=7648&side=consumer×tamp=1560410656099, dubbo version: 2.0.1, current host: 192.168.21.1
2019-06-13 15:24:19.201 INFO 7648 --- [ Thread-4] o.s.w.c.s.GenericWebApplicationContext : Closing org.springframework.web.context.support.GenericWebApplicationContext@568ff82: startup date [Thu Jun 13 15:24:12 CST 2019]; root of context hierarchy
2019-06-13 15:24:19.207 INFO 7648 --- [ Thread-4] f.a.ReferenceAnnotationBeanPostProcessor : <dubbo:reference object="com.alibaba.dubbo.common.bytecode.proxy0@5eefa415" singleton="true" interface="com.kuake.springboot.service.ProviderService" uniqueServiceName="com.kuake.springboot.service.ProviderService" filter="" listener="" generic="false" id="com.kuake.springboot.service.ProviderService" /> was destroying!
2019-06-13 15:24:19.208 INFO 7648 --- [ Thread-4] f.a.ReferenceAnnotationBeanPostProcessor : class com.alibaba.dubbo.config.spring.beans.factory.annotation.ReferenceAnnotationBeanPostProcessor was destroying!
成功调用了UserService#getService方法,而getService方法是远程调用生产者发布到注册中心的服务,测试成功