分布式:
什么是分布式系统:分布式系统是若干个独立计算机的集合,这些计算机对于用户来说就像是单个相关系统。
分布式系统是由一组通过网络进行通信,为了完成共同的任务而协调工作的计算机节点组成的系统,分布式系统的出现是为了用廉价的普通的机器完成单个计算机无法完成的计算,存储任务,目的是利用更多的机器,处理更多的数据。
RPC:远程过程调用
是一种进程间通信方式,是一种技术思想,而不是规范,它允许程序调用另一个地址空间(通常是共享网络的另一台机器上)的过程或函数,而不是程序员显式编码这个远程调用的细节,即程序员无论是调用本地的还是远程的函数,本质上编写的调用代码基本相同。
核心模块:通讯,序列化
序列化:数据传输都需要转换,
------------------------------------------------------
Dubbbo:高性能,轻量级的开源JavaRPC框架,他提供了三大核心能力:,面向接口的远程方法调用,智能容错和负载均衡,以及自动注册和发现。
Dubbo是一个分布式、高性能、透明化的RPC服务框架,提供服务自动注册、自动发现等高效服务治理方案,可以和Spring框架无缝集成。
这句话有5个点要掌握:
- 分布式:即应用场景是系统拆分,A系统和B系统需要通讯的情况下,需要一个RPC框架;
- 高性能:要支持集群、负载均衡及容错机制;
- 透明化:即远程方法调用,就像调用本地方法一样,只需简单配置,没有任何API侵入;
- 自动注册:默认使用zookeeper,提供:配置维护、域名服务、分布式同步、组服务等;
- 服务治理:这个原理有些抽象,我还没了解透,先不说了。
Dubbo的主要应用场景
透明化的远程方法调用,就像调用本地方法一样调用远程方法,只需简单配置,没有任何API侵入。
软负载均衡及容错机制,可在内网替代F5等硬件负载均衡器,降低成本,减少单点。(F5负载均衡器我也是百度来的)。
服务自动注册与发现,不再需要写死服务提供方地址,注册中心基于接口名查询服务提供者的IP地址,并且能够平滑添加或删除服务提供者。
Dubbo服务注册与发现的流程
这张图是在dubbo官网上下载的:
流程说明:
0.Provider(提供者)绑定指定端口并启动服务;
1.提供者连接注册中心,并发送本机IP、端口、应用信息和提供服务信息至注册中心存储;
2.Consumer(消费者),订阅注册中心 ,并发送应用信息、所求服务信息至注册中心;
3.注册中心根据消费者所求服务信息匹配对应的提供者列表发送至Consumer应用缓存。
4.Consumer在发起远程调用时基于缓存的提供者列表择其一发起调用;
5.消费者调用服务次数count等信息,定时发送到监控中心用于监控。
注意两点:
第3步,Provider状态变更会实时通知注册中心、注册中心是基于长连接推送变更给Consumer。
注册中心始终不代替调用者发送请求到服务提供者,它只是告诉调用者服务方地址,调用方根据具体地址请求服务,即第4步的invoke。
Dubbo有些哪些注册中心?
- Multicast注册中心:Multicast注册中心不需要任何中心节点,只要广播地址,就能进行服务注册和发现。基于网络中组播传输实现。
- Zookeeper注册中心:基于分布式协调系统Zookeeper实现,采用Zookeeper的watch机制实现数据变更。这种也是dubbo默认采用的注册中心。
- redis注册中心:基于redis实现,采用key/Map存储,住key存储服务名和类型,Map中key存储服务URL,value服务过期时间。基于redis的发布/订阅模式通知数据变更。
- Simple注册中心。
- ------------------------------------------------------------------------------
zookeeper:
ZooKeeper 是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是Hadoop和Hbase的重要组件。它是一个为分布式应用提供一致性服务的软件,提供的功能包括:配置维护、域名服务、分布式同步、组服务等。
ZooKeeper的特性
Leader 选举是 Zookeeper 最重要的技术之一,也是保障分布式数据一致性的关键所在。我们以三台机器为例,在服务器集群初始化阶段,当有一台服务器Server1启动时候是无法完成选举的,当第二台机器 Server2 启动后两台机器能互相通信,每台机器都试图找到一个leader,于是便进入了 leader 选举流程.
- 顺序一致性,从同一个客户端发起的事务请求,最终将会严格地按照其发起顺序被应用到Zookeeper中去。
- 原子性,所有事务请求的处理结果在整个集群中所有机器上的应用情况是一致的,即整个集群要么都成功应用了某个事务,要么都没有应用。
- 单一视图,无论客户端连接的是哪个 Zookeeper 服务器,其看到的服务端数据模型都是一致的。
- 可靠性,一旦服务端成功地应用了一个事务,并完成对客户端的响应,那么该事务所引起的服务端状态变更将会一直被保留,除非有另一个事务对其进行了变更。
- 实时性,Zookeeper 保证在一定的时间段内,客户端最终一定能够从服务端上读取到最新的数据状态。
-
集群角色
Leader:是整个 Zookeeper 集群工作机制中的核心 。Leader 作为整个 ZooKeeper 集群的主节点,负责响应所有对 ZooKeeper 状态变更的请求。
主要工作: - 事务请求的唯一调度和处理,保障集群处理事务的顺序性。
- 集群内各服务器的调度者。
- 每个 server 发出一个投票
投票的最基本元素是(SID-服务器id,ZXID-事物id) - 接受来自各个服务器的投票
- 处理投票
优先检查 ZXID(数据越新ZXID越大),ZXID比较大的作为leader,ZXID一样的情况下比较SID - 统计投票
这里有个过半的概念,大于集群机器数量的一半,即大于或等于(n/2+1),我们这里的由三台,大于等于2即为达到“过半”的要求。
这里也有引申到为什么 Zookeeper 集群推荐是单数。
--------------------------------------------------------
dubbo+zookeeper实例环境搭建
环境搭建:
先安装zookeeper(注册中心):如果闪退改两个配置即可,一个是cof,一个是启动服务加一段话。
ls /
create -e /lingdu 123
再安装:dubbo-admin
先打包:
mvn clean package -Dmaven.test.skip=true
之后打开zoopeper:
再运行:
java -jar dubbo-admin-0.0.1-SNAPSHOT.jar
密码账号:root
dubbo-admin:是一个监控管理后台,查看我们注册了哪些服务,哪些服务被消费了。
Dubbo:jar包
步骤:
前提;zookeper服务已经开启
- 提供者提供服务
导入依赖,
<!-- 导入Dubbo=zookeeper依赖-->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>2.7.8</version>
</dependency>
<!-- zkclint-->
<dependency>
<groupId>com.github.sgroschupf</groupId>
<artifactId>zkclient</artifactId>
<version>0.1</version>
</dependency>
<!-- 日志会冲突,引入zookerper-->
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>2.12.0</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>2.12.0</version>
</dependency>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.5.7</version>
<!-- 排除slf-log4j-->
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
</exclusions>
</dependency>
配置注册中心的地址以及服务器发现名,和要扫描的包:
server.port=8001
#服务应用名字
dubbo.application.name=provider-server
#注册中心地址
dubbo.registry.address=zookeeper://127.0.0.1:2181
#哪些服务要被注册
dubbo.scan.base-packages=com.zhang.service
在想要被注册的服务上面加一个注解
注意接口的这个地方的注解别错了。
//zookeper服务注册与发现
@DubboService
@Component //这里使用了dubbo,尽量不用service注解
public class TicketServiceimpl implements TicketService{
@Override
public String getTicket(){
return "你好,零度";
}
}
消费者如何消费:
导入依赖(和上面的一样)
配置注册中心的地址,配置自己的服务名
server.port=8002
#消费者哪里获取服务器需要暴露自己的名字
dubbo.application.name=dubbo-consumer
#注册中心地址
dubbo.registry.address=zookeeper://127.0.0.1:2181
从远程注入服务。@DubboReference
@Service//放到容器中
public class UserService {
//想要拿到另一个模块的票,去注册中心拿服务
@DubboReference
TicketService ticketService;
public void buyTicket(){
String ticket = ticketService.getTicket();
System.out.println("再注册中心拿到=》"+ticket);
}