资料搜集-JAVA系统的梳理知识17- RPC

 

## 什么是 RPC?RPC原理是什么?

### **什么是 RPC?**

RPC(Remote Procedure Call)—远程过程调用,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。比如两个不同的服务 A、B 部署在两台不同的机器上,那么服务 A 如果想要调用服务 B 中的某个方法该怎么办呢?使用 HTTP请求 当然可以,但是可能会比较慢而且一些优化做的并不好。 RPC 的出现就是为了解决这个问题。

### **RPC原理是什么?**

我这里这是简单的提一下,详细内容可以查看下面这篇文章:

http://www.importnew.com/22003.html

![RPC原理图](http://my-blog-to-use.oss-cn-beijing.aliyuncs.com/18-12-6/37345851.jpg)

1. 服务消费方(client)调用以本地调用方式调用服务;
2. client stub接收到调用后负责将方法、参数等组装成能够进行网络传输的消息体;
3. client stub找到服务地址,并将消息发送到服务端;
4. server stub收到消息后进行解码;
5. server stub根据解码结果调用本地的服务;
6. 本地服务执行并将结果返回给server stub;
7. server stub将返回结果打包成消息并发送至消费方;
8. client stub接收到消息,并进行解码;
9. 服务消费方得到最终结果。

下面再贴一个网上的时序图:

![RPC原理时序图](http://my-blog-to-use.oss-cn-beijing.aliyuncs.com/18-12-6/32527396.jpg)

### RPC 解决了什么问题?

从上面对 RPC 介绍的内容中,概括来讲RPC 主要解决了:**让分布式或者微服务系统中不同服务之间的调用像本地调用一样简单。**

### 常见的 RPC 框架总结?

- **RMI(JDK自带):** JDK自带的RPC,有很多局限性,不推荐使用。
- **Dubbo:** Dubbo是 阿里巴巴公司开源的一个高性能优秀的服务框架,使得应用可通过高性能的 RPC 实现服务的输出和输入功能,可以和 Spring框架无缝集成。目前 Dubbo 已经成为 Spring Cloud Alibaba 中的官方组件。
- **gRPC** :gRPC是可以在任何环境中运行的现代开源高性能RPC框架。它可以通过可插拔的支持来有效地连接数据中心内和跨数据中心的服务,以实现负载平衡,跟踪,运行状况检查和身份验证。它也适用于分布式计算的最后一英里,以将设备,移动应用程序和浏览器连接到后端服务。

- **Hessian:** Hessian是一个轻量级的remotingonhttp工具,使用简单的方法提供了RMI的功能。 相比WebService,Hessian更简单、快捷。采用的是二进制RPC协议,因为采用的是二进制协议,所以它很适合于发送二进制数据。
- **Thrift:**  Apache Thrift是Facebook开源的跨语言的RPC通信框架,目前已经捐献给Apache基金会管理,由于其跨语言特性和出色的性能,在很多互联网公司得到应用,有能力的公司甚至会基于thrift研发一套分布式服务框架,增加诸如服务注册、服务发现等功能。

## 既有 HTTP ,为啥用 RPC 进行服务调用?

###RPC 只是一种设计而已

RPC 只是一种概念、一种设计,就是为了解决 **不同服务之间的调用问题**, 它一般会包含有 **传输协议** 和 **序列化协议** 这两个。

实现 RPC 的可以传输协议可以直接建立在 TCP 之上,也可以建立在 HTTP 协议之上。**大部分 RPC 框架都是使用的 TCP 连接(gRPC使用了HTTP2)。**

### HTTP 和 TCP

**可能现在很多对计算机网络不太熟悉的朋友已经被搞蒙了,要想真正搞懂,还需要来简单复习一下计算机网络基础知识:**

> 我们通常谈计算机网络的五层协议的体系结构是指:应用层、传输层、网络层、数据链路层、物理层。
>
> **应用层(application-layer)的任务是通过应用进程间的交互来完成特定网络应用。**HTTP 属于应用层协议,它会基于TCP/IP通信协议来传递数据(HTML 文件, 图片文件, 查询结果等)。HTTP协议工作于客户端-服务端架构为上。浏览器作为HTTP客户端通过 URL 向HTTP服务端即WEB服务器发送所有请求。Web服务器根据接收到的请求后,向客户端发送响应信息。HTTP协议建立在 TCP 协议之上。
>
> **运输层(transport layer)的主要任务就是负责向两台主机进程之间的通信提供通用的数据传输服务**。TCP是传输层协议,主要解决数据如何在网络中传输。相比于UDP,**TCP** 提供的是**面向连接**的,**可靠的**数据传输服务。

**主要关键就在 HTTP 使用的 TCP 协议,和我们自定义的 TCP 协议在报文上的区别。**

**http1.1协议的 TCP 报文包含太多在传输过程中可能无用的信息:**

```
HTTP/1.0 200 OK 
Content-Type: text/plain
Content-Length: 137582
Expires: Thu, 05 Dec 1997 16:00:00 GMT
Last-Modified: Wed, 5 August 1996 15:55:28 GMT
Server: Apache 0.84


  Hello World

```

**使用自定义 TCP 协议进行传输就会避免上面这个问题,极大地减轻了传输数据的开销。**
这也就是为什么通常会采用自定义 TCP 协议的 RPC
来进行进行服务调用的真正原因。除此之外,成熟的 RPC
框架还提供好了“服务自动注册与发现”、"智能负载均衡"、“可视化的服务治理和运维”、“运行期流量调度”等等功能,这些也算是选择
RPC 进行服务注册和发现的一方面原因吧!

**相关阅读:**

- http://www.ruanyifeng.com/blog/2016/08/http.html (HTTP 协议入门- 阮一峰)

### 一个常见的错误观点

很多文章中还会提到说 HTTP 协议相较于自定义 TCP 报文协议,增加的开销在于连接的建立与断开,但是这个观点已经被否认,下面截取自知乎中一个回答,原回答地址:https://www.zhihu.com/question/41609070/answer/191965937。

>首先要否认一点 HTTP 协议相较于自定义 TCP 报文协议,增加的开销在于连接的建立与断开。HTTP 协议是支持连接池复用的,也就是建立一定数量的连接不断开,并不会频繁的创建和销毁连接。二一要说的是 HTTP 也可以使用 Protobuf 这种二进制编码协议对内容进行编码,因此二者最大的区别还是在传输协议上。

### 题外话

除此之外,还需要注意的一点是 Spring Cloud Netflix 并没有使用 RPC
框架来进行不同服务之间的调用,而是使用 HTTP 协议进行调用的,速度虽然不比 RPC
,但是使用 HTTP 协议也会带来其他很多好处(这一点,可以自行查阅相关资料了解)。



> ## RPC

**RPC(Remote Procedure Call)—远程过程调用** ,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。RPC协议假定某些传输协议的存在,如TCP或UDP,为通信程序之间携带信息数据。在OSI网络通信模型中,RPC跨越了传输层和应用层。RPC使得开发分布式程序就像开发本地程序一样简单。

**RPC采用客户端(服务调用方)/服务器端(服务提供方)模式,** 都运行在自己的JVM中。客户端只需要引入要使用的接口,接口的实现和运行都在服务器端。RPC主要依赖的技术包括序列化、反序列化和数据传输协议,这是一种定义与实现相分离的设计。

**目前Java使用比较多的RPC方案主要有RMI(JDK自带)、Hessian、Dubbo以及Thrift等。**

**注意: RPC主要指内部服务之间的调用,RESTful也可以用于内部服务之间的调用,但其主要用途还在于外部系统提供服务,因此没有将其包含在本知识点内。**

### 常见RPC框架:

- **RMI(JDK自带):** JDK自带的RPC
 
   详细内容可以参考:[从懵逼到恍然大悟之Java中RMI的使用](https://blog.csdn.net/lmy86263/article/details/72594760)

- **Dubbo:** Dubbo是 阿里巴巴公司开源的一个高性能优秀的服务框架,使得应用可通过高性能的 RPC 实现服务的输出和输入功能,可以和 Spring框架无缝集成。

  详细内容可以参考:

  - [ 高性能优秀的服务框架-dubbo介绍](https://blog.csdn.net/qq_34337272/article/details/79862899)
  
  - [Dubbo是什么?能做什么?](https://blog.csdn.net/houshaolin/article/details/76408399)
 

- **Hessian:** Hessian是一个轻量级的remotingonhttp工具,使用简单的方法提供了RMI的功能。 相比WebService,Hessian更简单、快捷。采用的是二进制RPC协议,因为采用的是二进制协议,所以它很适合于发送二进制数据。

  详细内容可以参考: [Hessian的使用以及理解](https://blog.csdn.net/sunwei_pyw/article/details/74002351)

- **Thrift:**  Apache Thrift是Facebook开源的跨语言的RPC通信框架,目前已经捐献给Apache基金会管理,由于其跨语言特性和出色的性能,在很多互联网公司得到应用,有能力的公司甚至会基于thrift研发一套分布式服务框架,增加诸如服务注册、服务发现等功能。
  

    详细内容可以参考: [【Java】分布式RPC通信框架Apache Thrift 使用总结](https://www.cnblogs.com/zeze/p/8628585.html)
  
### 如何进行选择:

- **是否允许代码侵入:**  即需要依赖相应的代码生成器生成代码,比如Thrift。
- **是否需要长连接获取高性能:**  如果对于性能需求较高的haul,那么可以果断选择基于TCP的Thrift、Dubbo。
- **是否需要跨越网段、跨越防火墙:** 这种情况一般选择基于HTTP协议的Hessian和Thrift的HTTP Transport。

此外,Google推出的基于HTTP2.0的gRPC框架也开始得到应用,其序列化协议基于Protobuf,网络框架使用的是Netty4,但是其需要生成代码,可扩展性也比较差。  

> ## 消息中间件

**消息中间件,也可以叫做中央消息队列或者是消息队列(区别于本地消息队列,本地消息队列指的是JVM内的队列实现)**,是一种独立的队列系统,消息中间件经常用来解决内部服务之间的 **异步调用问题** 。请求服务方把请求队列放到队列中即可返回,然后等待服务提供方去队列中获取请求进行处理,之后通过回调等机制把结果返回给请求服务方。

异步调用只是消息中间件一个非常常见的应用场景。此外,常用的消息队列应用场景还有如下几个:
- **解耦 :** 一个业务的非核心流程需要依赖其他系统,但结果并不重要,有通知即可。
- **最终一致性 :** 指的是两个系统的状态保持一致,可以有一定的延迟,只要最终达到一致性即可。经常用在解决分布式事务上。
- **广播 :** 消息队列最基本的功能。生产者只负责生产消息,订阅者接收消息。
- **错峰和流控**


具体可以参考: 
 
[《消息队列深入解析》](https://blog.csdn.net/qq_34337272/article/details/80029918)

当前使用较多的消息队列有ActiveMQ(性能差,不推荐使用)、RabbitMQ、RocketMQ、Kafka等等,我们之前提到的redis数据库也可以实现消息队列,不过不推荐,redis本身设计就不是用来做消息队列的。

-  **ActiveMQ:** ActiveMQ是Apache出品,最流行的,能力强劲的开源消息总线。ActiveMQ是一个完全支持JMS1.1和J2EE 1.4规范的JMSProvider实现,尽管JMS规范出台已经是很久的事情了,但是JMS在当今的J2EE应用中间仍然扮演着特殊的地位。

   具体可以参考: 
   
   [《消息队列ActiveMQ的使用详解》](https://blog.csdn.net/qq_34337272/article/details/80031702)
 
- **RabbitMQ:** RabbitMQ 是一个由 Erlang 语言开发的 AMQP 的开源实现。RabbitMQ 最初起源于金融系统,用于在分布式系统中存储转发消息,在易用性、扩展性、高可用性等方面表现不俗
    > AMQP :Advanced Message Queue,高级消息队列协议。它是应用层协议的一个开放标准,为面向消息的中间件设计,基于此协议的客户端与消息中间件可传递消息,并不受产品、开发语言等条件的限制。


   具体可以参考:
   
   [《消息队列之 RabbitMQ》](https://www.jianshu.com/p/79ca08116d57)

- **RocketMQ:**
   
   具体可以参考:
   
   [《RocketMQ 实战之快速入门》](https://www.jianshu.com/p/824066d70da8)

   [《十分钟入门RocketMQ》](http://jm.taobao.org/2017/01/12/rocketmq-quick-start-in-10-minutes/) (阿里中间件团队博客)


- **Kafka**:Kafka是一个分布式的、可分区的、可复制的、基于发布/订阅的消息系统(现在官方的描述是“一个分布式流平台”),Kafka主要用于大数据领域,当然在分布式系统中也有应用。目前市面上流行的消息队列RocketMQ就是阿里借鉴Kafka的原理、用Java开发而得。
  
  具体可以参考:

  [《Kafka应用场景》](http://book.51cto.com/art/201801/565244.htm)
   
  [《初谈Kafka》](https://mp.weixin.qq.com/s?__biz=MzU4NDQ4MzU5OA==&mid=2247484106&idx=1&sn=aa1999895d009d91eb3692a3e6429d18&chksm=fd9854abcaefddbd1101ca5dc2c7c783d7171320d6300d9b2d8e68b7ef8abd2b02ea03e03600#rd)

**推荐阅读:**

[《Kafka、RabbitMQ、RocketMQ等消息中间件的对比 —— 消息发送性能和区别》](https://mp.weixin.qq.com/s?__biz=MzU5OTMyODAyNg==&mid=2247484721&idx=1&sn=11e4e29886e581dd328311d308ccc068&chksm=feb7d144c9c058529465b02a4e26a25ef76b60be8984ace9e4a0f5d3d98ca52e014ecb73b061&scene=21#wechat_redirect)







鏈枃鏉ヨ嚜璇昏�� [PR](https://github.com/Snailclimb/JavaGuide/pull/291)銆�


- [1 鍗曟満鐗堟秷鎭腑蹇僝(#1-%E5%8D%95%E6%9C%BA%E7%89%88%E6%B6%88%E6%81%AF%E4%B8%AD%E5%BF%83)
- [2 鍒嗗竷寮忔秷鎭腑蹇僝(#2-%E5%88%86%E5%B8%83%E5%BC%8F%E6%B6%88%E6%81%AF%E4%B8%AD%E5%BF%83)
  - [2.1 闂涓庤В鍐砞(#21-%E9%97%AE%E9%A2%98%E4%B8%8E%E8%A7%A3%E5%86%B3)
    - [2.1.1 娑堟伅涓㈠け鐨勯棶棰榏(#211-%E6%B6%88%E6%81%AF%E4%B8%A2%E5%A4%B1%E7%9A%84%E9%97%AE%E9%A2%98)
    - [2.1.2 鍚屾钀界洏鎬庝箞鎵嶈兘蹇玗(#212-%E5%90%8C%E6%AD%A5%E8%90%BD%E7%9B%98%E6%80%8E%E4%B9%88%E6%89%8D%E8%83%BD%E5%BF%AB)
    - [2.1.3 娑堟伅鍫嗙Н鐨勯棶棰榏(#213-%E6%B6%88%E6%81%AF%E5%A0%86%E7%A7%AF%E7%9A%84%E9%97%AE%E9%A2%98)
    - [2.1.4 瀹氭椂娑堟伅鐨勫疄鐜癩(#214-%E5%AE%9A%E6%97%B6%E6%B6%88%E6%81%AF%E7%9A%84%E5%AE%9E%E7%8E%B0)
    - [2.1.5 椤哄簭娑堟伅鐨勫疄鐜癩(#215-%E9%A1%BA%E5%BA%8F%E6%B6%88%E6%81%AF%E7%9A%84%E5%AE%9E%E7%8E%B0)
    - [2.1.6 鍒嗗竷寮忔秷鎭殑瀹炵幇](#216-%E5%88%86%E5%B8%83%E5%BC%8F%E6%B6%88%E6%81%AF%E7%9A%84%E5%AE%9E%E7%8E%B0)
    - [2.1.7 娑堟伅鐨� push 瀹炵幇](#217-%E6%B6%88%E6%81%AF%E7%9A%84-push-%E5%AE%9E%E7%8E%B0)
    - [2.1.8 娑堟伅閲嶅鍙戦�佺殑閬垮厤](#218-%E6%B6%88%E6%81%AF%E9%87%8D%E5%A4%8D%E5%8F%91%E9%80%81%E7%9A%84%E9%81%BF%E5%85%8D)
    - [2.1.9 骞挎挱娑堣垂涓庨泦缇ゆ秷璐筣(#219-%E5%B9%BF%E6%92%AD%E6%B6%88%E8%B4%B9%E4%B8%8E%E9%9B%86%E7%BE%A4%E6%B6%88%E8%B4%B9)
    - [2.1.10 RocketMQ 涓嶄娇鐢� ZooKeeper 浣滀负娉ㄥ唽涓績鐨勫師鍥狅紝浠ュ強鑷埗鐨� NameServer 浼樼己鐐癸紵](#2110-rocketmq-%E4%B8%8D%E4%BD%BF%E7%94%A8-zookeeper-%E4%BD%9C%E4%B8%BA%E6%B3%A8%E5%86%8C%E4%B8%AD%E5%BF%83%E7%9A%84%E5%8E%9F%E5%9B%A0%E4%BB%A5%E5%8F%8A%E8%87%AA%E5%88%B6%E7%9A%84-nameserver-%E4%BC%98%E7%BC%BA%E7%82%B9)
    - [2.1.11 鍏跺畠](#2111-%E5%85%B6%E5%AE%83)
- [3 鍙傝�僝(#3-%E5%8F%82%E8%80%83)



# 1 鍗曟満鐗堟秷鎭腑蹇�

涓�涓秷鎭腑蹇冿紝鏈�鍩烘湰鐨勯渶瑕佹敮鎸佸鐢熶骇鑰呫�佸娑堣垂鑰咃紝渚嬪涓嬶細

```java
class Scratch {

    public static void main(String[] args) {
        // 瀹為檯涓細鏈� nameserver 鏈嶅姟鏉ユ壘鍒� broker 鍏蜂綋浣嶇疆浠ュ強 broker 涓讳粠淇℃伅
        Broker broker = new Broker();
        Producer producer1 = new Producer();
        producer1.connectBroker(broker);
        Producer producer2 = new Producer();
        producer2.connectBroker(broker);

        Consumer consumer1 = new Consumer();
        consumer1.connectBroker(broker);
        Consumer consumer2 = new Consumer();
        consumer2.connectBroker(broker);

        for (int i = 0; i < 2; i++) {
            producer1.asyncSendMsg("producer1 send msg" + i);
            producer2.asyncSendMsg("producer2 send msg" + i);
        }
        System.out.println("broker has msg:" + broker.getAllMagByDisk());

        for (int i = 0; i < 1; i++) {
            System.out.println("consumer1 consume msg锛�" + consumer1.syncPullMsg());
        }
        for (int i = 0; i < 3; i++) {
            System.out.println("consumer2 consume msg锛�" + consumer2.syncPullMsg());
        }
    }

}

class Producer {

    private Broker broker;

    public void connectBroker(Broker broker) {
        this.broker = broker;
    }

    public void asyncSendMsg(String msg) {
        if (broker == null) {
            throw new RuntimeException("please connect broker first");
        }
        new Thread(() -> {
            broker.sendMsg(msg);
        }).start();
    }
}

class Consumer {
    private Broker broker;

    public void connectBroker(Broker broker) {
        this.broker = broker;
    }

    public String syncPullMsg() {
        return broker.getMsg();
    }

}

class Broker {

    // 瀵瑰簲 RocketMQ 涓� MessageQueue锛岄粯璁ゆ儏鍐典笅 1 涓� Topic 鍖呭惈 4 涓� MessageQueue
    private LinkedBlockingQueue messageQueue = new LinkedBlockingQueue(Integer.MAX_VALUE);

    // 瀹為檯鍙戦�佹秷鎭埌 broker 鏈嶅姟鍣ㄤ娇鐢� Netty 鍙戦��
    public void sendMsg(String msg) {
        try {
            messageQueue.put(msg);
            // 瀹為檯浼氬悓姝ユ垨寮傛钀界洏锛屽紓姝ヨ惤鐩樹娇鐢ㄧ殑瀹氭椂浠诲姟瀹氭椂鎵弿钀界洏
        } catch (InterruptedException e) {

        }
    }

    public String getMsg() {
        try {
            return messageQueue.take();
        } catch (InterruptedException e) {

        }
        return null;
    }

    public String getAllMagByDisk() {
        StringBuilder sb = new StringBuilder("\n");
        messageQueue.iterator().forEachRemaining((msg) -> {
            sb.append(msg + "\n");
        });
        return sb.toString();
    }
}
```

闂锛�  
1. 娌℃湁瀹炵幇鐪熸鎵ц娑堟伅瀛樺偍钀界洏
2. 娌℃湁瀹炵幇 NameServer 鍘讳綔涓烘敞鍐屼腑蹇冿紝瀹氫綅鏈嶅姟
3. 浣跨敤 LinkedBlockingQueue 浣滀负娑堟伅闃熷垪锛屾敞鎰忥紝鍙傛暟鏄棤闄愬ぇ锛屽湪鐪熸 RocketMQ 涔熸槸濡傛鏄棤闄愬ぇ锛岀悊璁轰笂涓嶄細鍑虹幇瀵硅繘鏉ョ殑鏁版嵁杩涜鎶涘純锛屼絾鏄細鏈夊唴瀛樻硠婕忛棶棰橈紙闃块噷宸村反寮�鍙戞墜鍐屼篃鍥犱负杩欎釜闂锛屽缓璁垜浠娇鐢ㄨ嚜鍒剁嚎绋嬫睜锛�  
4. 娌℃湁浣跨敤澶氫釜闃熷垪锛堝嵆澶氫釜 LinkedBlockingQueue锛夛紝RocketMQ 鐨勯『搴忔秷鎭槸閫氳繃鐢熶骇鑰呭拰娑堣垂鑰呭悓鏃朵娇鐢ㄥ悓涓�涓� MessageQueue 鏉ュ疄鐜帮紝浣嗘槸濡傛灉鎴戜滑鍙湁涓�涓� MessageQueue锛岄偅鎴戜滑澶╃劧灏辨敮鎸侀『搴忔秷鎭�
5. 娌℃湁浣跨敤 MappedByteBuffer 鏉ュ疄鐜版枃浠舵槧灏勪粠鑰屼娇娑堟伅鏁版嵁钀界洏闈炲父鐨勫揩锛堝疄闄� RocketMQ 浣跨敤鐨勬槸 FileChannel+DirectBuffer锛�

# 2 鍒嗗竷寮忔秷鎭腑蹇�

## 2.1 闂涓庤В鍐�

### 2.1.1 娑堟伅涓㈠け鐨勯棶棰�

1. 褰撲綘绯荤粺闇�瑕佷繚璇佺櫨鍒嗙櫨娑堟伅涓嶄涪澶憋紝浣犲彲浠ヤ娇鐢ㄧ敓浜ц�呮瘡鍙戦�佷竴涓秷鎭紝Broker 鍚屾杩斿洖涓�涓秷鎭彂閫佹垚鍔熺殑鍙嶉娑堟伅
2. 鍗虫瘡鍙戦�佷竴涓秷鎭紝鍚屾钀界洏鍚庢墠杩斿洖鐢熶骇鑰呮秷鎭彂閫佹垚鍔燂紝杩欐牱鍙鐢熶骇鑰呭緱鍒颁簡娑堟伅鍙戦�佺敓鎴愮殑杩斿洖锛屼簨鍚庨櫎浜嗙‖鐩樻崯鍧忥紝閮藉彲浠ヤ繚璇佷笉浼氭秷鎭涪澶�
3. 浣嗘槸杩欏悓鏃跺紩鍏ヤ簡涓�涓棶棰橈紝鍚屾钀界洏鎬庝箞鎵嶈兘蹇紵

### 2.1.2 鍚屾钀界洏鎬庝箞鎵嶈兘蹇�

1. 浣跨敤 FileChannel + DirectBuffer 姹狅紝浣跨敤鍫嗗鍐呭瓨锛屽姞蹇唴瀛樻嫹璐�  
2. 浣跨敤鏁版嵁鍜岀储寮曞垎绂伙紝褰撴秷鎭渶瑕佸啓鍏ユ椂锛屼娇鐢� commitlog 鏂囦欢椤哄簭鍐欙紝褰撻渶瑕佸畾浣嶆煇涓秷鎭椂锛屾煡璇ndex 鏂囦欢鏉ュ畾浣嶏紝浠庤�屽噺灏戞枃浠禝O闅忔満璇诲啓鐨勬�ц兘鎹熻��

### 2.1.3 娑堟伅鍫嗙Н鐨勯棶棰�

1. 鍚庡彴瀹氭椂浠诲姟姣忛殧72灏忔椂锛屽垹闄ゆ棫鐨勬病鏈変娇鐢ㄨ繃鐨勬秷鎭俊鎭�  
2. 鏍规嵁涓嶅悓鐨勪笟鍔″疄鐜颁笉鍚岀殑涓㈠純浠诲姟锛屽叿浣撳弬鑰冪嚎绋嬫睜鐨� AbortPolicy锛屼緥濡侳IFO/LRU绛夛紙RocketMQ娌℃湁姝ょ瓥鐣ワ級  
3. 娑堟伅瀹氭椂杞Щ锛屾垨鑰呭鏌愪簺閲嶈鐨� TAG 鍨嬶紙鏀粯鍨嬶級娑堟伅鐪熸钀藉簱
   
### 2.1.4 瀹氭椂娑堟伅鐨勫疄鐜�

1. 瀹為檯 RocketMQ 娌℃湁瀹炵幇浠绘剰绮惧害鐨勫畾鏃舵秷鎭紝瀹冨彧鏀寔鏌愪簺鐗瑰畾鐨勬椂闂寸簿搴︾殑瀹氭椂娑堟伅
2. 瀹炵幇瀹氭椂娑堟伅鐨勫師鐞嗘槸锛氬垱寤虹壒瀹氭椂闂寸簿搴︾殑 MessageQueue锛屼緥濡傜敓浜ц�呴渶瑕佸畾鏃�1s涔嬪悗琚秷璐硅�呮秷璐癸紝浣犲彧闇�瑕佸皢姝ゆ秷鎭彂閫佸埌鐗瑰畾鐨� Topic锛屼緥濡傦細MessageQueue-1 琛ㄧず杩欎釜 MessageQueue 閲岄潰鐨勬秷鎭兘浼氬欢杩熶竴绉掕娑堣垂锛岀劧鍚� Broker 浼氬湪 1s 鍚庡彂閫佸埌娑堣垂鑰呮秷璐规娑堟伅锛屼娇鐢� newSingleThreadScheduledExecutor 瀹炵幇

### 2.1.5 椤哄簭娑堟伅鐨勫疄鐜�

1. 涓庡畾鏃舵秷鎭悓鍘熺悊锛岀敓浜ц�呯敓浜ф秷鎭椂鎸囧畾鐗瑰畾鐨� MessageQueue 锛屾秷璐硅�呮秷璐规秷鎭椂锛屾秷璐圭壒瀹氱殑 MessageQueue锛屽叾瀹炲崟鏈虹増鐨勬秷鎭腑蹇冨湪涓�涓� MessageQueue 灏卞ぉ鐒舵敮鎸佷簡椤哄簭娑堟伅
2. 娉ㄦ剰锛氬悓涓�涓� MessageQueue 淇濊瘉閲岄潰鐨勬秷鎭槸椤哄簭娑堣垂鐨勫墠鎻愭槸锛氭秷璐硅�呮槸涓茶鐨勬秷璐硅 MessageQueue锛屽洜涓哄氨绠� MessageQueue 鏄『搴忕殑锛屼絾鏄綋骞惰娑堣垂鏃讹紝杩樻槸浼氭湁椤哄簭闂锛屼絾鏄覆琛屾秷璐逛篃鍚屾椂寮曞叆浜嗕袱涓棶棰橈細
>1. 寮曞叆閿佹潵瀹炵幇涓茶
>2. 鍓嶄竴涓秷璐归樆濉炴椂鍚庨潰閮戒細琚樆濉�

### 2.1.6 鍒嗗竷寮忔秷鎭殑瀹炵幇

1. 闇�瑕佸墠缃煡璇嗭細2PC  
2. RocketMQ4.3 璧锋敮鎸侊紝鍘熺悊涓�2PC锛屽嵆涓ら樁娈垫彁浜わ紝prepared->commit/rollback
3. 鐢熶骇鑰呭彂閫佷簨鍔℃秷鎭紝鍋囪璇ヤ簨鍔℃秷鎭� Topic 涓� Topic1-Trans锛孊roker 寰楀埌鍚庨鍏堟洿鏀硅娑堟伅鐨� Topic 涓� Topic1-Prepared锛岃 Topic1-Prepared 瀵规秷璐硅�呬笉鍙銆傜劧鍚庡畾鏃跺洖璋冪敓浜ц�呯殑鏈湴浜嬪姟A鎵ц鐘舵�侊紝鏍规嵁鏈湴浜嬪姟A鎵ц鐘舵�侊紝鏉ユ槸鍚﹀皢璇ユ秷鎭慨鏀逛负 Topic1-Commit 鎴� Topic1-Rollback锛屾秷璐硅�呭氨鍙互姝e父鎵惧埌璇ヤ簨鍔℃秷鎭垨鑰呬笉鎵ц绛�

>娉ㄦ剰锛屽氨绠楁槸浜嬪姟娑堟伅鏈�鍚庡洖婊氫簡涔熶笉浼氱墿鐞嗗垹闄わ紝鍙細閫昏緫鍒犻櫎璇ユ秷鎭�

### 2.1.7 娑堟伅鐨� push 瀹炵幇

1. 娉ㄦ剰锛孯ocketMQ 宸茬粡璇翠簡鑷繁浼氭湁浣庡欢杩熼棶棰橈紝鍏朵腑灏卞寘鎷繖涓秷鎭殑 push 寤惰繜闂
2. 鍥犱负杩欏苟涓嶆槸鐪熸鐨勫皢娑堟伅涓诲姩鐨勬帹閫佸埌娑堣垂鑰咃紝鑰屾槸 Broker 瀹氭椂浠诲姟姣�5s灏嗘秷鎭帹閫佸埌娑堣垂鑰�

### 2.1.8 娑堟伅閲嶅鍙戦�佺殑閬垮厤

1. RocketMQ 浼氬嚭鐜版秷鎭噸澶嶅彂閫佺殑闂锛屽洜涓哄湪缃戠粶寤惰繜鐨勬儏鍐典笅锛岃繖绉嶉棶棰樹笉鍙伩鍏嶇殑鍙戠敓锛屽鏋滈潪瑕佸疄鐜版秷鎭笉鍙噸澶嶅彂閫侊紝閭e熀鏈お闅撅紝鍥犱负缃戠粶鐜鏃犳硶棰勭煡锛岃繕浼氫娇绋嬪簭澶嶆潅搴﹀姞澶э紝鍥犳榛樿鍏佽娑堟伅閲嶅鍙戦��
2. RocketMQ 璁╀娇鐢ㄨ�呭湪娑堣垂鑰呯鍘昏В鍐宠闂锛屽嵆闇�瑕佹秷璐硅�呯鍦ㄦ秷璐规秷鎭椂鏀寔骞傜瓑鎬х殑鍘绘秷璐规秷鎭�
3. 鏈�绠�鍗曠殑瑙e喅鏂规鏄瘡鏉℃秷璐硅褰曟湁涓秷璐圭姸鎬佸瓧娈碉紝鏍规嵁杩欎釜娑堣垂鐘舵�佸瓧娈垫潵鏄惁娑堣垂鎴栬�呬娇鐢ㄤ竴涓泦涓紡鐨勮〃锛屾潵瀛樺偍鎵�鏈夋秷鎭殑娑堣垂鐘舵�侊紝浠庤�岄伩鍏嶉噸澶嶆秷璐�
4. 鍏蜂綋瀹炵幇鍙互鏌ヨ鍏充簬娑堟伅骞傜瓑娑堣垂鐨勮В鍐虫柟妗�

### 2.1.9 骞挎挱娑堣垂涓庨泦缇ゆ秷璐�

1. 娑堟伅娑堣垂鍖哄埆锛氬箍鎾秷璐癸紝璁㈤槄璇� Topic 鐨勬秷鎭�呬滑閮戒細娑堣垂**姣忎釜**娑堟伅銆傞泦缇ゆ秷璐癸紝璁㈤槄璇� Topic 鐨勬秷鎭�呬滑鍙細鏈変竴涓幓娑堣垂**鏌愪釜**娑堟伅
2. 娑堟伅钀界洏鍖哄埆锛氬叿浣撹〃鐜板湪娑堟伅娑堣垂杩涘害鐨勪繚瀛樹笂銆傚箍鎾秷璐癸紝鐢变簬姣忎釜娑堣垂鑰呴兘鐙珛鐨勫幓娑堣垂姣忎釜娑堟伅锛屽洜姝ゆ瘡涓秷璐硅�呭悇鑷繚瀛樿嚜宸辩殑娑堟伅娑堣垂杩涘害銆傝�岄泦缇ゆ秷璐逛笅锛岃闃呬簡鏌愪釜 Topic锛岃�屾棗涓嬪張鏈夊涓� MessageQueue锛屾瘡涓秷璐硅�呴兘鍙兘浼氬幓娑堣垂涓嶅悓鐨� MessageQueue锛屽洜姝ゆ�讳綋鐨勬秷璐硅繘搴︿繚瀛樺湪 Broker 涓婇泦涓殑绠$悊

### 2.1.10 RocketMQ 涓嶄娇鐢� ZooKeeper 浣滀负娉ㄥ唽涓績鐨勫師鍥狅紝浠ュ強鑷埗鐨� NameServer 浼樼己鐐癸紵

1. ZooKeeper 浣滀负鏀寔椤哄簭涓�鑷存�х殑涓棿浠讹紝鍦ㄦ煇浜涙儏鍐典笅锛屽畠涓轰簡婊¤冻涓�鑷存�э紝浼氫涪澶变竴瀹氭椂闂村唴鐨勫彲鐢ㄦ�э紝RocketMQ 闇�瑕佹敞鍐屼腑蹇冨彧鏄负浜嗗彂鐜扮粍浠跺湴鍧�锛屽湪鏌愪簺鎯呭喌涓嬶紝RocketMQ 鐨勬敞鍐屼腑蹇冨彲浠ュ嚭鐜版暟鎹笉涓�鑷存�э紝杩欏悓鏃朵篃鏄� NameServer 鐨勭己鐐癸紝鍥犱负 NameServer 闆嗙兢闂翠簰涓嶉�氫俊锛屽畠浠箣闂寸殑娉ㄥ唽淇℃伅鍙兘浼氫笉涓�鑷�
2. 鍙﹀锛屽綋鏈夋柊鐨勬湇鍔″櫒鍔犲叆鏃讹紝NameServer 骞朵笉浼氱珛椹�氱煡鍒� Produer锛岃�屾槸鐢� Produer 瀹氭椂鍘昏姹� NameServer 鑾峰彇鏈�鏂扮殑 Broker/Consumer 淇℃伅锛堣繖绉嶆儏鍐垫槸閫氳繃 Producer 鍙戦�佹秷鎭椂锛岃礋杞藉潎琛¤В鍐筹級

### 2.1.11 鍏跺畠

![][1]

鍔犲垎椤瑰挴 
1. 鍖呮嫭缁勪欢閫氫俊闂翠娇鐢� Netty 鐨勮嚜瀹氫箟鍗忚
2. 娑堟伅閲嶈瘯璐熻浇鍧囪 绛栫暐锛堝叿浣撳弬鑰� Dubbo 璐熻浇鍧囪 绛栫暐锛�
3. 娑堟伅杩囨护鍣紙Producer 鍙戦�佹秷鎭埌 Broker锛孊roker 瀛樺偍娑堟伅淇℃伅锛孋onsumer 娑堣垂鏃惰姹� Broker 绔粠纾佺洏鏂囦欢鏌ヨ娑堟伅鏂囦欢鏃�,鍦� Broker 绔氨浣跨敤杩囨护鏈嶅姟鍣ㄨ繘琛岃繃婊わ級  
4. Broker 鍚屾鍙屽啓鍜屽紓姝ュ弻鍐欎腑 Master 鍜� Slave 鐨勪氦浜�
5. Broker 鍦� 4.5.0 鐗堟湰鏇存柊涓紩鍏ヤ簡鍩轰簬 Raft 鍗忚鐨勫鍓湰閫変妇锛屼箣鍓嶈繖鏄晢涓氱増鎵嶆湁鐨勭壒鎬� [ISSUE-1046][2]

# 3 鍙傝��

1. 銆奟ocketMQ鎶�鏈唴骞曘�嬶細https://blog.csdn.net/prestigeding/article/details/85233529
2. 鍏充簬 RocketMQ 瀵� MappedByteBuffer 鐨勪竴鐐逛紭鍖栵細https://lishoubo.github.io/2017/09/27/MappedByteBuffer%E7%9A%84%E4%B8%80%E7%82%B9%E4%BC%98%E5%8C%96/
3. 闃块噷涓棿浠跺洟闃熷崥瀹�-鍗佸垎閽熷叆闂≧ocketMQ锛歨ttp://jm.taobao.org/2017/01/12/rocketmq-quick-start-in-10-minutes/
4. 鍒嗗竷寮忎簨鍔$殑绉嶇被浠ュ強 RocketMQ 鏀寔鐨勫垎甯冨紡娑堟伅锛歨ttps://www.infoq.cn/article/2018/08/rocketmq-4.3-release
5. 婊存淮鍑鸿鍩轰簬RocketMQ鏋勫缓浼佷笟绾ф秷鎭槦鍒楁湇鍔$殑瀹炶返锛歨ttps://yq.aliyun.com/articles/664608
6. 鍩轰簬銆奟ocketMQ鎶�鏈唴骞曘�嬫簮鐮佹敞閲婏細https://github.com/LiWenGu/awesome-rocketmq

[1]: https://leran2deeplearnjavawebtech.oss-cn-beijing.aliyuncs.com/somephoto/RocketMQ%E6%B5%81%E7%A8%8B.png
[2]: http://rocketmq.apache.org/release_notes/release-notes-4.5.0/

 

你可能感兴趣的:(整理资料,Java相关)