Dubbo & ZooKeeper
分布式的基本定义
分布式系统是若干个独立计算机的集合 ,这些计算机对于用户来说就像单个相关系统
利用更多机器,进行更多计算
使用廉价的机器完成更高性能的计算机才能完成的工作
应用架构的演变
- 单一的小型应用
- 垂直应用架构(多个应用放在多个多个服务器上)
- 界面-逻辑实现分离
- 应用
- 分布式服务架构
RPC
远程过程调用
相对于本地过程调用,本地A方法调用本地B方法
远程过程调用,本地的A方法调用另外一台电脑上的B方法
他允许程序调用另一个地址空间的过程或函数,而不用程序员显式编码这个远程调用的细节,使调用本地的过程和调用远程的过程代码基本相同
ZooKeeper
ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是Hadoop和Hbase的重要组件。它是一个为分布式应用提供一致性服务的软件,提供的功能包括:配置维护、域名服务、分布式同步、组服务等。
安装zookeeper
下载安装完成后,需要配置一个文件才能进行运行
在安装目录下conf文件夹下配置一个zoo.cfg
需要把zoo_sample.cfg复制一份,然后进行配置
如果出错,确保环境变量中JAVA_HOME
配置正确
启动zookeeper
启动bin目录下
以管理员身份启动 zkServer.cmd
,服务端程序
如果没有闪退就证明启动成功了,如果闪退可能是Java环境变量的问题
再启动zkCli.cmd
,这是客户端程序
Dubbo Admin
为了方便我们管理Dubbo,我们使用Dubbo Admin来进行管理
下载Dubbo Admin 的方式很简单
直接clone或者下载下来都行
因为这个只有源码,只能自己进行构建,我们使用maven进行构建
在项目根目录打开cmd
mvn clean package
便会自动开始打包
Dubbo Admin默认的端口是7001端口
server.port=7001
spring.velocity.cache=false
spring.velocity.charset=UTF-8
spring.velocity.layout-url=/templates/default.vm
spring.messages.fallback-to-system-locale=false
spring.messages.basename=i18n/message
spring.root.password=root
spring.guest.password=guest
dubbo.registry.address=zookeeper://127.0.0.1:2181
这里面的东西都能进行更改
如果zookeeper的端口号进行了修改的话,这里也要同步进行修改
打包好的jar在dubbo-admin/target
文件夹下,cd到那边,在这里进行启动
java -jar jar包名
基本上就成功运行了
重要提醒:打开dubbo-admin之前要打开zookeeper
Dubbo
- 面向接口代理的高性能RPC调用
- 智能负载均衡
- 服务自动注册与发现
快速开始
导入依赖
这里没有使用spring boot,使用的是一个普通的maven项目
<!-- https://mvnrepository.com/artifact/org.apache.dubbo/dubbo -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.6.2</version>
</dependency>
因为zookeeper的注册也需要使用jar包
Dubbo 支持 zkclient 和 curator 两种 Zookeeper 客户端实现
这里注意
- Dubbo从
2.2.0
版本开始缺省为 zkclient 实现 - Dubbo从
2.3.0
版本开始支持可选 curator 实现
根据我这里的Dubbo版本,我们使用curator实现
<!-- https://mvnrepository.com/artifact/org.apache.curator/curator-framework -->
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>4.2.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.curator/curator-recipes -->
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>4.2.0</version>
</dependency>
场景描述
这里分为两个角色生产者(服务提供者)
和消费者(服务使用者)
生产者提供服务,消费者消费服务
定义生产者提供服务的类
public interface UserService()
{
User findUserById(String id);
}
消费者使用的类是
public interface OrderService()
{
void addOrder();
}
这是两个接口
其中消费者使用的方法中会调用这个生产者的UserService
代码编写
定义公共的接口项目
在官方文档中指出
http://dubbo.apache.org/zh-cn/docs/user/best-practice.html
建议将服务接口、服务模型、服务异常等均放在 API 包中,因为服务模型和异常也是 API 的一部分,这样做也符合分包原则:重用发布等价原则(REP),共同重用原则(CRP)。
所以我们在使用Dubbo的时候最好建立一个API包
在项目中新建API模块,取名service-api
,这是一个maven项目,里面存放的内容有
- Bean
- Service的接口
- ...等公共的部分
所以我们在里面新建一个包,com.dubboLearn.pojo
,编写Bean
public class User {
private String UserId;
private String UserName;
}
新建一个包com.dubboLearn.service
编写Service,里面的内容和刚刚场景描述中的相同
编写服务提供者
新建一个模块dubbo-provider
,也是一个普通的maven项目,在pom.xml文件中需要导入依赖
<dependency>
<groupId>com.dubboLearn</groupId>
<artifactId>service-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
这样构建的时候就导入了Api模块的依赖
编写服务的实现类,在com.dubboLearn.service.impl
包下新建UserServiceImpl
public class UserServiceImpl implements UserService {
public static Map<String,User> userMap;
static {
userMap = new HashMap<String, User>();
userMap.put("1",new User("1","lucas"));
}
public User findUserById(String id) {
return UserServiceImpl.userMap.get(id);
}
}
我们这里使用的假数据,由静态代码块进行初始化
现在我们将配置dubbo并暴露服务
因为dubbo的底层也使用spring进行项目的管理,我们可以使用spring配置文件进行配置
在官方文档中
创建,provider.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
http://dubbo.apache.org/schema/dubbo
http://dubbo.apache.org/schema/dubbo/dubbo.xsd">
<!-- 提供方应用信息,用于计算依赖关系 -->
<!-- 只要不和别的服务同名就行 -->
<dubbo:application name="server-provider" />
<!-- 使用zookeeper注册中心暴露服务地址 -->
<!-- 指定注册中心的位置 -->
<dubbo:registry address="zookeeper://127.0.0.1:2181" />
<!-- 也可以这样写 -->
<!-- <dubbo:registry protocol="zookeeper" address="zookeeper://127.0.0.1:2181"/> -->
<!-- 用dubbo协议在20880端口暴露服务 -->
<!-- 指定通信规则 -->
<dubbo:protocol name="dubbo" port="20880" />
<!-- 声明需要暴露的服务接口 -->
<!-- ref指向真正实现的类 -->
<dubbo:service interface="com.dubboLearn.service.UserService" ref="userService" />
<!-- 和本地bean一样实现服务 -->
<!-- 注册这个bean到 spring 容器 -->
<bean id="userService" class="com.dubboLearn.service.impl.UserServiceImpl" />
</beans>
启动这个服务
编写main方法
public static void main(String[] args) throws IOException {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:provider.xml");
//启动Ioc容器
context.start();
//阻塞进程,不让容器关闭
System.in.read();
}
此时如果报错可能是jar包导入的不对,导入的是阿里的依赖,不是阿帕奇的
如果zookeeper启动的话,那么项目启动就会成功,在Dubbo admin控制台中也能看得见v
编写服务的使用者
新建一个模块dubbo-consumer
,是一个普通的maven项目
和provider一样,新建一个包com.dubboLearn.service.impl
,新建一个类OrderServiceImpl
编写实现类
public class OrderServiceImpl implements OrderService {
private UserService userService;
public UserService getUserService() {
return userService;
}
public void setUserService(UserService userService) {
this.userService = userService;
}
public void addOrder() {
User user = userService.findUserById("1");
if (user!=null)
System.out.println(user.getUserName()+"订购了一些东西");
}
}
配置dubbo
新建consumer.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
http://dubbo.apache.org/schema/dubbo
http://dubbo.apache.org/schema/dubbo/dubbo.xsd">
<!-- 消费方应用名,用于计算依赖关系,不是匹配条件,不要与提供方一样 -->
<dubbo:application name="dubbo-consumer" />
<!-- 使用multicast广播注册中心暴露发现服务地址 -->
<dubbo:registry address="zookeeper://127.0.0.1:2181" />
<!-- 生成远程服务代理,可以和本地bean一样使用UserService -->
<!-- 声明需要访问的服务的接口,在本地IOC容器中生成代理 -->
<dubbo:reference id="userService" interface="com.dubboLearn.service.UserService" />
<!-- 在容器中注册我们刚刚写好的Bean -->
<bean id="orderService" class="com.dubboLaern.service.impl.OrderServiceImpl">
<property name="userService" ref="userService"/>
</bean>
</beans>
启动消费者
public static void main(String[] args) throws IOException {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("consumer.xml");
OrderService orderService = context.getBean("orderService", OrderService.class);
orderService.addOrder();
System.in.read();
}
这样调用就成功了
dubbo 监控中心
在刚刚的Dubbo Admin文件夹中有一个dubbo-monitor
,在里面构建项目,构建完会有一个压缩包,解压
里面有一个conf
文件夹,文件夹下有一个properties
文件,里面的文件按需更改
值得注意的是
dubbo.protocol.port=7070
这个可能会用到
在bin
目录下找到start.bat
,启动,访问刚刚配置文件中的端口号,如果能访问成功那就证明配置没问题
配置注册的服务
在provider.xml
中配置
使用以下两种都可以
-
<dubbo:monitor protocol="registry"/>
-
<dubbo:monitor address="127.0.0.1:7070"/>
第一个表示从注册中心寻找
第二个表示直接连接监控中心,address中填的端口号就是刚刚配置的端口号
这样监控中心就有服务的信息了
当然,在consumer那边也是可以配置的