自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

一文詳細(xì)解讀 Dubbo 中的 Http 協(xié)議

網(wǎng)絡(luò) 通信技術(shù)
說到 Dubbo 框架支持的協(xié)議,你的第一反應(yīng)是什么?大概會(huì)有 Dubbo 默認(rèn)支持的 dubbo 協(xié)議,以及老生常談的由當(dāng)當(dāng)貢獻(xiàn)給 Dubbo 的 rest 協(xié)議,或者是今天的主角 http。

 太陽(yáng)紅彤彤,花兒五顏六色,各位讀者朋友好,又來到了分享 Dubbo 知識(shí)點(diǎn)的時(shí)候了。說到 Dubbo 框架支持的協(xié)議,你的第一反應(yīng)是什么?大概會(huì)有 Dubbo 默認(rèn)支持的 dubbo 協(xié)議,以及老生常談的由當(dāng)當(dāng)貢獻(xiàn)給 Dubbo 的 rest 協(xié)議,或者是今天的主角 http。截止到目前,Dubbo 最新版本演進(jìn)到了 2.7.3,已經(jīng)支持了:dubbo,hessain,http,injvm,jsonrpc,memcached,native-thrift,thrift,redis,rest,rmi,webservice,xml 等協(xié)議,有些協(xié)議的使用方式還沒有補(bǔ)全到官方文檔中。原來 Dubbo 支持這么多協(xié)議,是不是有點(diǎn)出乎你的意料呢?

[[283525]]

 

這么多 RPC 協(xié)議,可能有人會(huì)產(chǎn)生如下的疑問:rest,jsonrpc,webservice 不都是依靠 http 通信嗎?為什么還單獨(dú)有一個(gè) http 協(xié)議?先不急著回答這個(gè)問題,而是引出今天的話題,先來介紹下 Dubbo 框架中所謂的 http 協(xié)議。

Dubbo 中的 http 協(xié)議

在 Dubbo 使用 http 協(xié)議和其他協(xié)議基本一樣,只需要指定 protocol 即可。

  1. <dubbo:protocol name="http" port="8080" server="jetty" /> 

server 屬性可選值:jetty,tomcat,servlet。

配置過后,當(dāng)服務(wù)消費(fèi)者向服務(wù)提供者發(fā)起調(diào)用,底層便會(huì)使用標(biāo)準(zhǔn)的 http 協(xié)議進(jìn)行通信??梢灾苯釉? https://github.com/apache/dubbo-samples 中找到官方示例,其中的子模塊:dubbo-samples-http 構(gòu)建了一個(gè) http 協(xié)議調(diào)用的例子。

為避免大家誤解,特在此聲明:本文中,所有的 http 協(xié)議特指的是 dubbo 中的 http 協(xié)議,并非那個(gè)大家耳熟能詳?shù)耐ㄓ玫?http 協(xié)議。

http 協(xié)議的底層原理

從默認(rèn)的 dubbo 協(xié)議改為 http 協(xié)議是非常簡(jiǎn)單的一件事,上面便是使用者視角所看到的全部的內(nèi)容了,接下來我們將會(huì)探討其底層實(shí)現(xiàn)原理。

翻看 Dubbo 的源碼,找到 HttpProtocol 的實(shí)現(xiàn),你可能會(huì)吃驚,基本就依靠 HttpProtocol 一個(gè)類,就實(shí)現(xiàn)了 http 協(xié)議

 

一文詳細(xì)解讀 Dubbo 中的 http 協(xié)議

 

要知道實(shí)現(xiàn)自定義的 dubbo 協(xié)議,有近 30 個(gè)類!http 協(xié)議實(shí)現(xiàn)的如此簡(jiǎn)單,背后主要原因有兩點(diǎn):

  1. remoting 層使用 http 通信,不需要自定義編解碼
  2. 借助了 Spring 提供的 HttpInvoker 封裝了 refer 和 exporter 的邏輯

Spring 提供的 HttpInvoker 是何方神圣呢?的確是一個(gè)比較生僻的概念,但并不復(fù)雜,簡(jiǎn)單來說,就是使用 Java 序列化將對(duì)象轉(zhuǎn)換成字節(jié),通過 http 發(fā)送出去,在 server 端,Spring 能根據(jù) Url 映射,找到容器中對(duì)應(yīng)的 Bean 反射調(diào)用的過程,沒見識(shí)過它也不要緊,可以通過下面的示例快速掌握這一概念。

 

Spring HttpInvoker

本節(jié)內(nèi)容可參見 Spring 文檔:https://docs.spring.io/spring/docs/4.3.24.RELEASE/spring-framework-reference/htmlsingle/#remoting-httpinvoker-server

下面的示例將會(huì)展示如何使用 Spring 原生的 HttpInvoker 實(shí)現(xiàn)遠(yuǎn)程調(diào)用。

創(chuàng)建服務(wù)提供者

  1. public class AccountServiceImpl implements AccountService { 
  2.  @Override 
  3.  public Account findById(int id) { 
  4.  Account account = new Account(id, new Date().toString()); 
  5.  return account; 
  6.  } 
  7. @Bean 
  8. AccountService accountService(){ 
  9.  return new AccountServiceImpl(); 
  10. @Bean("/AccountService"
  11. public HttpInvokerServiceExporter accountServiceExporter(AccountService accountService){ 
  12.  HttpInvokerServiceExporter exporter = new HttpInvokerServiceExporter(); 
  13.  exporter.setService(accountService); 
  14.  exporter.setServiceInterface(AccountService.class); 
  15.  return exporter; 

暴露服務(wù)的代碼相當(dāng)簡(jiǎn)單,需要注意兩點(diǎn):

  1. org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter 是 Spring 封裝的一個(gè)服務(wù)暴露器,它會(huì)以 serviceInterface 為公共接口,以 service 為實(shí)現(xiàn)類向外提供服務(wù)。
  2. @Bean("/AccountService") 不僅僅指定了 IOC 容器中 bean 的名字,還充當(dāng)了路徑映射的功能,如果本地服務(wù)器暴露在 8080 端口,則示例服務(wù)的訪問路徑為http://localhost:8080/AccountService

創(chuàng)建服務(wù)消費(fèi)者

  1. @Configuration 
  2. public class HttpProxyConfig { 
  3.  @Bean("accountServiceProxy"
  4.  public HttpInvokerProxyFactoryBean accountServiceProxy(){ 
  5.  HttpInvokerProxyFactoryBean accountService = new HttpInvokerProxyFactoryBean(); 
  6.  accountService.setServiceInterface(AccountService.class); 
  7.  accountService.setServiceUrl("http://localhost:8080/AccountService"); 
  8.  return accountService; 
  9.  } 
  10. @SpringBootApplication 
  11. public class HttpClientApp { 
  12.  public static void main(String[] args) { 
  13.  ConfigurableApplicationContext applicationContext = SpringApplication.run(HttpClientApp.class, args); 
  14.  AccountService accountService = applicationContext.getBean(AccountService.class); 
  15.  System.out.println(accountService.findById(10086)); 
  16.  } 

消費(fèi)者端引用服務(wù)同樣有兩個(gè)注意點(diǎn):

  1. org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean 是 Spring 封裝的一個(gè)服務(wù)引用器,serviceInterface 指定了生成代理的接口,serviceUrl 指定了服務(wù)所在的地址,與之前配置的服務(wù)暴露者的路徑需要對(duì)應(yīng)。
  2. HttpInvokerProxyFactoryBean 注冊(cè)到容器之中時(shí),會(huì)同時(shí)生成一個(gè) AccountService 接口的代理類,由 Spring 封裝遠(yuǎn)程調(diào)用的邏輯。

調(diào)用細(xì)節(jié)分析

對(duì)于 Spring HttpInvoker 的底層實(shí)現(xiàn),就沒必要深究了,但大家肯定還是會(huì)好奇一些細(xì)節(jié):dubbo 中的 http 報(bào)文體是怎么組織的?如何序列化對(duì)象的?

我們使用 Wireshark 可以抓取到客戶端發(fā)送的請(qǐng)求以及服務(wù)端響應(yīng)的報(bào)文。

 

一文詳細(xì)解讀 Dubbo 中的 http 協(xié)議

 

追蹤報(bào)文流,可以看到詳細(xì)的請(qǐng)求和響應(yīng)內(nèi)容

 

一文詳細(xì)解讀 Dubbo 中的 http 協(xié)議

 

從 ContentType:application/x-java-serialized-object 和報(bào)文 Body 部分的 ASCII 碼可以看出,使用的是 Java Serialize 序列化。我們將 Body 部分導(dǎo)出成文件,使用 Java Serialize 反序列化響應(yīng),來驗(yàn)證一下它的廬山真面目:

 

一文詳細(xì)解讀 Dubbo 中的 http 協(xié)議

 

使用 Java Serialize 可以正常反序列化報(bào)文,得到結(jié)果是 Spring 內(nèi)置的包裝類 RemoteInvocationResult,里面裝飾著實(shí)際的業(yè)務(wù)返回結(jié)果。

http 協(xié)議的意義

Dubbo 提供的眾多協(xié)議有各自適用的場(chǎng)景,例如

  • dubbo://,dubbo 協(xié)議是默認(rèn)的協(xié)議,自定義二進(jìn)制協(xié)議;單個(gè)長(zhǎng)連接節(jié)省資源;基于 tcp,架構(gòu)于 netty 之上,性能還算可以;協(xié)議設(shè)計(jì)上沒有足夠的前瞻性,不適合做 service-mesh 談不上多么優(yōu)雅,但是好歹風(fēng)風(fēng)雨雨用了這么多年,周邊也有不少配套組件例如 dubbo2.js, dubbo-go, dubbo-cpp,一定程度解決了多語(yǔ)言的問題。
  • webservice://,hession://,thrift:// 等協(xié)議,基本是為了適配已有協(xié)議的服務(wù)端/客戶端,借助于 dubbo 框架的 api,可以使用其功能特性,意義不是特別大。
  • redis://,memcached:// 等協(xié)議,并非是暴露給用戶配置的協(xié)議,一般是 dubbo 自用,在注冊(cè)中心模塊中會(huì)使用到相應(yīng)的擴(kuò)展

所有協(xié)議的具體使用場(chǎng)景和其特性,我可能會(huì)單獨(dú)寫文章來分析,而如今我們要思考的是 Dubbo 提供 http 協(xié)議到底解決什么問題,什么場(chǎng)景下用戶會(huì)考慮使用 Dubbo 的 http 協(xié)議。

我個(gè)人認(rèn)為 Dubbo 現(xiàn)如今的 http 協(xié)議比較雞肋,原生 http 通信的優(yōu)勢(shì)在于其通用性,基本所有語(yǔ)言都有配套的 http 客戶端和服務(wù)端支持,但是 Dubbo 的 http 協(xié)議卻使用了 application/x-java-serialized-object 的格式來做為默認(rèn)的 payload,使得其喪失了跨語(yǔ)言的優(yōu)勢(shì)??赡苡凶x者會(huì)反駁:HttpInvoker 支持配置序列化格式,不能這么草率的詬病它。但其實(shí)我們所關(guān)注的恰恰是默認(rèn)實(shí)現(xiàn),正如 dubbo:// 協(xié)議也可以配置 fastjson 作為序列化方案,但是我們同樣不認(rèn)為 dubbo:// 協(xié)議是一個(gè)優(yōu)秀的跨語(yǔ)言方案,理由是一樣的。當(dāng)然,評(píng)價(jià)一個(gè)應(yīng)用層協(xié)議是否是優(yōu)秀的,是否適合做 mesh 等等,需要多種方向去分析,這些我不在本文去分析。

說到底,本文花了一定的篇幅向大家介紹了 Dubbo 的 http 協(xié)議,到頭來卻是想告訴你:這是一個(gè)比較雞肋的協(xié)議,是不是有些失望呢?不要失望,dubbo 可能在 2.7.4 版本廢棄現(xiàn)有的 http 協(xié)議,轉(zhuǎn)而使用 jsonrpc 協(xié)議替代,其實(shí)也就是將 jsonrpc 協(xié)議換了個(gè)名字而已,而關(guān)于 jsonrpc 的細(xì)節(jié),我將會(huì)在下一篇文章中介紹,屆時(shí),我也會(huì)分析,為什么 jsonrpc 比現(xiàn)有的 http 協(xié)議更適合戴上 http 協(xié)議的帽子,至于現(xiàn)有的 http 協(xié)議,我更傾向于稱之為:spring-httpinvoker 協(xié)議。

 

總結(jié)

dubbo 現(xiàn)有 http 協(xié)議的意義是什么?如果你習(xí)慣于使用 Spring HttpInvoker,那或許現(xiàn)有的 http 協(xié)議還有一定的用處,但從 Dubbo 交流群和 Spring 文檔介紹其所花費(fèi)的篇幅來看,它還是非常小眾的。同時(shí)也可以讓我們更好地認(rèn)識(shí)協(xié)議發(fā)展的歷史,知道一個(gè)協(xié)議為什么存在,為什么會(huì)被淘汰。

當(dāng)然,我說了不算,最終還是要看 Dubbo 社區(qū)的決策,如果你對(duì)這個(gè)遷移方案感興趣,想要參與討論,歡迎大家在 Dubbo 社區(qū)的郵件列表中發(fā)表你的見解

責(zé)任編輯:武曉燕 來源: 今日頭條
相關(guān)推薦

2019-10-11 08:51:11

Http協(xié)議Dubbo

2022-06-20 09:09:26

IDaaSIAM身份即服務(wù)

2021-05-07 09:17:21

HTTPTCP協(xié)議

2022-05-11 11:54:55

Http傳送協(xié)議

2021-09-02 10:24:54

JavaScript前端語(yǔ)言

2019-05-14 10:50:11

HTTP協(xié)議HttpServlet

2021-09-09 10:26:26

Javascript 文檔對(duì)象前端

2024-12-23 14:46:24

2022-02-25 07:34:36

MQTT協(xié)議RabbitMQ

2020-03-08 21:22:03

HTTP112

2025-01-10 08:42:27

分布式服務(wù)發(fā)布Dubbo

2017-05-04 20:29:12

HTTP服務(wù)器TCP

2021-10-11 10:19:48

Javascript 高階函數(shù)前端

2022-02-24 07:34:10

SSL協(xié)議加密

2023-08-26 20:56:02

滑動(dòng)窗口協(xié)議

2022-05-16 10:49:28

網(wǎng)絡(luò)協(xié)議數(shù)據(jù)

2021-04-27 05:53:50

6G 衛(wèi)星通信6G 通信產(chǎn)業(yè)

2020-02-02 15:14:24

HTTP黑科技前端

2023-01-09 08:14:08

GoHttpServer

2022-08-05 08:22:10

eBPFHTTP項(xiàng)目
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)