太陽紅彤彤,花兒五顏六色,各位讀者朋友好,又來到了分享 Dubbo 知識點的時候了。說到 Dubbo 框架支持的協(xié)議,你的第一反應是什么?大概會有 Dubbo 默認支持的 dubbo 協(xié)議,以及老生常談的由當當貢獻給 Dubbo 的 rest 協(xié)議,或者是今天的主角 http。截止到目前,Dubbo 最新版本演進到了 2.7.3,已經(jīng)支持了:dubbo,hessain,http,injvm,jsonrpc,memcached,native-thrift,thrift,redis,rest,rmi,webservice,xml 等協(xié)議,有些協(xié)議的使用方式還沒有補全到官方文檔中。原來 Dubbo 支持這么多協(xié)議,是不是有點出乎你的意料呢?
創(chuàng)新互聯(lián)建站自2013年創(chuàng)立以來,先為昌邑等服務建站,昌邑等地企業(yè),進行企業(yè)商務咨詢服務。為昌邑企業(yè)網(wǎng)站制作PC+手機+微官網(wǎng)三網(wǎng)同步一站式服務解決您的所有建站問題。這么多 RPC 協(xié)議,可能有人會產(chǎn)生如下的疑問:rest,jsonrpc,webservice 不都是依靠 http 通信嗎?為什么還單獨有一個 http 協(xié)議?先不急著回答這個問題,而是引出今天的話題,先來介紹下 Dubbo 框架中所謂的 http 協(xié)議。
<!-- more -->
在 Dubbo 使用 http 協(xié)議和其他協(xié)議基本一樣,只需要指定 protocol 即可。
<dubbo:protocol name="http" port="8080" server="jetty" />
server 屬性可選值:jetty,tomcat,servlet。
配置過后,當服務消費者向服務提供者發(fā)起調(diào)用,底層便會使用標準的 http 協(xié)議進行通信??梢灾苯釉?https://github.com/apache/dubbo-samples 中找到官方示例,其中的子模塊:dubbo-samples-http 構(gòu)建了一個 http 協(xié)議調(diào)用的例子。
為避免大家誤解,特在此聲明:本文中,所有的 http 協(xié)議特指的是 dubbo 中的 http 協(xié)議,并非那個大家耳熟能詳?shù)耐ㄓ玫?http 協(xié)議。
從默認的 dubbo 協(xié)議改為 http 協(xié)議是非常簡單的一件事,上面便是使用者視角所看到的全部的內(nèi)容了,接下來我們將會探討其底層實現(xiàn)原理。
翻看 Dubbo 的源碼,找到 HttpProtocol 的實現(xiàn),你可能會吃驚,基本就依靠 HttpProtocol 一個類,就實現(xiàn)了 http 協(xié)議
要知道實現(xiàn)自定義的 dubbo 協(xié)議,有近 30 個類!http 協(xié)議實現(xiàn)的如此簡單,背后主要原因有兩點:
Spring 提供的 HttpInvoker 是何方神圣呢?的確是一個比較生僻的概念,但并不復雜,簡單來說,就是使用 Java 序列化將對象轉(zhuǎn)換成字節(jié),通過 http 發(fā)送出去,在 server 端,Spring 能根據(jù) url 映射,找到容器中對應的 Bean 反射調(diào)用的過程,沒見識過它也不要緊,可以通過下面的示例快速掌握這一概念。
本節(jié)內(nèi)容可參見 Spring 文檔:https://docs.spring.io/spring/docs/4.3.24.RELEASE/spring-framework-reference/htmlsingle/#remoting-httpinvoker-server
下面的示例將會展示如何使用 Spring 原生的 HttpInvoker 實現(xiàn)遠程調(diào)用。
public class AccountServiceImpl implements AccountService {
@Override
public Account findById(int id) {
Account account = new Account(id, new Date().toString());
return account;
}
}
@Bean
AccountService accountService(){
return new AccountServiceImpl();
}
@Bean("/AccountService")
public HttpInvokerServiceExporter accountServiceExporter(AccountService accountService){
HttpInvokerServiceExporter exporter = new HttpInvokerServiceExporter();
exporter.setService(accountService);
exporter.setServiceInterface(AccountService.class);
return exporter;
}
暴露服務的代碼相當簡單,需要注意兩點:
org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter
是 Spring 封裝的一個服務暴露器,它會以 serviceInterface 為公共接口,以 service 為實現(xiàn)類向外提供服務。http://localhost:8080/AccountService
@Configuration
public class HttpProxyConfig {
@Bean("accountServiceProxy")
public HttpInvokerProxyFactoryBean accountServiceProxy(){
HttpInvokerProxyFactoryBean accountService = new HttpInvokerProxyFactoryBean();
accountService.setServiceInterface(AccountService.class);
accountService.setServiceUrl("http://localhost:8080/AccountService");
return accountService;
}
}
@SpringBootApplication
public class HttpClientApp {
public static void main(String[] args) {
ConfigurableApplicationContext applicationContext = SpringApplication.run(HttpClientApp.class, args);
AccountService accountService = applicationContext.getBean(AccountService.class);
System.out.println(accountService.findById(10086));
}
}
消費者端引用服務同樣有兩個注意點:
org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean
是 Spring 封裝的一個服務引用器,serviceInterface 指定了生成代理的接口,serviceUrl 指定了服務所在的地址,與之前配置的服務暴露者的路徑需要對應。對于 Spring HttpInvoker 的底層實現(xiàn),就沒必要深究了,但大家肯定還是會好奇一些細節(jié):dubbo 中的 http 報文體是怎么組織的?如何序列化對象的?
我們使用 wireshark 可以抓取到客戶端發(fā)送的請求以及服務端響應的報文。
追蹤報文流,可以看到詳細的請求和響應內(nèi)容
從ContentType: application/x-java-serialized-object
和報文 Body 部分的 ASCII 碼可以看出,使用的是 Java Serialize 序列化。我們將 Body 部分導出成文件,使用 Java Serialize 反序列化響應,來驗證一下它的廬山真面目:
使用 Java Serialize 可以正常反序列化報文,得到結(jié)果是 Spring 內(nèi)置的包裝類 RemoteInvocationResult,里面裝飾著實際的業(yè)務返回結(jié)果。
Dubbo 提供的眾多協(xié)議有各自適用的場景,例如
所有協(xié)議的具體使用場景和其特性,我可能會單獨寫文章來分析,而如今我們要思考的是 dubbo 提供 http 協(xié)議到底解決什么問題,什么場景下用戶會考慮使用 dubbo 的 http 協(xié)議。
我個人認為 dubbo 現(xiàn)如今的 http 協(xié)議比較雞肋,原生 http 通信的優(yōu)勢在于其通用性,基本所有語言都有配套的 http 客戶端和服務端支持,但是 dubbo 的 http 協(xié)議卻使用了application/x-java-serialized-object
的格式來做為默認的 payload,使得其喪失了跨語言的優(yōu)勢??赡苡凶x者會反駁:HttpInvoker 支持配置序列化格式,不能這么草率的詬病它。但其實我們所關注的恰恰是默認實現(xiàn),正如 dubbo:// 協(xié)議也可以配置 fastjson 作為序列化方案,但是我們同樣不認為 dubbo:// 協(xié)議是一個優(yōu)秀的跨語言方案,理由是一樣的。當然,評價一個應用層協(xié)議是否是優(yōu)秀的,是否適合做 mesh 等等,需要多種方向去分析,這些我不在本文去分析。
說到底,本文花了一定的篇幅向大家介紹了 dubbo 的 http 協(xié)議,到頭來卻是想告訴你:這是一個比較雞肋的協(xié)議,是不是有些失望呢?不要失望,dubbo 可能在 2.7.4 版本廢棄現(xiàn)有的 http 協(xié)議,轉(zhuǎn)而使用 jsonrpc 協(xié)議替代,其實也就是將 jsonrpc 協(xié)議換了個名字而已,而關于 jsonrpc 的細節(jié),我將會在下一篇文章中介紹,屆時,我也會分析,為什么 jsonrpc 比現(xiàn)有的 http 協(xié)議更適合戴上 http 協(xié)議的帽子,至于現(xiàn)有的 http 協(xié)議,我更傾向于稱之為:spring-httpinvoker 協(xié)議。
總結(jié),dubbo 現(xiàn)有 http 協(xié)議的意義是什么?如果你習慣于使用 Spring HttpInvoker,那或許現(xiàn)有的 http 協(xié)議還有一定的用處,但從 dubbo 交流群和 Spring 文檔介紹其所花費的篇幅來看,它還是非常小眾的。同時也可以讓我們更好地認識協(xié)議發(fā)展的歷史,知道一個協(xié)議為什么存在,為什么會被淘汰。
當然,我說了不算,最終還是要看 dubbo 社區(qū)的決策,如果你對這個遷移方案感興趣,想要參與討論,歡迎大家在 dubbo 社區(qū)的郵件列表中發(fā)表你的見解
Topic:[Proposal] replace the protocol="http" with protocol="jsonrpc"
歡迎關注我的微信公眾號:「Kirito的技術(shù)分享」,關于文章的任何疑問都會得到回復,帶來更多 Java 相關的技術(shù)分享。
創(chuàng)新互聯(lián)www.cdcxhl.cn,專業(yè)提供香港、美國云服務器,動態(tài)BGP最優(yōu)骨干路由自動選擇,持續(xù)穩(wěn)定高效的網(wǎng)絡助力業(yè)務部署。公司持有工信部辦法的idc、isp許可證, 機房獨有T級流量清洗系統(tǒng)配攻擊溯源,準確進行流量調(diào)度,確保服務器高可用性。佳節(jié)活動現(xiàn)已開啟,新人活動云服務器買多久送多久。
網(wǎng)站欄目:一文詳解Dubbo中的http協(xié)議-創(chuàng)新互聯(lián)
標題路徑:http://chinadenli.net/article28/cdghjp.html
成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站建設、品牌網(wǎng)站制作、微信小程序、網(wǎng)站排名、靜態(tài)網(wǎng)站、商城網(wǎng)站
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)