| <rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Apache Dubbo – 概念体系</title><link>https://dubbo.apache.org/zh-cn/overview/mannual/golang-sdk/preface/concept/</link><description>Recent content in 概念体系 on Apache Dubbo</description><generator>Hugo -- gohugo.io</generator><language>zh-cn</language><atom:link href="https://dubbo.apache.org/zh-cn/overview/mannual/golang-sdk/preface/concept/index.xml" rel="self" type="application/rss+xml"/><item><title>Overview: 多语言 RPC</title><link>https://dubbo.apache.org/zh-cn/overview/mannual/golang-sdk/preface/concept/multi_language/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/zh-cn/overview/mannual/golang-sdk/preface/concept/multi_language/</guid><description> |
| <p><img src="https://dubbo.apache.org/imgs/docs3-v2/golang-sdk/concept/rpc/multi_language/dubbogo-3.0-invocation.png" alt="img"></p> |
| <h3 id="跨语言调用">跨语言调用</h3> |
| <p>随着微服务场景的大范围应用,多语言场景越来越普遍,开发人员更愿意使用更适合的语言,来实现一个复杂系统的不同模块。例如使用 C 来编写网关,使用 Go 来编写 K8S 资源 operator,使用 Java 来编写业务应用。语言与场景并不是绑定的,企业往往可以结合自身发展的技术栈、开发人员的专长,来选型合适的语言。</p> |
| <p>在多语言场景中,跨语言调用能力就显得十分重要。</p> |
| <p>跨语言能力本质上是 <a href="../protocol/">【网络协议】</a> 提供的能力。如何方便地让用户使用需要的网络协议、针对合适的跨语言场景进行开发、享受 Dubbo 生态的服务治理能力,是 Dubbo-go 服务框架所关心的。</p> |
| <h3 id="跨生态">跨生态</h3> |
| <p>Dubbo-go 服务框架提供了跨生态的能力,开发人员可以使用 Dubbo-go 以及其 <a href="../../../refer/ecology/">生态项目</a> 建立 HTTP/前端服务、Dubbo/Spring 应用、gRPC 生态应用之间的联系。</p></description></item><item><title>Overview: 泛化调用</title><link>https://dubbo.apache.org/zh-cn/overview/mannual/golang-sdk/preface/concept/generic/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/zh-cn/overview/mannual/golang-sdk/preface/concept/generic/</guid><description> |
| <p>泛化调用是一种 Dubbo-Go 的特殊调用方式,它允许中间节点在没有接口信息的情况下传递调用信息,常被用于测试、网关的场景下。泛化调用支持 Dubbo 和 Triple 协议,但是目前序列化方案只支持 Hessian。</p> |
| <h2 id="背景">背景</h2> |
| <p>为了便于理解,这篇文档中以网关使用场景介绍泛化调用。我们先来考虑普通调用(非泛化调用)。下图包含了 consumer 和 provider 两个关键角色(后文中用 endpoint 代表一个 consumer 或一个 provider),各自都有一份关于 org.apache.dubbo.sample.User 接口的定义。假定在调用行为中需要使用 org.apache.dubbo.sample.User 接口。</p> |
| <p><img src="https://dubbo.apache.org/imgs/docs3-v2/golang-sdk/concept/rpc/generic/1631941941270-86ce9845-5a88-4cb5-8c8a-da8ae7eeb4d5.png" alt="img"></p> |
| <p>RPC 需要借助网络介质传输,因此数据不能以 go struct 形式传输,而必须以二进制形式传输。这就要求 consumer 端在传输前,需要将实现 org.apache.dubbo.sample.User 接口的结构体序列化为二进制格式。同样的,对于 provider 端,需要将二进制数据反序列化为结构体信息。<strong>总之,普通调用要求接口信息在每一个 endpoint 必须有相同的定义,这样才能保证数据序列化和反序列化的结果与预期一致</strong>。</p> |
| <p>在网关场景下,网关不可能存储全部接口定义。比如一个网关需要转发 100 个服务调用,每个服务需要的接口数量为 10 个,普通调用要求把 1000 个(100 * 10)接口定义提前全部存储在网关内,这显然是难以做到的。所以有没有一种方式可以既不需要提前存储接口定义,又能正确转发调用呢?答案是肯定的,这就是使用泛化调用的原因。</p> |
| <h2 id="原理">原理</h2> |
| <p>泛化调用本质上就是把复杂结构转化为通用结构,这里说的通用结构是指 map、string 等,网关是可以顺利解析并传递这些通用结构的。</p> |
| <p><img src="https://dubbo.apache.org/imgs/docs3-v2/golang-sdk/concept/rpc/generic/1632207075184-25939db4-f384-452e-a0b8-e1deff7971de.png" alt="img"></p> |
| <p>目前,Dubbo-go v3 只支持 Map 泛化方式(default)。我们以 User 接口为例,其定义如下所示。</p> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#586e75">// definition |
| </span></span></span><span style="display:flex;"><span><span style="color:#586e75"></span><span style="color:#268bd2">type</span> User <span style="color:#268bd2">struct</span> { |
| </span></span><span style="display:flex;"><span> ID <span style="color:#dc322f">string</span> |
| </span></span><span style="display:flex;"><span> Name <span style="color:#dc322f">string</span> |
| </span></span><span style="display:flex;"><span> Age <span style="color:#dc322f">int32</span> |
| </span></span><span style="display:flex;"><span>} |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">func</span> (u <span style="color:#719e07">*</span>User) <span style="color:#268bd2">JavaClassName</span>() <span style="color:#dc322f">string</span> { |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> <span style="color:#2aa198">&#34;org.apache.dubbo.sample.User&#34;</span> |
| </span></span><span style="display:flex;"><span>} |
| </span></span></code></pre></div><p>假定调用一个服务需要一个 user 作为入参,其定义如下所示。</p> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#586e75">// an instance of the User |
| </span></span></span><span style="display:flex;"><span><span style="color:#586e75"></span>user <span style="color:#719e07">:=</span> <span style="color:#719e07">&amp;</span>User{ |
| </span></span><span style="display:flex;"><span> ID: <span style="color:#2aa198">&#34;1&#34;</span>, |
| </span></span><span style="display:flex;"><span> Name: <span style="color:#2aa198">&#34;Zhangsan&#34;</span>, |
| </span></span><span style="display:flex;"><span> Age: <span style="color:#2aa198">20</span>, |
| </span></span><span style="display:flex;"><span>} |
| </span></span></code></pre></div><p>那么在使用 Map 泛化方式下,user 会被自动转换为 Map 格式,如下所示。</p> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span>usermap <span style="color:#719e07">:=</span> <span style="color:#268bd2">map</span>[<span style="color:#268bd2">interface</span>{}]<span style="color:#268bd2">interface</span>{} { |
| </span></span><span style="display:flex;"><span> <span style="color:#2aa198">&#34;iD&#34;</span>: <span style="color:#2aa198">&#34;1&#34;</span>, |
| </span></span><span style="display:flex;"><span> <span style="color:#2aa198">&#34;name&#34;</span>: <span style="color:#2aa198">&#34;zhangsan&#34;</span>, |
| </span></span><span style="display:flex;"><span> <span style="color:#2aa198">&#34;age&#34;</span>: <span style="color:#2aa198">20</span>, |
| </span></span><span style="display:flex;"><span> <span style="color:#2aa198">&#34;class&#34;</span>: <span style="color:#2aa198">&#34;org.apache.dubbo.sample.User&#34;</span>, |
| </span></span><span style="display:flex;"><span>} |
| </span></span></code></pre></div><p>需要注意的是:</p> |
| <ul> |
| <li>Map 泛化方式会自动将首字母小写,即 ID 会被转换为 iD,如果需要对齐 Dubbo-Java 请考虑将 ID 改为 Id;</li> |
| <li>在 Map 中会自动插入 class 字段,用于标识原有接口类。</li> |
| </ul> |
| <h2 id="使用">使用</h2> |
| <p>泛化调用对 provider 端是透明的,即 provider 端不需要任何显式配置就可以正确处理泛化请求。</p> |
| <h3 id="基于-dubbo-url-泛化调用">基于 Dubbo URL 泛化调用</h3> |
| <p>基于 Filter 泛化调用对 consumer 是透明的,典型应用场景是网关。这种方式需要要求 Dubbo URL 中包含泛化调用标识,如下所示。</p> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-plain" data-lang="plain"><span style="display:flex;"><span>dubbo://127.0.0.1:20000/org.apache.dubbo.sample.UserProvider?generic=true&amp;... |
| </span></span></code></pre></div><p>这个 Dubbo URL 表达的语意是:</p> |
| <ul> |
| <li>RPC 协议为 dubbo;</li> |
| <li>org.apache.dubbo.sample.UserProvider 接口位于 127.0.0.1:20000;</li> |
| <li>使用泛化调用(generic=true)。</li> |
| </ul> |
| <p>Consumer 端的 Filter 会自动根据 Dubbo URL 携带的配置自动将普通调用转化为泛化调用,但是需要注意的是,在这种方式下响应结果是以泛化格式返回,不会自动转化为相应的对象。举个例子,在 map 泛化方式下,如果需要返回 User 类,那么 consumer 获得的相应是一个 User 类对应的 map。</p> |
| <h3 id="手动泛化调用">手动泛化调用</h3> |
| <p>手动泛化调用发起的请求不经过 filter,所以需要 consumer 端显式地发起泛化调用,典型应用场景是测试。在 <a href="https://github.com/apache/dubbo-go-samples/tree/master/generic">dubbo-go-samples</a> 中,为了便于测试都是采用手动调用的方式。</p> |
| <p>泛化调用不需要创建配置文件(dubbogo.yaml),但是需要在代码中手动配置注册中心、reference 等信息,初始化方法被封装到 newRefConf 方法中,如下所示。</p> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#268bd2">func</span> <span style="color:#268bd2">newRefConf</span>(appName, iface, protocol <span style="color:#dc322f">string</span>) config.ReferenceConfig { |
| </span></span><span style="display:flex;"><span> registryConfig <span style="color:#719e07">:=</span> <span style="color:#719e07">&amp;</span>config.RegistryConfig{ |
| </span></span><span style="display:flex;"><span> Protocol: <span style="color:#2aa198">&#34;zookeeper&#34;</span>, |
| </span></span><span style="display:flex;"><span> Address: <span style="color:#2aa198">&#34;127.0.0.1:2181&#34;</span>, |
| </span></span><span style="display:flex;"><span> } |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> refConf <span style="color:#719e07">:=</span> config.ReferenceConfig{ |
| </span></span><span style="display:flex;"><span> InterfaceName: iface, |
| </span></span><span style="display:flex;"><span> Cluster: <span style="color:#2aa198">&#34;failover&#34;</span>, |
| </span></span><span style="display:flex;"><span> Registry: []<span style="color:#dc322f">string</span>{<span style="color:#2aa198">&#34;zk&#34;</span>}, |
| </span></span><span style="display:flex;"><span> Protocol: protocol, |
| </span></span><span style="display:flex;"><span> Generic: <span style="color:#2aa198">&#34;true&#34;</span>, |
| </span></span><span style="display:flex;"><span> } |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> rootConfig <span style="color:#719e07">:=</span> config.<span style="color:#268bd2">NewRootConfig</span>(config.<span style="color:#268bd2">WithRootRegistryConfig</span>(<span style="color:#2aa198">&#34;zk&#34;</span>, registryConfig)) |
| </span></span><span style="display:flex;"><span> _ = rootConfig.<span style="color:#268bd2">Init</span>() |
| </span></span><span style="display:flex;"><span> _ = refConf.<span style="color:#268bd2">Init</span>(rootConfig) |
| </span></span><span style="display:flex;"><span> refConf.<span style="color:#268bd2">GenericLoad</span>(appName) |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> refConf |
| </span></span><span style="display:flex;"><span>} |
| </span></span></code></pre></div><p>newRefConf 方法接收三个参数,分别是:</p> |
| <ul> |
| <li>appName: 应用名;</li> |
| <li>iface: 服务接口名;</li> |
| <li>protocol: RPC 协议,目前只支持 dubbo 和 tri(triple 协议)。</li> |
| </ul> |
| <p>在上述方法中,为了保持函数简单性,把注册中心设置为一个固定值,即使用在 127.0.0.1:2181 的 ZooKeeper 作为注册中心,在实践中可以根据实际情况自由定制。</p> |
| <p>我们可以很容易的获取一个 ReferenceConfig 实例,暂时命名为 refConf。</p> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span>refConf <span style="color:#719e07">:=</span> <span style="color:#268bd2">newRefConf</span>(<span style="color:#2aa198">&#34;example.dubbo.io&#34;</span>, <span style="color:#2aa198">&#34;org.apache.dubbo.sample.UserProvider&#34;</span>, <span style="color:#2aa198">&#34;tri&#34;</span>) |
| </span></span></code></pre></div><p>接着我们可以对 org.apache.dubbo.sample.UserProvider 服务的 GetUser 方法发起泛化调用。</p> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span>resp, err <span style="color:#719e07">:=</span> refConf. |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">GetRPCService</span>().(<span style="color:#719e07">*</span>generic.GenericService). |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">Invoke</span>( |
| </span></span><span style="display:flex;"><span> context.<span style="color:#268bd2">TODO</span>(), |
| </span></span><span style="display:flex;"><span> <span style="color:#2aa198">&#34;GetUser&#34;</span>, |
| </span></span><span style="display:flex;"><span> []<span style="color:#dc322f">string</span>{<span style="color:#2aa198">&#34;java.lang.String&#34;</span>}, |
| </span></span><span style="display:flex;"><span> []hessian.Object{<span style="color:#2aa198">&#34;A003&#34;</span>}, |
| </span></span><span style="display:flex;"><span> ) |
| </span></span></code></pre></div><p>GenericService 的 Invoke 方法接收四个参数,分别是:</p> |
| <ul> |
| <li>context;</li> |
| <li>方法名: 在这个例子中表示调用 GetUser 方法;</li> |
| <li>参数类型: GetUser 方法接收一个 string 类型的参数,如果目标方法接收多个参数,可以写为 <code>[]string{&quot;type1&quot;, &quot;type2&quot;, ...}</code>,如果目前方法是无参的,则需要填入一个空数组 <code>[]string{}</code>;</li> |
| <li>实参: 写法同参数类型,如果是无参函数,依然要填入一个空数组 <code>[]hessian.Object{}</code> 占位。</li> |
| </ul> |
| <p>注意:在目前版本中,无参调用会出现崩溃问题。</p> |
| <p>相关阅读:<a href="https://blog.csdn.net/weixin_39860915/article/details/122738548">【Dubbo-go 服务代理模型】</a></p></description></item><item><title>Overview: 服务注册发现</title><link>https://dubbo.apache.org/zh-cn/overview/mannual/golang-sdk/preface/concept/registry/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/zh-cn/overview/mannual/golang-sdk/preface/concept/registry/</guid><description> |
| <h2 id="1-dubbo-的注册中心">1. Dubbo 的注册中心</h2> |
| <p>注册中心在 RPC 场景下负责保存服务端应用的信息。</p> |
| <p>服务端注册接口信息和到自身地址到注册中心,客户端从注册中心读取和订阅需要调用的地址列表。整个架构如图所示:</p> |
| <p><img src="https://dubbo.apache.org/imgs/architecture.png" alt="img"></p> |
| <p>关于 Dubbo 服务发现细节,详情可参考 <a href="https://dubbo.apache.org/zh-cn/docs/concepts/service-discovery/">Dubbo 官网的概念介绍</a></p> |
| <h2 id="2-服务发现概念">2. 服务发现概念</h2> |
| <p>Dubbo 生态中,服务发现有以下主要概念:</p> |
| <ul> |
| <li> |
| <p>应用 Application</p> |
| <p>应用是一个 dubbo 服务进程,对应一个应用名。</p> |
| </li> |
| <li> |
| <p>接口(服务)</p> |
| <p>接口是一个 RPC 接口类,例如一个通过 proto 定义的 Service,再例如一个 Java Interface 类。一个 dubbo 进程可以包含多个服务/接口。</p> |
| </li> |
| <li> |
| <p>方法</p> |
| <p>方法在接口中定义,一个接口可以包含多个方法。</p> |
| </li> |
| <li> |
| <p>参数列表</p> |
| <p>参数列表在方法中定义。由于 Java 支持重载,一个方法可以包含多个参数列表。对于 Go 是一对一的关系。</p> |
| </li> |
| <li> |
| <p>注册信息</p> |
| <p>在“接口级服务发现”的场景下,注册信息主要包含应用名、接口列表、元数据信息、以及服务端的IP地址等。以 URL 的形式保存在注册中心,供客户端发起调用前查询。</p> |
| <p>在“应用级服务发现”的场景下,注册信息只包含应用名、应用名到接口的映射等少量应用级别的信息,接口级别的信息作为元数据保存在元数据中心。</p> |
| </li> |
| <li> |
| <p>元数据</p> |
| <p>元数据指接口信息,例如接口名、包含的方法、方法对应的参数、序列化方式、协议等等信息。</p> |
| </li> |
| <li> |
| <p>注册中心</p> |
| <p>注册中心用于保存服务端的信息。</p> |
| </li> |
| <li> |
| <p>元数据中心</p> |
| <p>元数据中心用于保存服务端的元数据信息,在“应用级服务发现”场景中,作为“服务自省”阶段的依赖。</p> |
| </li> |
| </ul> |
| <p>Dubbo-go 中的服务网格能力,引入以下几个概念</p> |
| <ul> |
| <li> |
| <p>主机名</p> |
| <p>主机名当前应用在 k8s 上注册的 Service 名。其他应用可以通过主机名访问本应用实例。</p> |
| </li> |
| <li> |
| <p>端点</p> |
| <p>端点包含实例的 IP 地址、端口。</p> |
| </li> |
| <li> |
| <p>集群</p> |
| <p>集群 ID 保存了从{主机名、集群子集名、端口}</p> |
| <p>集群保存集群 ID 到所有其包含端点的映射关系。</p> |
| </li> |
| <li> |
| <p>服务网格元数据</p> |
| <p>服务网格元数据是接口名到主机名到映射,用于客户端查询所需接口的主机名信息。</p> |
| </li> |
| </ul> |
| <h2 id="3-dubbo-go-注册中心">3. Dubbo-go 注册中心</h2> |
| <p>Dubbo-go 支持的注册中心类型如下:</p> |
| <table> |
| <thead> |
| <tr> |
| <th>注册中心</th> |
| <th>注册中心名(用于配置)</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td>Zookeeper</td> |
| <td>zookeeper</td> |
| </tr> |
| <tr> |
| <td>Nacos</td> |
| <td>nacos</td> |
| </tr> |
| <tr> |
| <td>Etcd</td> |
| <td>etcd</td> |
| </tr> |
| <tr> |
| <td>Consul</td> |
| <td>consul</td> |
| </tr> |
| </tbody> |
| </table> |
| <p>相关阅读:<a href="https://developer.aliyun.com/article/764173">【应用级服务发现解析】</a></p></description></item><item><title>Overview: 网络协议</title><link>https://dubbo.apache.org/zh-cn/overview/mannual/golang-sdk/preface/concept/protocol/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/zh-cn/overview/mannual/golang-sdk/preface/concept/protocol/</guid><description> |
| <h2 id="1-rpc-服务框架与网络协议">1. RPC 服务框架与网络协议</h2> |
| <p>网络协议在 RPC 场景十分重要,在微服务场景下,服务进程之间的通信依赖可以连通的网络,以及client与server 端保持一致的网络协议。网络协议是一个抽象的概念,站在 Dubbo-go 应用开发的角度,不妨把我们关注的协议分为三个维度来讨论。</p> |
| <h3 id="11-打解包协议">1.1 打解包协议</h3> |
| <p>Dubbo-go 服务框架内置的打解包协议都是基于 TCP/IP 协议栈的,在此基础之上,封装/引入了多种协议,例如 Triple(dubbo3)、Dubbo、gRPC。</p> |
| <p>这一类协议重点关注 TCP 报文的封装和拆解过程,保证点对点的可靠通信。</p> |
| <p>在 dubbo-go 生态中,支持多种网络往往指的这一类协议。</p> |
| <h3 id="12-序列化协议">1.2 序列化协议</h3> |
| <p>序列化协议负责将内存中的对象以特定格式序列化为二进制流。一些主流的序列化库有:具有较好可读性、应用广泛的 json 序列化方式;较高压缩效率,性能较好的 protobuf 序列化方式;适配与 Java 语言的 hessian2 序列化方式等。Dubbo-go 内置了这三种序列化方式</p> |
| <p>序列化协议是需要开发者在业务开发过程中关注的,序列化协议往往需要特定的对象标注:</p> |
| <p>一个由 protoc-gen-go 生成的 protobuf 序列对象的例子:</p> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-protobuf" data-lang="protobuf"><span style="display:flex;"><span>type HelloRequest struct { |
| </span></span><span style="display:flex;"><span> state protoimpl.MessageState |
| </span></span><span style="display:flex;"><span> sizeCache protoimpl.SizeCache |
| </span></span><span style="display:flex;"><span> unknownFields protoimpl.UnknownFields |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> Name <span style="color:#dc322f">string</span> `protobuf<span style="color:#719e07">:</span><span style="color:#2aa198">&#34;bytes,1,opt,name=name,proto3&#34;</span> json<span style="color:#719e07">:</span><span style="color:#2aa198">&#34;name,omitempty&#34;</span>` |
| </span></span><span style="display:flex;"><span>} |
| </span></span></code></pre></div><p>一个可与 java 服务互通的 hessian2 序列化对象</p> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#268bd2">type</span> HelloRequest <span style="color:#268bd2">struct</span> { |
| </span></span><span style="display:flex;"><span> Name <span style="color:#dc322f">string</span> <span style="color:#2aa198">`hessian:&#34;name&#34;`</span> |
| </span></span><span style="display:flex;"><span>} |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">func</span> (u <span style="color:#719e07">*</span>HelloRequest) <span style="color:#268bd2">JavaClassName</span>() <span style="color:#dc322f">string</span> { |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> <span style="color:#2aa198">&#34;org.apache.dubbo.sample.User&#34;</span> |
| </span></span><span style="display:flex;"><span>} |
| </span></span></code></pre></div><p>序列化协议与打解包协议的关系</p> |
| <ul> |
| <li>一种打解包协议可以适配于多种序列化协议支持:例如,您可以使用 dubbogo 的 triple 协议来传递 hessian序列化参数与 Dubbo-java 服务框架互通;传递 pb 序列化参数与原生 gRPC 服务互通;通过实现接口来自定义您的希望的序列化方式例如 json,从而传递具有较强可读性的参数。</li> |
| </ul> |
| <h3 id="13-接口协议">1.3 接口协议</h3> |
| <p>接口协议,是由业务开发人员开发并且维护的协议,用于描述服务接口的信息。例如接口名、方法、参数类型。</p> |
| <p>以 Triple/gRPC 为例,开发人员可以使用插件,从 proto 文件中定义的接口生成存根(.pb.go 文件),存根文件内包含接口所有信息,及接口协议。</p> |
| <p>在编写服务时,客户端和服务端同时引入相同的接口,即可保证客户端发起针对特定接口和方法的调用,能被服务端正确识别和响应。</p> |
| <p>一个由 proto 编写的接口描述文件:</p> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-protobuf" data-lang="protobuf"><span style="display:flex;"><span>syntax <span style="color:#719e07">=</span> <span style="color:#2aa198">&#34;proto3&#34;</span>; |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">package</span> api; |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">option</span> go_package <span style="color:#719e07">=</span> <span style="color:#2aa198">&#34;./;api&#34;</span>; |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span><span style="color:#586e75">// The greeting service definition. |
| </span></span></span><span style="display:flex;"><span><span style="color:#586e75"></span><span style="color:#268bd2">service</span> Greeter { |
| </span></span><span style="display:flex;"><span> <span style="color:#586e75">// Sends a greeting |
| </span></span></span><span style="display:flex;"><span><span style="color:#586e75"></span> <span style="color:#719e07">rpc</span> SayHello (HelloRequest) <span style="color:#719e07">returns</span> (User) {} |
| </span></span><span style="display:flex;"><span> <span style="color:#586e75">// Sends a greeting via stream |
| </span></span></span><span style="display:flex;"><span><span style="color:#586e75"></span> <span style="color:#719e07">rpc</span> SayHelloStream (stream HelloRequest) <span style="color:#719e07">returns</span> (stream User) {} |
| </span></span><span style="display:flex;"><span>} |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span><span style="color:#586e75">// The request message containing the user&#39;s name. |
| </span></span></span><span style="display:flex;"><span><span style="color:#586e75"></span><span style="color:#268bd2">message</span> <span style="color:#268bd2">HelloRequest</span> { |
| </span></span><span style="display:flex;"><span> <span style="color:#dc322f">string</span> name <span style="color:#719e07">=</span> <span style="color:#2aa198">1</span>; |
| </span></span><span style="display:flex;"><span>} |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span><span style="color:#586e75">// The response message containing the greetings |
| </span></span></span><span style="display:flex;"><span><span style="color:#586e75"></span><span style="color:#268bd2">message</span> <span style="color:#268bd2">User</span> { |
| </span></span><span style="display:flex;"><span> <span style="color:#dc322f">string</span> name <span style="color:#719e07">=</span> <span style="color:#2aa198">1</span>; |
| </span></span><span style="display:flex;"><span> <span style="color:#dc322f">string</span> id <span style="color:#719e07">=</span> <span style="color:#2aa198">2</span>; |
| </span></span><span style="display:flex;"><span> <span style="color:#dc322f">int32</span> age <span style="color:#719e07">=</span> <span style="color:#2aa198">3</span>; |
| </span></span><span style="display:flex;"><span>} |
| </span></span></code></pre></div><p>接口协议与序列化协议的关系</p> |
| <ul> |
| <li>接口协议是抽象的概念,一种接口协议可以使用多种接口描述语言来编写,并且可以转化成多种序列化协议对象。</li> |
| </ul> |
| <h2 id="2-dubbo-go-支持的网络协议">2. Dubbo-go 支持的网络协议</h2> |
| <p>Dubbo-go 支持的网络协议和序列化方式如下:</p> |
| <table> |
| <thead> |
| <tr> |
| <th>协议</th> |
| <th>协议名 (用于配置)</th> |
| <th style="text-align:center">序列化方式</th> |
| <th>默认序列化方式</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td>Triple 【推荐】</td> |
| <td>tri</td> |
| <td style="text-align:center">pb/hessian2/msgpack/自定义</td> |
| <td>pb</td> |
| </tr> |
| <tr> |
| <td>Dubbo</td> |
| <td>dubbo</td> |
| <td style="text-align:center">hessian2</td> |
| <td>hessian2</td> |
| </tr> |
| <tr> |
| <td>gRPC</td> |
| <td>grpc</td> |
| <td style="text-align:center">pb</td> |
| <td>pb</td> |
| </tr> |
| <tr> |
| <td>jsonRPC</td> |
| <td>jsonrpc</td> |
| <td style="text-align:center">json</td> |
| <td>json</td> |
| </tr> |
| </tbody> |
| </table> |
| <p>相关阅读:<a href="https://developer.aliyun.com/article/878252">【Dubbo-go 服务代理模型】</a></p></description></item></channel></rss> |