title: dubbo + zookeeper学习
基础知识
- 什么是分布式
分布式系统是若干独立计算机的集合; 对用户来说像单个系统。 - 系统垂直拆分面临的问题
(1)界面,业务逻辑实现分离
(2)应用不可能完全独立,应用之间交互 - RPC是什么
远程过程调用。 - dubbo特性
(1)面向接口的RPC框架
(2)负载均衡
(3)运行期间流量调度,逐渐过渡上线服务器台数
(4)可视化治理与运维界面 - 服务注册推荐zookeeper
安装监控中心(可视化界面)
- dubbo-admin : 管理控制台。主要包含:路由规则、动态配置、服务降级、访问控制、权重调整、负载均衡等管理功能
- dubbo-monitor-simple : 简单的监控中心。主要用来统计服务的调用次数和调用时间,服务消费者和 提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心,监控中心则使用数据绘制图表来显示。
服务提供者、服务消费者、API接口
- 将服务提供者注册到注册中心 (暴漏服务)
(1)导入dubbo依赖以及zookeeper的客户端(dubbo2.6以上用curator)
(2)配置提供者 - 让消费者去注册中心订阅提供者的服务地址
API接口代码
- 调用接口统一放到此处
- Bean要实现Serializable
- pom引入dubbo和zookeeper的客户端
package com.itic.dubbo_orderApi.api;
import java.util.List;
import com.itic.dubbo_orderApi.bean.UserAddress;
public interface OrderService {
public List<UserAddress> initOrder(String userId);
}
package com.itic.dubbo_orderApi.api;
import java.util.List;
import com.itic.dubbo_orderApi.bean.UserAddress;
public interface UserService {
public List<UserAddress> getUser(String userId);
}
<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.itic</groupId>
<artifactId>dubbo_orderApi</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>dubbo_orderApi</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/com.alibaba/dubbo -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.6.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.curator/curator-framework -->
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>4.0.1</version>
</dependency>
</dependencies>
</project>
服务提供者代码
- 指定服务名字(同样的服务名字相同)
- 指定注册中心的位置
- 指定通信规则(通信协议和通信端口)
- 暴漏服务 ref:指向真正的实现对象
package com.liuyaofang.dubbo_provide.service.imp;
import java.util.ArrayList;
import java.util.List;
import com.itic.dubbo_orderApi.api.UserService;
import com.itic.dubbo_orderApi.bean.UserAddress;
public class UserServiceImp implements UserService {
@Override
public List<UserAddress> getUser(String userId) {
UserAddress UserAddress1 = new UserAddress("liuyaofang", "北京", 12);
UserAddress UserAddress2 = new UserAddress("liuyaofang", "衡水", 12);
List<UserAddress> list = new ArrayList<>();
list.add(UserAddress1);
list.add(UserAddress2);
return list;
}
}
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
xmlns="http://www.springframework.org/schema/beans"
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">
<!-- provider's application name, used for tracing dependency relationship -->
<dubbo:application name="dubbo-provide"/>
<!-- use multicast registry center to export service -->
<dubbo:registry address="zookeeper://127.0.0.1:2181"/>
<!-- use dubbo protocol to export service on port 20880 -->
<dubbo:protocol name="dubbo" port="20880"/>
<!-- service implementation, as same as regular local bean -->
<bean id="UserServiceImp" class="com.liuyaofang.dubbo_provide.service.imp.UserServiceImp"/>
<!-- declare the service interface to be exported -->
<dubbo:service interface="com.itic.dubbo_orderApi.api.UserService" ref="UserServiceImp"/>
</beans>
<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.liuyaofang</groupId>
<artifactId>dubbo-provide</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>dubbo-provide</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.itic</groupId>
<artifactId>dubbo_orderApi</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.alibaba/dubbo -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.6.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.curator/curator-framework -->
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>4.0.1</version>
</dependency>
</dependencies>
</project>
package com.liuyaofang.dubbo_provide;
import java.io.IOException;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Start {
public static void main(String[] args) throws IOException {
System.setProperty("java.net.preferIPv4Stack", "true");
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
new String[] { "provider.xml" });
context.start();
System.out.println("Provider started.");
System.in.read(); // press any key to exit
}
}
服务消费者代码
- 指定服务名字(同样的服务名字相同)
- 指定注册中心的位置
- dubbo:reference依赖的服务
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:dubbo="http://dubbo.apache.org/schema/dubbo" xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd">
<context:component-scan base-package="com.itic.dubbo_consumer" />
<!-- consumer's application name, used for tracing dependency relationship
(not a matching criterion), don't set it same as provider -->
<dubbo:application name="dubbo_consumer" />
<!-- use multicast registry center to discover service -->
<dubbo:registry address="zookeeper://127.0.0.1:2181" />
<!-- generate proxy for the remote service, then demoService can be used
in the same way as the local regular interface -->
<dubbo:reference id="UserService" check="false"
interface="com.itic.dubbo_orderApi.api.UserService" />
</beans>
package com.itic.dubbo_consumer.service.imp;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.itic.dubbo_orderApi.api.OrderService;
import com.itic.dubbo_orderApi.api.UserService;
import com.itic.dubbo_orderApi.bean.UserAddress;
@Service
public class OrderServiceImp implements OrderService {
@Autowired
private UserService UserService;
@Override
public List<UserAddress> initOrder(String userId) {
List<UserAddress> user = UserService.getUser("1");
return user;
}
}
<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.itic</groupId>
<artifactId>dubbo_consumer</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>dubbo_consumer</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.itic</groupId>
<artifactId>dubbo_orderApi</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
</project>
package com.itic.dubbo_consumer;
import java.util.List;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.itic.dubbo_orderApi.api.OrderService;
import com.itic.dubbo_orderApi.bean.UserAddress;
public class Consumer {
public static void main(String[] args) throws Exception {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[] { "Consumer.xml" });
context.start();
// Obtaining a remote service proxy
OrderService demoService = (OrderService) context.getBean(OrderService.class);
// Executing remote methods
List<UserAddress> hello = demoService.initOrder("1");
for (UserAddress userAddress : hello) {
System.out.println(userAddress.getAddress());
}
// Display the call result
System.out.println("END");
System.in.read(); // press any key to exit
}
}
spring-boot整合
- 在pom.xml导入dubbo-spring-boot-starter\
- 在properties中配置(之前的xml)
- 暴露服务(注解@Service) ; 消费服务(注解:@Reference)
dubbo覆盖策略
虚拟机参数 > xml > dubbo.properties
启动时检查
check=“false” 只有在调用的时候才会检查
超时设置(毫秒)
- 方法优先,接口次之,全局再次之
- 如果级别一样,消费者优先
重试次数
retries 重试次数不包含第一次
- 幂等(设置重试次数) - 查询,删除,修改不会改变结果
- 非幂等(不能设置重试次数) - 新增
多版本
version : 实现灰度发布;
本地存根
stub 。 在调用真的接口前,先做某些事,实现本地接口,并创建有参构造器,参数为接口(代理),配置xml 的stub
dubbo配置与springBoot整合的三种方式
- 导入dubbo-starter,在application配置,@Service @Reference
- 保留dubbo 的xml配置文件,导入dubbo-starter,使用@ImportantResouce导入xml配置文件
- 将每一个组件手动创建(闲的)
高可用
-
zookeeper宕机
zookeeper宕机后,还可以为消费者提供服务 (如果调用过,注册中心宕机后,会通过缓存提供服务) -
直连,绕过注册中心
集群下dubbo负载均衡设置
负载均衡策略
- 随机(根据权重设置随机率)
- 轮询
- 最少活跃数
- 一致性Hash,相同的参数发给同一个提供者
服务降级
当服务器压力剧增,牺牲某些用户利益,保重大部分利益。
- 不发起远程调用,直接返回为空
- 服务调用后失败返回为空
集群容错
当调用一个服务失败,迅速切换。
- 失败自动切换
- 快速失败,只调用一次,失败立即报错
- 失败安全,出现异常时,直接忽略(日志)
- 失败自动恢复,记录失败,定时重发(消息通知)
- 并行调用多个服务器,只要一个成功立即返回
- 广播调用所有提供者,逐个调用,任意一个报错则报错(更新缓存或者日志)
整合hystrix,可以在调用出现问题时,返回别的结果