This is an automated email from the ASF dual-hosted git repository.

albumenj pushed a commit to branch refactor/next-2
in repository https://gitbox.apache.org/repos/asf/dubbo-website.git


The following commit(s) were added to refs/heads/refactor/next-2 by this push:
     new 96dc6d2953 Update protocol
96dc6d2953 is described below

commit 96dc6d29539826a32059681ec301c005095b97aa
Author: Albumen Kevin <[email protected]>
AuthorDate: Fri Feb 10 11:37:48 2023 +0800

    Update protocol
---
 content/zh-cn/overview/what/ecosystem/_index.md    |   1 +
 .../overview/what/ecosystem/protocol/dubbo.md      | 131 +++-
 .../zh-cn/overview/what/ecosystem/protocol/grpc.md |  44 +-
 .../zh-cn/overview/what/ecosystem/protocol/http.md | 679 ++++++++++++++++++++-
 .../zh-cn/overview/what/ecosystem/protocol/rmi.md  | 104 +++-
 .../overview/what/ecosystem/protocol/thrift.md     |  56 +-
 .../overview/what/ecosystem/protocol/triple.md     | 400 ++++++++++++
 7 files changed, 1407 insertions(+), 8 deletions(-)

diff --git a/content/zh-cn/overview/what/ecosystem/_index.md 
b/content/zh-cn/overview/what/ecosystem/_index.md
index d64f99bf32..aeaabf3dc4 100644
--- a/content/zh-cn/overview/what/ecosystem/_index.md
+++ b/content/zh-cn/overview/what/ecosystem/_index.md
@@ -19,6 +19,7 @@ no_list: true
                 </h4>
                     <p>Dubbo 提供以下协议类型的支持:</p>
                     <p><a href='{{< relref "./protocol/dubbo" >}}'>Dubbo 
协议</a></p>
+                    <p><a href='{{< relref "./protocol/triple" >}}'>Triple 
协议</a></p>
                     <p><a href='{{< relref "./protocol/gRPC" >}}'>gRPC 
协议</a></p>
                     <p><a href='{{< relref "./protocol/http" >}}'>HTTP / Rest 
协议</a></p>
                     <p><a href='{{< relref "./protocol/thrift" >}}'>Thrift 
协议</a></p>
diff --git a/content/zh-cn/overview/what/ecosystem/protocol/dubbo.md 
b/content/zh-cn/overview/what/ecosystem/protocol/dubbo.md
index e23f2984a2..e1df1c50ba 100644
--- a/content/zh-cn/overview/what/ecosystem/protocol/dubbo.md
+++ b/content/zh-cn/overview/what/ecosystem/protocol/dubbo.md
@@ -4,4 +4,133 @@ title: "Dubbo"
 linkTitle: "Dubbo"
 weight: 10
 description: ""
----
\ No newline at end of file
+---
+
+## 特性说明
+Dubbo 缺省协议采用单一长连接和 NIO 异步通讯,适合于小数据量大并发的服务调用,以及服务消费者机器数远大于服务提供者机器数的情况。
+
+反之,Dubbo 缺省协议不适合传送大数据量的服务,比如传文件,传视频等,除非请求量很低。
+
+![dubbo-protocol.jpg](/imgs/user/dubbo-protocol.jpg)
+
+* Transporter: mina, netty, grizzy
+* Serialization: dubbo, hessian2, java, json
+* Dispatcher: all, direct, message, execution, connection
+* ThreadPool: fixed, cached, ...
+
+
+* 连接个数:单连接
+* 连接方式:长连接
+* 传输协议:TCP
+* 传输方式:NIO 异步传输
+* 序列化:Hessian 二进制序列化
+* 适用范围:传入传出参数数据包较小(建议小于100K),消费者比提供者个数多,单一消费者无法压满提供者,尽量不要用 dubbo 协议传输大文件或超大字符串。
+* 适用场景:常规远程服务方法调用
+
+**约束**
+
+* 参数及返回值需实现 `Serializable` 接口
+* 参数及返回值不能自定义实现 `List`, `Map`, `Number`, `Date`, `Calendar` 等接口,只能用 JDK 
自带的实现,因为 hessian 会做特殊处理,自定义实现类中的属性值都会丢失。
+* Hessian 序列化,只传成员属性值和值的类型,不传方法或静态变量,兼容情况**吴亚军提供**
+
+| 数据通讯 | 情况 | 结果 |
+| ------------- | ------------- | ------------- |
+| A->B  | 类A多一种 属性(或者说类B少一种 属性)| 不抛异常,A多的那 个属性的值,B没有,其他正常 |
+| A->B  | 枚举A多一种 枚举(或者说B少一种 枚举)| A使用多 出来的枚举进行传输 | 抛异常 |
+| A->B  | 枚举A多一种 枚举(或者说B少一种 枚举)| A不使用 多出来的枚举进行传输 | 不抛异常,B正常接 收数据 |
+| A->B  | A和B的属性 名相同,但类型不相同 | 抛异常 |
+| A->B  | serialId 不相同 | 正常传输 |
+
+接口增加方法,对客户端无影响,如果该方法不是客户端需要的,客户端不需要重新部署。输入参数和结果集中增加属性,对客户端无影响,如果客户端并不需要新属性,不用重新部署。
+
+输入参数和结果集属性名变化,对客户端序列化无影响,但是如果客户端不重新部署,不管输入还是输出,属性名变化的属性值是获取不到的。
+
+**总结**
+- 服务器端和客户端对领域对象并不需要完全一致,而是按照最大匹配原则。
+- 会抛异常的情况:枚举值一边多一种,一边少一种,正好使用了差别的那种,或者属性名相同,类型不同。
+
+
+## 使用场景
+
+适合大并发小数据量的服务调用,服务消费者远大于服务提供者的情景。
+
+## 使用方式 - Java
+
+### 配置协议
+
+```xml
+<dubbo:protocol name="dubbo" port="20880" />
+```
+
+### 设置默认协议
+
+```xml
+<dubbo:provider protocol="dubbo" />
+```
+
+### 设置某个服务的协议
+
+```xml
+<dubbo:service interface="..." protocol="dubbo" />
+```
+
+### 多端口
+
+```xml
+<dubbo:protocol id="dubbo1" name="dubbo" port="20880" />
+<dubbo:protocol id="dubbo2" name="dubbo" port="20881" />
+```
+
+### 配置协议选项
+
+```xml
+<dubbo:protocol name=“dubbo” port=“9090” server=“netty” client=“netty” 
codec=“dubbo” serialization=“hessian2” charset=“UTF-8” threadpool=“fixed” 
threads=“100” queues=“0” iothreads=“9” buffer=“8192” accepts=“1000” 
payload=“8388608” />
+```
+
+### 多连接配置
+
+Dubbo 协议缺省每服务每提供者每消费者使用单一长连接,如果数据量较大,可以使用多个连接。
+
+```xml
+<dubbo:service interface="..." connections="1"/>
+<dubbo:reference interface="..." connections="1"/>
+```
+
+* `<dubbo:service connections="0">` 或 `<dubbo:reference connections="0">` 
表示该服务使用 JVM 共享长连接。**缺省**
+* `<dubbo:service connections="1">` 或 `<dubbo:reference connections="1">` 
表示该服务使用独立长连接。
+* `<dubbo:service connections="2">` 或`<dubbo:reference connections="2">` 
表示该服务使用独立两条长连接。
+
+为防止被大量连接撑挂,可在服务提供方限制大接收连接数,以实现服务提供方自我保护。
+
+```xml
+<dubbo:protocol name="dubbo" accepts="1000" />
+```
+
+## 使用方式 - Go
+
+TBD
+
+## 使用方式 - Node.Js
+
+TBD
+
+## 使用方式 - Rust
+
+暂不支持
+
+## 常见问题
+
+### Q1
+为什么要消费者比提供者个数多?
+
+因 dubbo 协议采用单一长连接,假设网络为千兆网卡 **1024Mbit=128MByte**,根据测试经验数据每条连接最多只能压满 
7MByte(不同的环境可能不一样,供参考),理论上 1 个服务提供者需要 20 个服务消费者才能压满网卡。
+
+### Q2
+为什么不能传大包?
+
+因 dubbo 协议采用单一长连接,如果每次请求的数据包大小为 500KByte,假设网络为千兆网卡 
**1024Mbit=128MByte**,每条连接最大 7MByte (不同的环境可能不一样),单个服务提供者的 
TPS(每秒处理事务数)最大为:128MByte / 500KByte = 262。单个消费者调用单个服务提供者的 TPS 
(每秒处理事务数)最大为:7MByte / 500KByte = 14。如果能接受,可以考虑使用,否则网络将成为瓶颈。
+
+### Q3
+为什么采用异步单一长连接?
+
+因为服务的现状大都是服务提供者少,通常只有几台机器,而服务的消费者多,可能整个网站都在访问该服务,比如 Morgan 的提供者只有 6 
台提供者,却有上百台消费者,每天有 1.5 亿次调用,如果采用常规的 hessian 
服务,服务提供者很容易就被压跨,通过单一连接,保证单一消费者不会压死提供者,长连接,减少连接握手验证等,并使用异步 IO,复用线程池,防止 C10K 问题。
\ No newline at end of file
diff --git a/content/zh-cn/overview/what/ecosystem/protocol/grpc.md 
b/content/zh-cn/overview/what/ecosystem/protocol/grpc.md
index f8282e436c..e2f0636088 100644
--- a/content/zh-cn/overview/what/ecosystem/protocol/grpc.md
+++ b/content/zh-cn/overview/what/ecosystem/protocol/grpc.md
@@ -2,6 +2,46 @@
 type: docs
 title: "gRPC"
 linkTitle: "gRPC"
-weight: 20
+weight: 40
 description: ""
----
\ No newline at end of file
+---
+
+## 特性说明
+
+Dubbo 自 2.7.5 版本开始支持原生 gRPC 协议,对于计划使用 HTTP/2 通信,或者想利用 gRPC 带来的 
Stream、反压、Reactive 编程等能力的开发者来说,
+都可以考虑启用 gRPC 协议。
+
+> 从 Dubbo 3 开始,Dubbo 提供的 Triple 协议原生支持 gRPC 协议。
+
+#### 支持 gRPC 的好处
+* 为期望使用 gRPC 协议的用户带来服务治理能力,方便接入 Dubbo 体系
+* 用户可以使用 Dubbo 风格的,基于接口的编程风格来定义和使用远程服务
+
+## 使用场景
+
+- 需要立即响应才能继续处理的同步后端微服务到微服务通信。
+- 需要支持混合编程平台的 Polyglot 环境。
+- 性能至关重要的低延迟和高吞吐量通信。
+- 点到点实时通信 - gRPC 无需轮询即可实时推送消息,并且能对双向流式处理提供出色的支持。
+- 网络受约束环境 - 二进制 gRPC 消息始终小于等效的基于文本的 JSON 消息。
+
+## 使用方式 - Java
+
+[示例](https://github.com/apache/dubbo-samples/tree/master/3-extensions/protocol/dubbo-samples-grpc)
+
+## 使用方式 - Go
+
+TBD
+
+## 使用方式 - Node.js
+
+TBD
+
+## 使用方式 - Rust
+
+暂不支持
+
+### 步骤
+1. 使用 IDL 定义服务
+2. 配置 compiler 插件,本地预编译
+3. 配置暴露/引用 Dubbo 服务
diff --git a/content/zh-cn/overview/what/ecosystem/protocol/http.md 
b/content/zh-cn/overview/what/ecosystem/protocol/http.md
index 16e5ac640c..3ecc43dbcb 100644
--- a/content/zh-cn/overview/what/ecosystem/protocol/http.md
+++ b/content/zh-cn/overview/what/ecosystem/protocol/http.md
@@ -4,4 +4,681 @@ title: "http"
 linkTitle: "http"
 weight: 30
 description: ""
----
\ No newline at end of file
+---
+
+基于标准的 Java REST API——JAX-RS 2.0(Java API for RESTful Web Services 的简写)实现的 REST 
调用支持
+
+## 特性说明
+此协议提供通过 web 访问服务的简单方式,将服务与其他基于 web 的应用程序集成。
+支持 JSON、XML 和 Text 格式的请求和响应,发布和使用服务的便捷方式,也提供了服务版本控制、服务过滤、服务元数据和服务参数, 实现 Dubbo 
框架的灵活性和可伸缩性。
+
+## 使用场景
+
+## 使用方式
+
+### 快速入门
+
+在 dubbo 中开发一个 REST 风格的服务会比较简单,下面以一个注册用户的简单服务为例说明。
+
+这个服务要实现的功能是提供如下 URL(注:这个URL不是完全符合 REST 的风格,但是更简单实用)
+```
+http://localhost:8080/users/register
+```
+而任何客户端都可以将包含用户信息的 JSON 字符串 POST 到以上 URL 来完成用户注册。
+
+首先,开发服务的接口
+
+```java
+public class UserService {    
+   void registerUser(User user);
+}
+```
+
+然后,开发服务的实现
+
+```java
+@Path("users")
+public class UserServiceImpl implements UserService {
+       
+    @POST
+    @Path("register")
+    @Consumes({MediaType.APPLICATION_JSON})
+    public void registerUser(User user) {
+        // save the user...
+    }
+}
+```
+上面的实现非常简单,但是由于该 REST 服务是要发布到指定 URL 上,供任意语言的客户端甚至浏览器来访问,所以这里额外添加了几个 JAX-RS 的标准 
annotation 来做相关的配置。
+
+@Path("users"):指定访问 UserService 的 URL 相对路径是 /users,即 
http://localhost:8080/users
+
+@Path("register"):指定访问 registerUser() 方法的 URL 相对路径是 /register,再结合上一个 
@Path为UserService 指定的路径,则调用 UserService.register() 的完整路径为 
http://localhost:8080/users/register
+
+@POST:指定访问 registerUser()用HTTP POST方法
+
+@Consumes({MediaType.APPLICATION_JSON}):指定 registerUser() 接收 JSON 格式的数据。REST 
框架会自动将 JSON 数据反序列化为 User 对象
+
+最后,在 spring 配置文件中添加此服务,即完成所有服务开发工作
+
+ ```xml
+<!-- 用rest协议在8080端口暴露服务 -->
+<dubbo:protocol name="rest" port="8080"/>
+ 
+<!-- 声明需要暴露的服务接口 -->
+<dubbo:service interface="xxx.UserService" ref="userService"/>
+ 
+<!-- 和本地bean一样实现服务 -->
+<bean id="userService" class="xxx.UserServiceImpl" />
+``` 
+
+### REST 服务提供端
+
+下面我们扩充“快速入门”中的UserService,进一步展示在dubbo中REST服务提供端的开发要点。
+
+### HTTP POST/GET 的实现
+
+REST 服务中虽然建议使用 HTTP 协议中四种标准方法 POST、DELETE、PUT、GET 
来分别实现常见的“增删改查”,但实际中,我们一般情况直接用POST来实现“增改”,GET 来实现“删查”即可(DELETE 和 PUT 
甚至会被一些防火墙阻挡)。
+
+前面已经简单演示了 POST 的实现,在此,我们为 UserService 添加一个获取注册用户资料的功能,来演示 GET 的实现。
+
+这个功能就是要实现客户端通过访问如下不同 URL 来获取不同 ID 的用户资料
+
+```
+http://localhost:8080/users/1001
+http://localhost:8080/users/1002
+http://localhost:8080/users/1003
+```
+
+当然,也可以通过其他形式的URL来访问不同 ID 的用户资料,例如
+
+```
+http://localhost:8080/users/load?id=1001
+```
+
+JAX-RS 本身可以支持所有这些形式。但是上面那种在 URL 路径中包含查询参数的形式(http://localhost:8080/users/1001) 
更符合 REST 的一般习惯,所以更推荐大家来使用。下面我们就为 UserService 添加一个 getUser() 方法来实现这种形式的 URL 访问
+
+```java
+@GET
+@Path("{id : \\d+}")
+@Produces({MediaType.APPLICATION_JSON})
+public User getUser(@PathParam("id") Long id) {
+    // ...
+}
+```
+
+@GET:指定用 HTTP GET 方法访问
+
+@Path("{id : \\d+}"):根据上面的功能需求,访问 getUser() 的 URL 应当是 
“http://localhost:8080/users/ + 任意数字",并且这个数字要被做为参数传入 getUser() 方法。 这里的 
annotation 配置中,@Path中间的 {id: xxx} 指定 URL 相对路径中包含了名为id参数,而它的值也将被自动传递给下面用 
@PathParam("id") 修饰的方法参数 id。{id:后面紧跟的\\d+ 是一个正则表达式,指定了 id 参数必须是数字。
+
+@Produces({MediaType.APPLICATION_JSON}):指定getUser()输出JSON格式的数据。框架会自动将User对象序列化为JSON数据。
+
+### Annotation
+
+在 Dubbo 中开发 REST 服务主要都是通过 JAX-RS的annotation 来完成配置的,在上面的示例中,我们都是将 annotation 
放在服务的实现类中。但其实,我们完全也可以将 annotation 放到服务的接口上,这两种方式是完全等价的,例如:
+
+```java
+@Path("users")
+public interface UserService {
+    
+    @GET
+    @Path("{id : \\d+}")
+    @Produces({MediaType.APPLICATION_JSON})
+    User getUser(@PathParam("id") Long id);
+}
+```
+
+在一般应用中,我们建议将 annotation 放到服务实现类,这样 annotation 和 java 
实现代码位置更接近,更便于开发和维护。另外更重要的是,我们一般倾向于避免对接口的污染,保持接口的纯净性和广泛适用性。
+
+但是,如后文所述,如果我们要用 dubbo 直接开发的消费端来访问此服务,则 annotation 必须放到接口上。
+
+如果接口和实现类都同时添加了 annotation,则实现类的 annotation 配置会生效,接口上的 annotation 被直接忽略。
+
+### 多数据格式支持
+
+在 dubbo 中开发的 REST 服务可以同时支持传输多种格式的数据,以给客户端提供最大的灵活性。其中我们目前对最常用的 JSON 和 XML 
格式特别添加了额外的功能。
+
+比如,我们要让上例中的getUser()方法支持分别返回 JSON 和 XML 格式的数据,只需要在 annotation 中同时包含两种格式即可
+
+```java
+@Produces({MediaType.APPLICATION_JSON, MediaType.TEXT_XML})
+User getUser(@PathParam("id") Long id);
+```
+
+或者也可以直接用字符串(还支持通配符)表示 MediaType
+
+```java
+@Produces({"application/json", "text/xml"})
+User getUser(@PathParam("id") Long id);
+```
+
+如果所有方法都支持同样类型的输入输出数据格式,则我们无需在每个方法上做配置,只需要在服务类上添加 annotation 即可
+
+```java
+@Path("users")
+@Consumes({MediaType.APPLICATION_JSON, MediaType.TEXT_XML})
+@Produces({MediaType.APPLICATION_JSON, MediaType.TEXT_XML})
+public class UserServiceImpl implements UserService {
+    // ...
+}
+```
+
+在一个 REST 服务同时对多种数据格式支持的情况下,根据 JAX-RS 标准,一般是通过HTTP中的MIME 
header(content-type和accept)来指定当前想用的是哪种格式的数据。
+
+但是在 dubbo 中,我们还自动支持目前业界普遍使用的方式,即用一个 URL 后缀(.json和.xml)来指定想用的数据格式。例如,在添加上述 
annotation后,直接访问 http://localhost:8888/users/1001.json 则表示用 json 格式,直接访问 
http://localhost:8888/users/1002.xml 则表示用 xml 格式,比用 HTTP Header 
更简单直观。Twitter、微博等的 REST API 都是采用这种方式。
+如果你既不加 HTTP header,也不加后缀,则 dubbo 的 REST 会优先启用在以上 annotation 定义中排位最靠前的那种数据格式。
+
+> 注意:这里要支持 XML 格式数据,在 annotation 中既可以用 MediaType.TEXT_XML,也可以用 
MediaType.APPLICATION_XML,但是 TEXT_XML 是更常用的,并且如果要利用上述的 URL 后缀方式来指定数据格式,只能配置为 
TEXT_XML 才能生效。
+### 中文字符支持
+
+为了在 dubbo REST 中正常输出中文字符,和通常的 Java web 应用一样,我们需要将 HTTP 响应的 contentType 设置为 
UTF-8编码。
+
+基于 JAX-RS 的标准用法,我们只需要做如下 annotation 配置即可:
+
+```java
+@Produces({"application/json; charset=UTF-8", "text/xml; charset=UTF-8"})
+User getUser(@PathParam("id") Long id);
+```
+
+为了方便用户,我们在 dubbo REST 中直接添加了一个支持类,来定义以上的常量,可以直接使用,减少出错的可能性。
+
+```java
+@Produces({ContentType.APPLICATION_JSON_UTF_8, ContentType.TEXT_XML_UTF_8})
+User getUser(@PathParam("id") Long id);
+```
+
+### XML 数据格式
+
+由于 JAX-RS 的实现一般都用标准的 JAXB(Java API for XML Binding)来序列化和反序列化 XML 
格式数据,所以我们需要为每一个要用 XML 传输的对象添加一个类级别的 JAXB annotation,否则序列化将报错。例如为 getUser() 中返回的 
User 添加如下
+
+```java
+@XmlRootElement
+public class User implements Serializable {
+    // ...
+}
+```    
+
+此外,如果service方法中的返回值是Java的 
primitive类型(如int,long,float,double等),最好为它们添加一层wrapper对象,因为JAXB不能直接序列化primitive类型。
+
+例如,我们想让前述的registerUser()方法返回服务器端为用户生成的ID号:
+
+```java
+long registerUser(User user);
+```
+
+由于 primitive 类型不被 JAXB 序列化支持,所以添加一个 wrapper 对象:
+
+```java
+@XmlRootElement
+public class RegistrationResult implements Serializable {
+    
+    private Long id;
+    
+    public RegistrationResult() {
+    }
+    
+    public RegistrationResult(Long id) {
+        this.id = id;
+    }
+    
+    public Long getId() {
+        return id;
+    }
+    
+    public void setId(Long id) {
+        this.id = id;
+    }
+}
+```
+
+并修改 service 方法:
+
+```java
+RegistrationResult registerUser(User user);
+```
+
+这样不但能够解决 XML 序列化的问题,而且使得返回的数据都符合 XML 和 JSON 的规范。例如,在 JSON中,返回的将是如下形式
+
+```javascript
+{"id": 1001}
+```
+
+如果不加 wrapper,JSON 返回值将直接是
+
+```
+1001   
+```
+
+而在 XML 中,加 wrapper 后返回值将是:
+
+```xml
+<registrationResult>
+    <id>1002</id>
+</registrationResult>
+```
+
+这种 wrapper 对象其实利用所谓 Data Transfer Object(DTO)模式,采用 DTO 还能对传输数据做更多有用的定制。
+
+### 定制序列化
+
+如上所述,REST 的底层实现会在 service 的对象和 JSON/XML 
数据格式之间自动做序列化/反序列化。但有些场景下,如果觉得这种自动转换不满足要求,可以对其做定制。
+
+Dubbo 中的 REST 实现是用 JAXB 做 XML 序列化,用 Jackson 做 JSON 序列化,所以在对象上添加 JAXB 或 Jackson 
的 annotation 即可以定制映射。
+
+例如,定制对象属性映射到 XML 元素的名字:
+
+```java
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.FIELD)
+public class User implements Serializable {
+    
+    @XmlElement(name="username") 
+    private String name;  
+}
+```
+
+定制对象属性映射到 JSON 字段的名字:
+
+```java
+public class User implements Serializable {
+    
+    @JsonProperty("username")
+    private String name;
+}
+```
+
+更多资料请参考 JAXB 和 Jackson 的官方文档,或自行 google。
+
+### REST Server 的实现
+
+目前在 dubbo 中,我们支持5种嵌入式 rest server 的实现,并同时支持采用外部应用服务器来做 rest server 的实现。rest 
server 可以通过如下配置实现:
+
+```xml
+<dubbo:protocol name="rest" server="jetty"/>
+```
+
+以上配置选用了嵌入式的 jetty 来做 rest server,同时,如果不配置 server 属性,rest 协议默认也是选用 jetty。jetty 
是非常成熟的 java servlet 容器,并和 dubbo 已经有较好的集成(目前5种嵌入式 server 中只有 jetty 和后面所述的 
tomcat、tjws,与 dubbo 监控系统等完成了无缝的集成),所以,如果你的 dubbo 系统是单独启动的进程,你可以直接默认采用 jetty 即可。
+
+
+```xml
+<dubbo:protocol name="rest" server="tomcat"/>
+```
+
+以上配置选用了嵌入式的 tomcat 来做 rest server。在嵌入式 tomcat 上,REST 的性能比 jetty 
上要好得多(参见后面的基准测试),建议在需要高性能的场景下采用 tomcat。
+
+```xml
+<dubbo:protocol name="rest" server="netty"/>
+```
+
+以上配置选用嵌入式的 netty 来做 rest server。(TODO more contents to add)
+
+```xml
+<dubbo:protocol name="rest" server="tjws"/> (tjws is now deprecated)
+<dubbo:protocol name="rest" server="sunhttp"/>
+```
+
+以上配置选用嵌入式的 tjws 或 Sun HTTP server 来做 rest server。这两个 server 
实现非常轻量级,非常方便在集成测试中快速启动使用,当然也可以在负荷不高的生产环境中使用。       
注:tjws目前已经被deprecated掉了,因为它不能很好的和servlet 3.1 API工作。
+
+如果你的 dubbo 系统不是单独启动的进程,而是部署到了 Java 应用服务器中,则建议你采用以下配置
+
+```xml
+<dubbo:protocol name="rest" server="servlet"/>
+```
+
+通过将 server 设置为 servlet,dubbo 将采用外部应用服务器的 servlet 容器来做 rest server。同时,还要在 dubbo 
系统的 web.xml 中添加如下配置
+
+```xml
+<web-app>
+    <context-param>
+        <param-name>contextConfigLocation</param-name>
+        
<param-value>/WEB-INF/classes/META-INF/spring/dubbo-demo-provider.xml</param-value>
+    </context-param>
+    
+    <listener>
+        
<listener-class>org.apache.dubbo.remoting.http.servlet.BootstrapListener</listener-class>
+    </listener>
+    
+    <listener>
+        
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
+    </listener>
+    
+    <servlet>
+        <servlet-name>dispatcher</servlet-name>
+        
<servlet-class>org.apache.dubbo.remoting.http.servlet.DispatcherServlet</servlet-class>
+        <load-on-startup>1</load-on-startup>
+    </servlet>
+    
+    <servlet-mapping>
+        <servlet-name>dispatcher</servlet-name>
+        <url-pattern>/*</url-pattern>
+    </servlet-mapping>
+</web-app>
+```
+
+即必须将 dubbo 的 BootstrapListener 和 DispatherServlet 添加到 web.xml,以完成 dubbo 的 REST 
功能与外部 servlet 容器的集成。
+
+> 注意:如果你是用 spring 的 ContextLoaderListener 来加载 spring,则必须保证 BootstrapListener 
配置在 ContextLoaderListener 之前,否则 dubbo 初始化会出错。
+其实,这种场景下你依然可以坚持用嵌入式 server,但外部应用服务器的 servlet 容器往往比嵌入式 server 
更加强大(特别是如果你是部署到更健壮更可伸缩的 WebLogic,WebSphere 等),另外有时也便于在应用服务器做统一管理、监控等等。
+
+### 获取 Context 信息
+
+在远程调用中,值得获取的上下文信息可能有很多种,这里特别以获取客户端 IP 为例。
+
+在 dubbo 的 REST 中,我们有两种方式获取客户端 IP。
+
+第一种方式,用 JAX-RS 标准的 @Context annotation
+
+```java
+public User getUser(@PathParam("id") Long id, @Context HttpServletRequest 
request) {
+    System.out.println("Client address is " + request.getRemoteAddr());
+} 
+```
+
+用 Context 修饰 getUser() 的一个方法参数后,就可以将当前的 HttpServletRequest 注入进来,然后直接调用 servlet 
api 获取 IP。
+
+> 注意:这种方式只能在将server设置为 tjws、tomcat、jetty 或者 servlet 的时候才能工作,因为只有这几种 server 
的实现才提供了 servlet 
容器。另外,标准的JAX-RS还支持用@Context修饰service类的一个实例字段来获取HttpServletRequest,但在dubbo中我们没有对此作出支持。
+第二种方式,用 dubbo 中常用的 RpcContext
+
+```java
+public User getUser(@PathParam("id") Long id) {
+    System.out.println("Client address is " + 
RpcContext.getContext().getRemoteAddressString());
+} 
+```
+
+> 注意:这种方式只能在设置 server="jetty" 或者 server="tomcat" 或者 server="servlet" 或者 
server="tjws" 的时候才能工作。另外,目前 dubbo 的 RpcContext 是一种比较有侵入性的用法,未来我们很可能会做出重构。
+如果你想保持你的项目对 JAX-RS 的兼容性,未来脱离 dubbo 也可以运行,请选择第一种方式。如果你想要更优雅的服务接口定义,请选用第二种方式。
+
+此外,在最新的 dubbo rest 中,还支持通过 RpcContext 来获取 HttpServletRequest和 
HttpServletResponse,以提供更大的灵活性来方便用户实现某些复杂功能,比如在 dubbo 标准的 filter 中访问 HTTP 
Header。用法示例如下
+
+```java
+if (RpcContext.getContext().getRequest() != null && 
RpcContext.getContext().getRequest() instanceof HttpServletRequest) {
+    System.out.println("Client address is " + ((HttpServletRequest) 
RpcContext.getContext().getRequest()).getRemoteAddr());
+}
+if (RpcContext.getContext().getResponse() != null && 
RpcContext.getContext().getResponse() instanceof HttpServletResponse) {
+    System.out.println("Response object from RpcContext: " + 
RpcContext.getContext().getResponse());
+}
+```
+
+> 
注意:为了保持协议的中立性,RpcContext.getRequest()和RpcContext.getResponse()返回的仅仅是一个Object类,而且可能为null。所以,你必须自己做null和类型的检查。
+> 
注意:只有在设置server="jetty"或者server="tomcat"或者server="servlet"的时候,你才能通过以上方法正确的得到HttpServletRequest和HttpServletResponse,因为只有这几种server实现了servlet容器。
+为了简化编程,在此你也可以用泛型的方式来直接获取特定类型的 request/response:
+
+```java
+if (RpcContext.getContext().getRequest(HttpServletRequest.class) != null) {
+    System.out.println("Client address is " + 
RpcContext.getContext().getRequest(HttpServletRequest.class).getRemoteAddr());
+}
+if (RpcContext.getContext().getResponse(HttpServletResponse.class) != null) {
+    System.out.println("Response object from RpcContext: " + 
RpcContext.getContext().getResponse(HttpServletResponse.class));
+}
+```
+
+如果 request/response 不符合指定的类型,这里也会返回 null。
+
+### 端口号和 Context Path
+
+dubbo 中的 rest 协议默认将采用80端口,如果想修改端口,直接配置:
+
+```xml
+<dubbo:protocol name="rest" port="8888"/>
+```
+
+另外,如前所述,我们可以用 @Path 来配置单个 rest 服务的 URL 相对路径。但其实,我们还可以设置一个所有 rest 
服务都适用的基础相对路径,即 java web 应用中常说的 context path。
+
+只需要添加如下 contextpath 属性即可:
+
+```xml
+<dubbo:protocol name="rest" port="8888" contextpath="services"/>
+```
+
+以前面代码为例:
+
+```java
+@Path("users")
+public class UserServiceImpl implements UserService {
+       
+    @POST
+    @Path("register")
+    @Consumes({MediaType.APPLICATION_JSON})
+    public void registerUser(User user) {
+        // save the user...
+    }  
+}
+```
+
+现在 registerUser() 的完整访问路径
+
+```
+http://localhost:8888/services/users/register
+```
+
+注意:如果你是选用外部应用服务器做 rest server,即配置
+
+```xml
+<dubbo:protocol name="rest" port="8888" contextpath="services" 
server="servlet"/>
+```
+
+则必须保证这里设置的 port、contextpath,与外部应用服务器的端口、DispatcherServlet 的上下文路径(即 webapp path 
加上 servlet url pattern)保持一致。例如,对于部署为 tomcat ROOT 路径的应用,这里的 contextpath 必须与 
web.xml 中 DispacherServlet 的`<url-pattern/>` 完全一致:
+
+```xml
+<servlet-mapping>
+     <servlet-name>dispatcher</servlet-name>
+     <url-pattern>/services/*</url-pattern>
+</servlet-mapping>
+```
+
+### 线程数和 IO 线程数
+
+可以为 rest 服务配置线程池大小
+
+```xml
+<dubbo:protocol name="rest" threads="500"/>
+```
+
+> 
注意:目前线程池的设置只有当server="netty"或者server="jetty"或者server="tomcat"的时候才能生效。另外,如果server="servlet",由于这时候启用的是外部应用服务器做rest
 server,不受dubbo控制,所以这里的线程池设置也无效。
+如果是选用 netty server,还可以配置 Netty 的 IO worker 线程数
+
+```xml
+<dubbo:protocol name="rest" iothreads="5" threads="100"/>
+```
+
+### 配置长连接
+
+Dubbo 中的 rest 服务默认都是采用 http 长连接来访问,如果想切换为短连接,直接配置
+
+```xml
+<dubbo:protocol name="rest" keepalive="false"/>
+```
+
+> 注意:这个配置目前只对 server="netty"和server="tomcat" 才能生效。
+### 最大 HTTP 连接数
+
+可以配置服务器提供端所能同时接收的最大 HTTP 连接数,防止 REST server 被过多连接撑爆,以作为一种最基本的自我保护机制
+
+```xml
+<dubbo:protocol name="rest" accepts="500" server="tomcat/>
+```
+> 注意:这个配置目前只对server="tomcat"才能生效。
+### 每个消费端的超时时间和 HTTP 连接数
+如果 rest 服务的消费端也是 dubbo 系统,可以像其他 dubbo RPC 机制一样,配置消费端调用此 rest 
服务的最大超时时间以及每个消费端所能启动的最大 HTTP 连接数。
+```xml
+<dubbo:service interface="xxx" ref="xxx" protocol="rest" timeout="2000" 
connections="10"/>
+```
+当然,由于这个配置针对消费端生效的,所以也可以在消费端配置
+```xml
+<dubbo:reference id="xxx" interface="xxx" timeout="2000" connections="10"/>
+```
+但是,通常我们建议配置在服务提供端提供此类配置。按照 dubbo 官方文档的说法:“Provider 上尽量多配置 Consumer 端的属性,让 
Provider 实现者一开始就思考 Provider 服务特点、服务质量的问题。”
+> 注意:如果 dubbo 的 REST 服务是发布给非 dubbo 的客户端使用,则这里 `<dubbo:service/>` 
上的配置完全无效,因为这种客户端不受 dubbo 控制。
+### Annotation 取代部分 Spring XML 配置
+以上所有的讨论都是基于 dubbo 在 spring 中的 xml 配置。但是,dubbo/spring 本身也支持用 annotation 
来作配置,所以我们也可以按dubbo官方文档中的步骤,把相关 annotation 加到 REST 服务的实现中,取代一些 xml 配置,例如
+```java
+@Service(protocol = "rest")
+@Path("users")
+public class UserServiceImpl implements UserService {
+    @Autowired
+    private UserRepository userRepository;
+       
+    @POST
+    @Path("register")
+    @Consumes({MediaType.APPLICATION_JSON})
+    public void registerUser(User user) {
+        // save the user
+        userRepository.save(user);
+    }  
+}
+```
+annotation 的配置更简单更精确,通常也更便于维护(当然现代IDE都可以在xml中支持比如类名重构,所以就这里的特定用例而言,xml 
的维护性也很好)。而 xml 
对代码的侵入性更小一些,尤其有利于动态修改配置,特别是比如你要针对单个服务配置连接超时时间、每客户端最大连接数、集群策略、权重等等。另外,特别对复杂应用或者模块来说,xml
 提供了一个中心点来涵盖的所有组件和配置,更一目了然,一般更便于项目长时期的维护。
+当然,选择哪种配置方式没有绝对的优劣,和个人的偏好也不无关系。
+### 添加自定义的 Filter、Interceptor
+Dubbo 的 REST 也支持 JAX-RS 标准的 Filter 和 Interceptor,以方便对 REST 的请求与响应过程做定制化的拦截处理。
+其中,Filter 主要用于访问和设置 HTTP 请求和响应的参数、URI 等等。例如,设置 HTTP 响应的 cache header:
+```java
+public class CacheControlFilter implements ContainerResponseFilter {
+    public void filter(ContainerRequestContext req, ContainerResponseContext 
res) {
+        if (req.getMethod().equals("GET")) {
+            res.getHeaders().add("Cache-Control", "someValue");
+        }
+    }
+}
+```
+Interceptor 主要用于访问和修改输入与输出字节流,例如,手动添加 GZIP 压缩
+```java
+public class GZIPWriterInterceptor implements WriterInterceptor {
+ 
+    @Override
+    public void aroundWriteTo(WriterInterceptorContext context)
+                    throws IOException, WebApplicationException {
+        OutputStream outputStream = context.getOutputStream();
+        context.setOutputStream(new GZIPOutputStream(outputStream));
+        context.proceed();
+    }
+}
+```
+在标准 JAX-RS 应用中,我们一般是为 Filter 和 Interceptor 添加 @Provider annotation,然后 JAX-RS 
runtime 会自动发现并启用它们。而在 dubbo 中,我们是通过添加XML配置的方式来注册 Filter 和 Interceptor:
+```xml
+<dubbo:protocol name="rest" port="8888" extension="xxx.TraceInterceptor, 
xxx.TraceFilter"/>
+```
+在此,我们可以将 Filter、Interceptor 和 DynamicFeature 这三种类型的对象都添加到 `extension` 
属性上,多个之间用逗号分隔。(DynamicFeature 是另一个接口,可以方便我们更动态的启用 Filter 和 Interceptor,感兴趣请自行 
google。)
+当然,dubbo 自身也支持 Filter 的概念,但我们这里讨论的 Filter 和 Interceptor 更加接近协议实现的底层,相比 dubbo 的 
filter,可以做更底层的定制化。
+> 注:这里的 XML 属性叫 extension,而不是叫 interceptor 或者 filter,是因为除了 Interceptor 和 
Filter,未来我们还会添加更多的扩展类型。
+如果 REST 的消费端也是 dubbo 系统(参见下文的讨论),则也可以用类似方式为消费端配置 Interceptor 和 
Filter。但注意,JAX-RS 中消费端的 Filter 和提供端的 Filter 是两种不同的接口。例如前面例子中服务端是 
ContainerResponseFilter 接口,而消费端对应的是 ClientResponseFilter:
+```java
+public class LoggingFilter implements ClientResponseFilter {
+ 
+    public void filter(ClientRequestContext reqCtx, ClientResponseContext 
resCtx) throws IOException {
+        System.out.println("status: " + resCtx.getStatus());
+           System.out.println("date: " + resCtx.getDate());
+           System.out.println("last-modified: " + resCtx.getLastModified());
+           System.out.println("location: " + resCtx.getLocation());
+           System.out.println("headers:");
+           for (Entry<String, List<String>> header : 
resCtx.getHeaders().entrySet()) {
+           System.out.print("\t" + header.getKey() + " :");
+               for (String value : header.getValue()) {
+                   System.out.print(value + ", ");
+               }
+               System.out.print("\n");
+           }
+           System.out.println("media-type: " + 
resCtx.getMediaType().getType());
+    } 
+}
+```
+### 添加自定义的 Exception 处理
+Dubbo 的 REST 也支持 JAX-RS 标准的 ExceptionMapper,可以用来定制特定 exception 发生后应该返回的 HTTP 
响应。
+```java
+public class CustomExceptionMapper implements 
ExceptionMapper<NotFoundException> {
+    public Response toResponse(NotFoundException e) {     
+        return Response.status(Response.Status.NOT_FOUND).entity("Oops! the 
requested resource is not found!").type("text/plain").build();
+    }
+}
+```
+和 Interceptor、Filter 类似,将其添加到 XML 配置文件中即可启用
+```xml
+<dubbo:protocol name="rest" port="8888" extension="xxx.CustomExceptionMapper"/>
+```
+### HTTP 日志输出
+Dubbo rest 支持输出所有 HTTP 请求/响应中的 header 字段和 body 消息体。
+在 XML 配置中添加如下自带的 REST filter:
+```xml
+<dubbo:protocol name="rest" port="8888" 
extension="org.apache.dubbo.rpc.protocol.rest.support.LoggingFilter"/>
+```
+然后配置在 logging 配置中至少为 org.apache.dubbo.rpc.protocol.rest.support 打开 INFO 
级别日志输出,例如,在 log4j.xml 中配置
+```xml
+<logger name="org.apache.dubbo.rpc.protocol.rest.support">
+    <level value="INFO"/>
+    <appender-ref ref="CONSOLE"/>
+</logger>
+```
+当然,你也可以直接在 ROOT logger 打开 INFO 级别日志输出
+```xml
+<root>
+       <level value="INFO" />
+       <appender-ref ref="CONSOLE"/>
+</root>
+```
+然后在日志中会有类似如下的内容输出
+```
+The HTTP headers are: 
+accept: application/json;charset=UTF-8
+accept-encoding: gzip, deflate
+connection: Keep-Alive
+content-length: 22
+content-type: application/json
+host: 192.168.1.100:8888
+user-agent: Apache-HttpClient/4.2.1 (java 1.5)
+```
+```
+The contents of request body is: 
+{"id":1,"name":"dang"}
+```
+打开 HTTP 日志输出后,除了正常日志输出的性能开销外,也会在比如 HTTP 
请求解析时产生额外的开销,因为需要建立额外的内存缓冲区来为日志的输出做数据准备。
+### 输入参数的校验
+dubbo 的 rest 支持采用 Java 标准的 bean validation annotation(JSR 303) 来做输入校验 
http://beanvalidation.org/
+为了和其他 dubbo 远程调用协议保持一致,在 rest 中作校验的 annotation 必须放在服务的接口上,例如
+```java
+public interface UserService {
+   
+    User getUser(@Min(value=1L, message="User ID must be greater than 1") Long 
id);
+}
+```
+当然,在很多其他的 bean validation 的应用场景都是将 annotation 放到实现类而不是接口上。把 annotation 
放在接口上至少有一个好处是,dubbo 的客户端可以共享这个接口的信息,dubbo 甚至不需要做远程调用,在本地就可以完成输入校验。
+然后按照 dubbo 的标准方式在 XML 配置中打开验证:
+```xml
+<dubbo:service interface=xxx.UserService" ref="userService" protocol="rest" 
validation="true"/>
+```
+
+在 dubbo 的其他很多远程调用协议中,如果输入验证出错,是直接将 `RpcException` 抛向客户端,而在 rest 中由于客户端经常是非 
dubbo,甚至非 java 的系统,所以不便直接抛出 Java 异常。因此,目前我们将校验错误以 XML 的格式返回
+
+```xml
+<violationReport>
+    <constraintViolations>
+        <path>getUserArgument0</path>
+        <message>User ID must be greater than 1</message>
+        <value>0</value>
+    </constraintViolations>
+</violationReport>
+```
+
+稍后也会支持其他数据格式的返回值。至于如何对验证错误消息作国际化处理,直接参考 bean validation 的相关文档即可。
+
+如果你认为默认的校验错误返回格式不符合你的要求,可以如上面章节所述,添加自定义的 ExceptionMapper 
来自由的定制错误返回格式。需要注意的是,这个 ExceptionMapper 必须用泛型声明来捕获 dubbo 的 RpcException,才能成功覆盖 
dubbo rest 默认的异常处理策略。为了简化操作,其实这里最简单的方式是直接继承 dubbo rest 的 
RpcExceptionMapper,并覆盖其中处理校验异常的方法即可
+
+```java
+public class MyValidationExceptionMapper extends RpcExceptionMapper {
+    protected Response 
handleConstraintViolationException(ConstraintViolationException cve) {
+        ViolationReport report = new ViolationReport();
+        for (ConstraintViolation cv : cve.getConstraintViolations()) {
+            report.addConstraintViolation(new RestConstraintViolation(
+                    cv.getPropertyPath().toString(),
+                    cv.getMessage(),
+                    cv.getInvalidValue() == null ? "null" : 
cv.getInvalidValue().toString()));
+        }
+        // 采用json输出代替xml输出
+        return 
Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(report).type(ContentType.APPLICATION_JSON_UTF_8).build();
+    }
+}
+```
+
+然后将这个 ExceptionMapper 添加到 XML 配置中即可:
+
+```xml
+<dubbo:protocol name="rest" port="8888" 
extension="xxx.MyValidationExceptionMapper"/>
+```
diff --git a/content/zh-cn/overview/what/ecosystem/protocol/rmi.md 
b/content/zh-cn/overview/what/ecosystem/protocol/rmi.md
index 45aadb8812..6288621277 100644
--- a/content/zh-cn/overview/what/ecosystem/protocol/rmi.md
+++ b/content/zh-cn/overview/what/ecosystem/protocol/rmi.md
@@ -2,6 +2,106 @@
 type: docs
 title: "RMI"
 linkTitle: "RMI"
-weight: 50
+weight: 60
 description: ""
----
\ No newline at end of file
+---
+
+## 特性说明
+RMI 协议采用 JDK 标准的 `java.rmi.*` 实现,采用阻塞式短连接和 JDK 标准序列化方式。
+
+* 连接个数:多连接
+* 连接方式:短连接
+* 传输协议:TCP
+* 传输方式:同步传输
+* 序列化:Java 标准二进制序列化
+* 适用范围:传入传出参数数据包大小混合,消费者与提供者个数差不多,可传文件。
+* 适用场景:常规远程服务方法调用,与原生RMI服务互操作
+
+#### 约束
+
+* 参数及返回值需实现 `Serializable` 接口
+* dubbo 配置中的超时时间对 RMI 无效,需使用 java 
启动参数设置:`-Dsun.rmi.transport.tcp.responseTimeout=3000`,参见下面的 RMI 配置
+
+
+## 使用场景
+
+是 Java 的一组拥护开发分布式应用程序的 API,实现了不同操作系统之间程序的方法调用。
+
+## 使用方式 - Java
+
+### 引入依赖
+
+从 Dubbo 3 开始,RMI 协议已经不再内嵌在 Dubbo 
中,需要单独引入独立的[模块](/zh-cn/release/dubbo-spi-extensions/#dubbo-rpc)。
+```xml
+<dependency>
+    <groupId>org.apache.dubbo.extensions</groupId>
+    <artifactId>dubbo-rpc-rmi</artifactId>
+    <version>1.0.0</version>
+</dependency>
+```
+
+```sh
+java -Dsun.rmi.transport.tcp.responseTimeout=3000
+```
+更多 RMI 优化参数请查看 [JDK 
文档](https://docs.oracle.com/javase/6/docs/technotes/guides/rmi/sunrmiproperties.html)
+
+### 接口说明
+如果服务接口继承了 `java.rmi.Remote` 接口,可以和原生 RMI 互操作,即:
+
+* 提供者用 Dubbo 的 RMI 协议暴露服务,消费者直接用标准 RMI 接口调用,
+* 或者提供方用标准 RMI 暴露服务,消费方用 Dubbo 的 RMI 协议调用。
+
+如果服务接口没有继承 `java.rmi.Remote` 接口:
+
+* 缺省 Dubbo 将自动生成一个 `com.xxx.XxxService$Remote` 的接口,并继承 `java.rmi.Remote` 
接口,并以此接口暴露服务,
+* 但如果设置了 `<dubbo:protocol name="rmi" codec="spring" />`,将不生成 `$Remote` 接口,而使用 
Spring 的 `RmiInvocationHandler` 接口暴露服务,和 Spring 兼容。
+
+**定义 RMI 协议**
+
+```xml
+<dubbo:protocol name="rmi" port="1099" />
+```
+
+**设置默认协议**
+
+```xml
+<dubbo:provider protocol="rmi" />
+```
+
+**设置某个服务的协议**
+
+```xml
+<dubbo:service interface="..." protocol="rmi" />
+```
+
+**多端口**
+
+```xml
+<dubbo:protocol id="rmi1" name="rmi" port="1099" />
+<dubbo:protocol id="rmi2" name="rmi" port="2099" />
+
+<dubbo:service interface="..." protocol="rmi1" />
+```
+
+**Spring 兼容性**
+
+```xml
+<dubbo:protocol name="rmi" codec="spring" />
+```
+
+
+> - **如果正在使用 RMI 提供服务给外部访问,** 公司内网环境应该不会有攻击风险。
+> - **同时应用里依赖了老的 common-collections 包的情况下,** dubbo 不会依赖这个包,请排查自己的应用有没有使用。
+> - **存在反序列化安全风险。** 请检查应用:将 commons-collections3 请升级到 
[3.2.2](https://commons.apache.org/proper/commons-collections/release_3_2_2.html);将
 commons-collections4 请升级到 
[4.1](https://commons.apache.org/proper/commons-collections/release_4_1.html)。新版本的
 commons-collections 解决了该问题。
+
+## 使用方式 - Go
+
+暂不支持
+
+## 使用方式 - Node.js
+
+暂不支持
+
+## 使用方式 - Rust
+
+暂不支持
diff --git a/content/zh-cn/overview/what/ecosystem/protocol/thrift.md 
b/content/zh-cn/overview/what/ecosystem/protocol/thrift.md
index 9dfab7590c..9de240fd18 100644
--- a/content/zh-cn/overview/what/ecosystem/protocol/thrift.md
+++ b/content/zh-cn/overview/what/ecosystem/protocol/thrift.md
@@ -2,6 +2,58 @@
 type: docs
 title: "Thrift"
 linkTitle: "Thrift"
-weight: 40
+weight: 50
 description: ""
----
\ No newline at end of file
+---
+
+## 特性说明
+当前 dubbo 支持的 thrift 协议是对 thrift 原生协议的扩展,在原生协议的基础上添加了一些额外的头信息,比如 service 
name,magic number 等。`2.3.0` 以上版本支持。
+
+[Thrift](http://thrift.apache.org) 是 Facebook 捐给 Apache 的一个 RPC 框架。
+
+## 使用场景
+
+适用于 SOA 标准 RPC 框架。
+
+## 使用方式 - Java
+
+### 依赖
+
+从 Dubbo 3 开始,Thrift 协议已经不再内嵌在 Dubbo 
中,需要单独引入独立的[模块](/zh-cn/release/dubbo-spi-extensions/#dubbo-rpc)。
+```xml
+<dependency>
+    <groupId>org.apache.dubbo.extensions</groupId>
+    <artifactId>dubbo-rpc-native-thrift</artifactId>
+    <version>1.0.0</version>
+</dependency>
+```
+
+
+```xml
+<dependency>
+    <groupId>org.apache.thrift</groupId>
+    <artifactId>libthrift</artifactId>
+    <version>0.8.0</version>
+</dependency>
+```
+
+### 所有服务共用一个端口
+
+与原生 Thrift 不兼容
+```xml
+<dubbo:protocol name="thrift" port="3030" />
+```
+
+> Thrift 不支持 null 值,即:不能在协议中传递 null 值
+
+## 使用方式 - Go
+
+暂不支持
+
+## 使用方式 - Node.js
+
+暂不支持
+
+## 使用方式 - Rust
+
+暂不支持
diff --git a/content/zh-cn/overview/what/ecosystem/protocol/triple.md 
b/content/zh-cn/overview/what/ecosystem/protocol/triple.md
new file mode 100644
index 0000000000..fccdbe2419
--- /dev/null
+++ b/content/zh-cn/overview/what/ecosystem/protocol/triple.md
@@ -0,0 +1,400 @@
+---
+type: docs
+title: "Triple"
+linkTitle: "Triple"
+weight: 20
+description: ""
+---
+
+## 概述说明
+
+Triple 协议是 Dubbo3 推出的主力协议。Triple 意为第三代,通过 Dubbo1.0/ Dubbo2.0 
两代协议的演进,以及云原生带来的技术标准化浪潮,Dubbo3 新协议 Triple 应运而生。
+
+### RPC 协议的选择
+
+协议是 RPC 
的核心,它规范了数据在网络中的传输内容和格式。除必须的请求、响应数据外,通常还会包含额外控制数据,如单次请求的序列化方式、超时时间、压缩方式和鉴权信息等。
+
+协议的内容包含三部分
+- 数据交换格式: 定义 RPC 的请求和响应对象在网络传输中的字节流内容,也叫作序列化方式
+- 协议结构: 定义包含字段列表和各字段语义以及不同字段的排列方式
+- 协议通过定义规则、格式和语义来约定数据如何在网络间传输。一次成功的 RPC 
需要通信的两端都能够按照协议约定进行网络字节流的读写和对象转换。如果两端对使用的协议不能达成一致,就会出现鸡同鸭讲,无法满足远程通信的需求。
+
+![协议选择](/imgs/v3/concepts/triple-protocol.png)
+
+RPC 协议的设计需要考虑以下内容:
+- 通用性: 统一的二进制格式,跨语言、跨平台、多传输层协议支持
+- 扩展性: 协议增加字段、升级、支持用户扩展和附加业务元数据
+- 性能:As fast as it can be
+- 穿透性:能够被各种终端设备识别和转发:网关、代理服务器等
+  通用性和高性能通常无法同时达到,需要协议设计者进行一定的取舍。
+
+#### HTTP/1.1
+
+比于直接构建于 TCP 传输层的私有 RPC 协议,构建于 HTTP 之上的远程调用解决方案会有更好的通用性,如WebServices 或 REST 
架构,使用 HTTP + JSON 可以说是一个事实标准的解决方案。
+
+选择构建在 HTTP 之上,有两个最大的优势:
+
+- HTTP 的语义和可扩展性能很好的满足 RPC 调用需求。
+- 通用性,HTTP 协议几乎被网络上的所有设备所支持,具有很好的协议穿透性。
+
+但也存在比较明显的问题:
+
+- 典型的 Request – Response 模型,一个链路上一次只能有一个等待的 Request 请求。会产生 HOL。
+- Human Readable Headers,使用更通用、更易于人类阅读的头部传输格式,但性能相当差
+- 无直接 Server Push 支持,需要使用 Polling Long-Polling 等变通模式
+
+#### gRPC
+上面提到了在 HTTP 及 TCP 协议之上构建 RPC 协议各自的优缺点,相比于 Dubbo 构建于 TCP 传输层之上,Google 选择将 gRPC 
直接定义在 HTTP/2 协议之上。
+gRPC 的优势由HTTP2 和 Protobuf 继承而来。
+
+- 基于 HTTP2 的协议足够简单,用户学习成本低,天然有 server push/ 多路复用 / 流量控制能力
+- 基于 Protobuf 的多语言跨平台二进制兼容能力,提供强大的统一跨语言能力
+- 基于协议本身的生态比较丰富,k8s/etcd 等组件的天然支持协议,云原生的事实协议标准
+
+但是也存在部分问题
+
+- 对服务治理的支持比较基础,更偏向于基础的 RPC 功能,协议层缺少必要的统一定义,对于用户而言直接用起来并不容易。
+- 强绑定 protobuf 的序列化方式,需要较高的学习成本和改造成本,对于现有的偏单语言的用户而言,迁移成本不可忽视
+
+#### 最终的选择 Triple
+最终我们选择了兼容 gRPC ,以 HTTP2 作为传输层构建新的协议,也就是 Triple。
+
+容器化应用程序和微服务的兴起促进了针对负载内容优化技术的发展。 客户端中使用的传统通信协议( RESTFUL或其他基于 HTTP 
的自定义协议)难以满足应用在性能、可维护性、扩展性、安全性等方便的需求。一个跨语言、模块化的协议会逐渐成为新的应用开发协议标准。自从 2017 年 gRPC 
协议成为 CNCF 的项目后,包括 k8s、etcd 等越来越多的基础设施和业务都开始使用 gRPC 的生态,作为云原生的微服务化框架, Dubbo 
的新协议也完美兼容了 gRPC。并且,对于 gRPC 协议中一些不完善的部分, Triple 也将进行增强和补充。
+
+那么,Triple 协议是否解决了上面我们提到的一系列问题呢?
+
+- 性能上: Triple 协议采取了 metadata 和 payload 分离的策略,这样就可以避免中间设备,如网关进行 payload 
的解析和反序列化,从而降低响应时间。
+- 路由支持上,由于 metadata 支持用户添加自定义 header ,用户可以根据 header 
更方便的划分集群或者进行路由,这样发布的时候切流灰度或容灾都有了更高的灵活性。
+- 安全性上,支持双向TLS认证(mTLS)等加密传输能力。
+- 易用性上,Triple 除了支持原生 gRPC 所推荐的 Protobuf 序列化外,使用通用的方式支持了 Hessian / JSON 
等其他序列化,能让用户更方便的升级到 Triple 协议。对原有的 Dubbo 服务而言,修改或增加 Triple 协议 
只需要在声明服务的代码块添加一行协议配置即可,改造成本几乎为 0。
+
+### Triple 协议
+
+![Triple 协议通信方式](/imgs/v3/concepts/triple.png)
+
+- 现状
+
+1、完整兼容grpc、客户端/服务端可以与原生grpc客户端打通
+
+2、目前已经经过大规模生产实践验证,达到生产级别
+
+- 特点与优势
+
+1、具备跨语言互通的能力,传统的多语言多 SDK 模式和 Mesh 化跨语言模式都需要一种更通用易扩展的数据传输格式。
+
+2、提供更完善的请求模型,除了 Request/Response 模型,还应该支持 Streaming 和 Bidirectional。
+
+3、易扩展、穿透性高,包括但不限于 Tracing / Monitoring 等支持,也应该能被各层设备识别,网关设施等可以识别数据报文,对 Service 
Mesh 部署友好,降低用户理解难度。
+
+4、多种序列化方式支持、平滑升级
+
+5、支持 Java 用户无感知升级,不需要定义繁琐的 IDL 文件,仅需要简单的修改协议名便可以轻松升级到 Triple 协议
+
+#### Triple 协议内容介绍
+
+基于 grpc 协议进行进一步扩展
+
+- Service-Version → "tri-service-version" {Dubbo service version}
+- Service-Group → "tri-service-group" {Dubbo service group}
+- Tracing-ID → "tri-trace-traceid" {tracing id}
+- Tracing-RPC-ID → "tri-trace-rpcid" {_span id _}
+- Cluster-Info → "tri-unit-info" {cluster infomation}
+
+其中 Service-Version 跟 Service-Group 分别标识了 Dubbo 服务的 version 跟 group 信息,因为grpc的 
path 申明了 service name 跟 method name,相比于 Dubbo 协议,缺少了version 跟 group 
信息;Tracing-ID、Tracing-RPC-ID 用于全链路追踪能力,分别表示 tracing id 跟 span id 
信息;Cluster-Info 表示集群信息,可以使用其构建一些如集群划分等路由相关的灵活的服务治理能力。
+
+#### Triple Streaming
+
+Triple协议相比传统的unary方式,多了目前提供的Streaming RPC的能力
+
+- Streaming 用于什么场景呢?
+
+在一些大文件传输、直播等应用场景中, 
consumer或provider需要跟对端进行大量数据的传输,由于这些情况下的数据量是非常大的,因此是没有办法可以在一个RPC的数据包中进行传输,因此对于这些数据包我们需要对数据包进行分片之后,通过多次RPC调用进行传输,如果我们对这些已经拆分了的RPC数据包进行并行传输,那么到对端后相关的数据包是无序的,需要对接收到的数据进行排序拼接,相关的逻辑会非常复杂。但如果我们对拆分了的RPC数据包进行串行传输,那么对应的网络传输RTT与数据处理的时延会是非常大的。
+
+为了解决以上的问题,并且为了大量数据的传输以流水线方式在consumer与provider之间传输,因此Streaming RPC的模型应运而生。
+
+通过Triple协议的Streaming 
RPC方式,会在consumer跟provider之间建立多条用户态的长连接,Stream。同一个TCP连接之上能同时存在多个Stream,其中每条Stream都有StreamId进行标识,对于一条Stream上的数据包会以顺序方式读写。
+
+## 使用方式 - Java
+
+### Protobuf 方式
+
+1. 编写 IDL 文件
+    ```protobuf
+    syntax = "proto3";
+    option java_multiple_files = true;
+    option java_package = "org.apache.dubbo.hello";
+    option java_outer_classname = "HelloWorldProto";
+    option objc_class_prefix = "HLW";
+    package helloworld;
+    // The request message containing the user's name.
+    message HelloRequest {
+      string name = 1;
+    }
+    // The response message containing the greetings
+    message HelloReply {
+      string message = 1;
+    }
+    ```
+
+2. 添加编译 protobuf 的 extension 和 plugin (以 maven 为例)
+    ```xml
+       <extensions>
+                <extension>
+                    <groupId>kr.motd.maven</groupId>
+                    <artifactId>os-maven-plugin</artifactId>
+                    <version>1.6.1</version>
+                </extension>
+            </extensions>
+            <plugins>
+                <plugin>
+                    <groupId>org.xolstice.maven.plugins</groupId>
+                    <artifactId>protobuf-maven-plugin</artifactId>
+                    <version>0.6.1</version>
+                    <configuration>
+                        
<protocArtifact>com.google.protobuf:protoc:3.7.1:exe:${os.detected.classifier}</protocArtifact>
+                        <pluginId>triple-java</pluginId>
+                        
<outputDirectory>build/generated/source/proto/main/java</outputDirectory>
+                    </configuration>
+                    <executions>
+                        <execution>
+                            <goals>
+                                <goal>compile</goal>
+                                <goal>test-compile</goal>
+                            </goals>
+                        </execution>
+                    </executions>
+                </plugin>
+            </plugins>
+    ```
+
+3. 构建/ 编译生成 protobuf Message 类
+    ```shell
+    mvn clean install
+    ```
+
+### Unary 方式
+
+1.  编写 Java 接口
+    ```java
+    import org.apache.dubbo.hello.HelloReply;
+    import org.apache.dubbo.hello.HelloRequest;
+    public interface IGreeter {
+        /**
+         * <pre>
+         *  Sends a greeting
+         * </pre>
+         */
+        HelloReply sayHello(HelloRequest request);
+    }
+    ```
+
+2. 创建 Provider
+    ```java
+        public static void main(String[] args) throws InterruptedException {
+            ServiceConfig<IGreeter> service = new ServiceConfig<>();
+            service.setInterface(IGreeter.class);
+            service.setRef(new IGreeter1Impl());
+            // 这里需要显示声明使用的协议为triple 
+            service.setProtocol(new ProtocolConfig(CommonConstants.TRIPLE, 
50051));
+            service.setApplication(new ApplicationConfig("demo-provider"));
+            service.setRegistry(new 
RegistryConfig("zookeeper://127.0.0.1:2181"));
+            service.export();
+            System.out.println("dubbo service started");
+            new CountDownLatch(1).await();
+        }
+    ```
+
+
+3. 创建 Consumer
+
+    ```java
+    public static void main(String[] args) throws IOException {
+        ReferenceConfig<IGreeter> ref = new ReferenceConfig<>();
+        ref.setInterface(IGreeter.class);
+        ref.setCheck(false);
+        ref.setProtocol(CommonConstants.TRIPLE);
+        ref.setLazy(true);
+        ref.setTimeout(100000);
+        ref.setApplication(new ApplicationConfig("demo-consumer"));
+        ref.setRegistry(new RegistryConfig("zookeeper://127.0.0.1:2181"));
+        final IGreeter iGreeter = ref.get();
+        System.out.println("dubbo ref started");
+        try {
+            final HelloReply reply = 
iGreeter.sayHello(HelloRequest.newBuilder()
+                    .setName("name")
+                    .build());
+            TimeUnit.SECONDS.sleep(1);
+            System.out.println("Reply:" + reply);
+        } catch (Throwable t) {
+            t.printStackTrace();
+        }
+        System.in.read();
+    }
+    ```
+
+4. 运行 Provider 和 Consumer ,可以看到请求正常返回
+    ```java
+   > Reply:message: "name"
+    ```
+
+### stream 方式
+
+1.  编写 Java 接口
+    ```java
+    import org.apache.dubbo.hello.HelloReply;
+    import org.apache.dubbo.hello.HelloRequest;
+    public interface IGreeter {
+        /**
+       * <pre>
+       *  Sends greeting by stream
+       * </pre>
+        */
+           StreamObserver<HelloRequest> sayHello(StreamObserver<HelloReply> 
replyObserver);
+    }
+    ```
+
+2. 编写实现类
+    ```java
+       public class IStreamGreeterImpl implements IStreamGreeter {
+           @Override
+           public StreamObserver<HelloRequest> 
sayHello(StreamObserver<HelloReply> replyObserver) {
+               return new StreamObserver<HelloRequest>() {
+                   private List<HelloReply> replyList = new ArrayList<>();
+                   @Override
+                   public void onNext(HelloRequest helloRequest) {
+                       System.out.println("onNext receive request name:" + 
helloRequest.getName());
+                       replyList.add(HelloReply.newBuilder()
+                           .setMessage("receive name:" + 
helloRequest.getName())
+                           .build());
+                   }
+                   @Override
+                   public void onError(Throwable cause) {
+                       System.out.println("onError");
+                       replyObserver.onError(cause);
+                   }
+                   @Override
+                   public void onCompleted() {
+                       System.out.println("onComplete receive request size:" + 
replyList.size());
+                       for (HelloReply reply : replyList) {
+                           replyObserver.onNext(reply);
+                       }
+                       replyObserver.onCompleted();
+                   }
+               };
+           }
+       }
+    ```
+
+3. 创建 Provider
+
+    ```java
+       public class StreamProvider {
+           public static void main(String[] args) throws InterruptedException {
+               ServiceConfig<IStreamGreeter> service = new ServiceConfig<>();
+               service.setInterface(IStreamGreeter.class);
+               service.setRef(new IStreamGreeterImpl());
+               service.setProtocol(new ProtocolConfig(CommonConstants.TRIPLE, 
50051));
+               service.setApplication(new 
ApplicationConfig("stream-provider"));
+               service.setRegistry(new 
RegistryConfig("zookeeper://127.0.0.1:2181"));
+               service.export();
+               System.out.println("dubbo service started");
+               new CountDownLatch(1).await();
+           }
+       }
+    ```
+
+4. 创建 Consumer
+
+    ```java
+       public class StreamConsumer {
+           public static void main(String[] args) throws InterruptedException, 
IOException {
+               ReferenceConfig<IStreamGreeter> ref = new ReferenceConfig<>();
+               ref.setInterface(IStreamGreeter.class);
+               ref.setCheck(false);
+               ref.setProtocol(CommonConstants.TRIPLE);
+               ref.setLazy(true);
+               ref.setTimeout(100000);
+               ref.setApplication(new ApplicationConfig("stream-consumer"));
+               ref.setRegistry(new 
RegistryConfig("zookeeper://mse-6e9fda00-p.zk.mse.aliyuncs.com:2181"));
+               final IStreamGreeter iStreamGreeter = ref.get();
+               System.out.println("dubbo ref started");
+               try {
+                   StreamObserver<HelloRequest> streamObserver = 
iStreamGreeter.sayHello(new StreamObserver<HelloReply>() {
+                       @Override
+                       public void onNext(HelloReply reply) {
+                           System.out.println("onNext");
+                           System.out.println(reply.getMessage());
+                       }
+                       @Override
+                       public void onError(Throwable throwable) {
+                           System.out.println("onError:" + 
throwable.getMessage());
+                       }
+                       @Override
+                       public void onCompleted() {
+                           System.out.println("onCompleted");
+                       }
+                   });
+                   streamObserver.onNext(HelloRequest.newBuilder()
+                       .setName("tony")
+                       .build());
+                   streamObserver.onNext(HelloRequest.newBuilder()
+                       .setName("nick")
+                       .build());
+                   streamObserver.onCompleted();
+               } catch (Throwable t) {
+                   t.printStackTrace();
+               }
+               System.in.read();
+           }
+       }
+    ```
+
+5. 运行 Provider 和 Consumer ,可以看到请求正常返回了
+    ```java
+    > onNext\
+    > receive name:tony\
+    > onNext\
+    > receive name:nick\
+    > onCompleted
+    ```
+
+### 其他序列化方式
+省略上文中的 1-3 步,指定 Provider 和 Consumer 使用的协议即可完成协议升级。
+
+## 使用方式 - Go
+
+TBD
+
+## 使用方式 - Node.js
+
+暂不支持
+
+## 使用方式 - Rust
+
+TBD
+
+## 常见问题
+
+### Q1
+protobuf 类找不到
+
+由于 Triple 协议底层需要依赖 protobuf 协议进行传输,即使定义的服务接口不使用 protobuf 也需要在环境中引入 protobuf 
的依赖。
+
+```xml
+        <dependency>
+            <groupId>com.google.protobuf</groupId>
+            <artifactId>protobuf-java</artifactId>
+            <version>3.19.4</version>
+        </dependency>
+```
+
+### Q2
+如何原生接入网关?
+
+对于需要网关接入的 Dubbo 用户,Triple 协议提供了更加原生的方式,让网关开发或者使用开源的 grpc 网关组件更加简单。网关可以选择不解析 
payload ,在性能上也有很大提高。在使用 Dubbo 协议时,语言相关的序列化方式是网关的一个很大痛点,而传统的 HTTP 转 Dubbo 
的方式对于跨语言序列化几乎是无能为力的。同时,由于 Triple 的协议元数据都存储在请求头中,网关可以轻松的实现定制需求,如路由和限流等功能。
+
+### 总结
+
+在API领域,最重要的趋势是标准化技术的崛起。Triple 协议是 Dubbo3 推出的主力协议。它采用分层设计,其数据交换格式基于Protobuf 
(Protocol Buffers) 协议开发,具备优秀的序列化/反序列化效率,当然还支持多种序列化方式,也支持众多开发语言。在传输层协议,Triple 
选择了 HTTP/2,相较于 
HTTP/1.1,其传输效率有了很大提升。此外HTTP/2作为一个成熟的开放标准,具备丰富的安全、流控等能力,同时拥有良好的互操作性。Triple 
不仅可以用于Server端服务调用,也可以支持浏览器、移动App和IoT设备与后端服务的交互,同时 Triple协议无缝支持 Dubbo3 的全部服务治理能力。
+
+在Cloud 
Native的潮流下,跨平台、跨厂商、跨环境的系统间互操作性的需求必然会催生基于开放标准的RPC技术,而gRPC顺应了历史趋势,得到了越来越广泛地应用。在微服务领域,Triple协议的提出与落地,是
 Dubbo3 迈向云原生微服务的一大步。

Reply via email to