高并发Day16--Dubbo&Zookeeper
Posted MyMethod
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了高并发Day16--Dubbo&Zookeeper相关的知识,希望对你有一定的参考价值。
1.1 官网介绍
http://dubbo.apache.org/zh-cn/
1.2 Dubbo框架介绍
Apache Dubbo |ˈdʌbəʊ| 是一款高性能、轻量级的开源Java RPC框架,它提供了三大核心能力:面向接口的远程方法调用,智能容错和负载均衡,以及服务自动注册和发现。
1.3 调用过程
1.4 微服务框架定义
程序在分布式的基础之上,让程序分而治之.如果出现了问题,也能自动的实现故障的迁移.无需人为操作.
1.5 SOA思想
面向服务的架构(SOA)是一个组件模型,它将应用程序的不同功能单元(称为服务)进行拆分,并通过这些服务之间定义良好的接口和协议联系起来。接口是采用中立的方式进行定义的,它应该独立于实现服务的硬件平台、操作系统和编程语言。这使得构件在各种各样的系统中的服务可以以一种统一和通用的方式进行交互。
微服务程序编码的一种实际方案.
1.6 RPC(概念)
RPC是远程过程调用(Remote Procedure Call)的缩写形式。SAP系统RPC调用的原理其实很简单,有一些类似于三层构架的C/S系统,第三方的客户程序通过接口调用SAP内部的标准或自定义函数,获得函数返回的数据进行处理后显示或打印。
定义:分布式系统中系统之间的通信的方式称之为RPC,远程过程调用
无需关注通信具体协议细节.可以利用RPC工具直接获取远程服务器数据.
2.1 Zookeeper介绍
ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是Hadoop和Hbase的重要组件。它是一个为分布式应用提供一致性服务的软件,提供的功能包括:配置维护、域名服务、分布式同步、组服务等。
ZooKeeper的目标就是封装好复杂易出错的关键服务,将简单易用的接口和性能高效、功能稳定的系统提供给用户。
ZooKeeper包含一个简单的原语集,提供Java和C的接口。
ZooKeeper代码版本中,提供了分布式独享锁、选举、队列的接口,代码在zookeeper-3.4.3src ecipes。其中分布锁和队列有Java和C两个版本,选举只有Java版本。
2.2.1 Zookeeper下载
网址: http://zookeeper.apache.org/releases.html.
如图-2所示
图-2
下载路径,点击download.
如图-3所示
图-3
http://mirrors.hust.edu.cn/apache/zookeeper/
如图-4所示
图-4
2.2.2 Zookeeper安装
2.2.2.1 安装JDK
将JDK1.8文件上传到Linux操作系统中/src/usr/local/java/文件下.
如图-5所示
图-5
1.解压文件
tar -xvf jdk-8u51-linux-x64.tar.gz
2.配置环境变量
编辑环境变量配置文件
vim /etc/profile
如图-6所示
图-6
使JDK生效,之后检查jdk安装是否成功
source /etc/profile
如图 -7所示
图-7
2.2.2.2 上传安装文件
说明:上传zookeeper安装文件.之后解压.
如图-8所示
图-8
解压目录:
tar -xvf zookeeper-3.4.8.tar.gz
2.2.2.3 修改配置文件
在zk根目录下创建文件夹data/log
mkdir data log
如图-9所示
图-9
复制配置文件并且修改名称
cp zoo_sample.cfg zoo.cfg
如图-10所示
图-10
2.2.2.4 启动zk
zk启动关闭命令如下.
sh zkServer.sh start 或者 ./zkServer.sh start
sh zkServer.sh stop
sh zkServer.sh status
如图-11所示
图-11
3.1 集群划分规定
规则: 集群剩余节点的数量 > n/2;
例子:
面试题:
为什么集群是单数台? 原因:偶数太和奇数台容灾效果相同,所以没有必要搭建偶数台.
面试题2:
集群选举中如果出现平票会发生什么? 如何预防?
如果连续3次平票,则可能出现脑裂现象. 1/8.
可以通过增加集群节点的数量来有效的降低脑裂的发生概率.
3.2 准备文件夹
在zookeeper根目录中创建新的文件夹zkCluster.
如图-12所示
图-12
如图-13所示
创建zk1/zk2/zk3文件夹.
图-13
在每个文件夹里创建data/log文件夹.
mkdir {zk1,zk2,zk3}/{data,log}
如图-14所示
图-14
3.3 添加myid文件
分别在zk1/zk2/zk3中的data文件夹中创建新的文件myid.其中的内容依次为1/2/3,与zk节点号对应.
如图-15所示
图-15
编辑myid文件,定义编号.
如图-16所示
图-16
3.4 编辑配置文件
将zoo_sample.cfg 复制为zoo1.cfg之后修改配置文件.
如图-17所示
图-17
3.5 修改zoo1.cfg
如图-18所示
图-18
配置完成后将zoo1.cfg复制2份.之后需要修改对应的文件夹目录.和不同的端口即可.
3.6 ZK集群测试
通过下面的命令启动zk集群.
sh zkServer.sh start zoo1.cfg
sh zkServer.sh stop zoo1.cfg
sh zkServer.sh status zoo1.cfg
检查主从关系,从机情况说明.
如图-19所示
图-19
检查主从关系,主机情况说明.
如图-20所示
图-20
3.7 关于zookeeper集群说明
Zookeeper集群中leader负责监控集群状态,follower主要负责客户端链接获取服务列表信息.同时参与投票.
图-30
4.1 原理说明
需求:能否实现服务的自动发现和注册.
5.1 项目搭建
5.2 导入项目步骤
5.3 定义公共API接口
5.4 添加依赖包
<!--引入dubbo配置 -->
<dependency>
<groupId>com.alibaba.boot</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>0.2.0</version>
</dependency>
5.5 定义服务提供者
5.5.1 编辑POM.xml文件
<parent>
<groupId>com.jt.dubbo</groupId>
<artifactId>dubbo-jt</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>dubbo-jt-demo-provider</artifactId>
<dependencies>
<dependency>
<groupId>com.jt.dubbo</groupId>
<artifactId>dubbo-jt-demo-interface</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
5.5.2 编辑Service具体实现
3000) //3秒超时 (timeout=
public class UserServiceImpl implements UserService {
private UserMapper userMapper;
public List<User> findAll() {
System.out.println("我是第一个服务的提供者");
return userMapper.selectList(null);
}
public void saveUser(User user) {
userMapper.insert(user);
}
}
5.5.3 修改YML配置文件
server:
port: 9000
spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/jtdb?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true
username: root
password: root
dubbo:
scan: #包扫描
basePackages: com.jt
application:
name: provider-user
registry: #注册中心
address: zookeeper://192.168.226.128:2181?backup=192.168.226.128:2182,192.168.226.128:2183
protocol: #协议
name: dubbo #dubbo协议 TCP/IP
port: 20880 #服务唯一端口号信息
mybatis-plus:
type-aliases-package: com.jt.dubbo.pojo #配置别名包路径
mapper-locations: classpath:/mybatis/mappers/*.xml #添加mapper映射文件
configuration:
map-underscore-to-camel-case: true #开启驼峰映射规则
5.6 定义服务消费者
5.6.1 添加依赖项
<parent>
<groupId>com.jt.dubbo</groupId>
<artifactId>dubbo-jt</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>dubbo-jt-demo-consumer</artifactId>
<dependencies>
<dependency>
<groupId>com.jt.dubbo</groupId>
<artifactId>dubbo-jt-demo-interface</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
5.6.2 编辑消费者的Controller
public class UserController {
/**
* check:是否校验提供者
*/
private UserService userService;//第三方的接口
/**
* RPC表示远程过程调用,调用者使用RPC就相当于使用自己的服务
* RPC程序引入rpc时使用代理模式,
* 要求调用代理和调用真实的服务没有区别.
* @return
*/
public List<User> findAll(){
return userService.findAll();
}
public String saveUser(User user) {
userService.saveUser(user);
return "用户入库成功!!!";
}
}
5.6.3 编辑消费者YML配置文件
server:
port: 9001
dubbo:
scan:
basePackages: com.jt
application:
name: consumer-user
registry:
address: zookeeper://192.168.226.128:2181?backup=192.168.226.128:2182,192.168.226.128:2183
5.7 页面调用效果
5.8 Dubbo框架报错异常
报错异常: type user 不能转化为 type user
原因:由于springBoot的热部署导致.
解决: 重启提供者和消费者
6.1 负载均衡测试
测试说明:根据一个消费者有多个提供者的状态的配置,发现确实可以实现负载均衡.
6.2 Dubbo负载均衡策略
默认策略: 随机访问.
3000,check=true,loadbalance = "random") (timeout=
private UserService userService;//第三方的接口
@Reference(timeout=3000,check=true,loadbalance =
"roundrobin")
/**
* check:是否校验提供者
* loadbalance="负载均衡的配置"
*/
3000,check=true,loadbalance ="consistenthash") (timeout=
private UserService userService;//第三方的接口
挑选连接数较小的访问.
3000,check=true,loadbalance ="leastactive") (timeout=
private UserService userService;//第三方的接口
6.3 面试题
答案: 依然可以访问,由于消费者启动时已经将服务信息缓存到本地.
答案: 不会报错,用户依然可以正常访问.原因本地服务列表也会动态更新.
这时这个程序处于高危运行状态
7.1 重构说明
7.2 引入jar包
<!--引入dubbo配置 -->
<dependency>
<groupId>com.alibaba.boot</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>0.2.0</version>
</dependency>
7.3 定义公共的API接口
//定义公共的API接口
public interface DubboUserService {
}
7.4 定义jt-sso的提供者
7.4.1 编辑YML配置
server:
port: 8093
servlet:
context-path: /
spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/jtdb?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true
username: root
password: root
#mybatis-plush配置
mybatis-plus:
type-aliases-package: com.jt.pojo
mapper-locations: classpath:/mybatis/mappers/*.xml
configuration:
map-underscore-to-camel-case: true
#引入日志信息
logging:
level:
com.jt.mapper: debug
dubbo:
scan: #包扫描
basePackages: com.jt
application:
name: provider-user
registry: #注册中心
address: zookeeper://192.168.226.128:2181?backup=192.168.226.128:2182,192.168.226.128:2183
protocol: #协议
name: dubbo #dubbo协议 TCP/IP
port: 20880 #服务唯一端口号信息
7.4.2 创建Dubbo的UserService实现类
//dubbo注解
public class DubboUserServiceImpl implements DubboUserService {
private UserMapper userMapper;
}
7.5 服务消费者改造
7.5.1 编辑jt-web的YML配置文件
server:
port: 8092
spring: #定义springmvc视图解析器
mvc:
view:
prefix: /WEB-INF/views/
suffix: .jsp
dubbo:
scan:
basePackages: com.jt
application:
name: consumer-web
registry:
address: zookeeper://192.168.226.128:2181?backup=192.168.226.128:2182,192.168.226.128:2183
7.5.2 编辑UserController
说明:注入中立第三方接口.
8.1 需求说明
当用户通过form表单提交参数时,将数据首先通过jt-web服务器传递参数.之后发起RPC调用jt-sso服务器.实现用户的注册.
8.2 页面分析
检查页面JS,确定返回值数据. 返回值结果SysResult对象
$.ajax({
type : "POST",
url : "/user/doRegister",
contentType : "application/x-www-form-urlencoded; charset=utf-8",
data : {password:_password,username:_username,phone:_phone},
dataType : 'json',
success : function(result) {
if(result.status == "200"){
// 注册成功,去登录页
showMessage('注册成功,请登录!');
verc();
$("#registsubmit").removeAttr("disabled").removeClass()
.addClass("btn-img btn-regist");
isSubmit = false;
return;
}else{
showMessage('注册失败,请联系管理员!');
//alert('注册失败,请重新注册! ' + result.data );
}
8.3 编辑UserController
/**
* password: admin123
username: admin1909
phone: 13212313121
* @return
*/
//转化JSON
public SysResult saveUser(User user) {
userService.saveUser(user);//RPC调用
return SysResult.success();
}
8.4 编辑UserService
//dubbo注解
public class DubboUserServiceImpl implements DubboUserService {
private UserMapper userMapper;
/**
* 1.密码明文 需要加密 md5/md5Hash
* 2.需要添加创建/更新时间
* 3.暂时使用phone代替email email为非null
*/
public void saveUser(User user) {
String password = user.getPassword();
String md5Pass = DigestUtils
.md5DigestAsHex
(password.getBytes());
user.setPassword(md5Pass)
.setEmail(user.getPhone())
.setCreated(new Date())
.setUpdated(user.getCreated());
userMapper.insert(user);
}
}
8.5 页面效果
扫描二维码
获取更多收获
MyMethod
以上是关于高并发Day16--Dubbo&Zookeeper的主要内容,如果未能解决你的问题,请参考以下文章
Day434.订单&库存服务分布式事务的最终解决 -谷粒商城
Day434.订单&库存服务分布式事务的最终解决 -谷粒商城