新网创想网站建设,新征程启航
为企业提供网站建设、域名注册、服务器等服务
太阳红彤彤,花儿五颜六色,各位读者朋友好,又来到了分享 Dubbo 知识点的时候了。说到 Dubbo 框架支持的协议,你的第一反应是什么?大概会有 Dubbo 默认支持的 dubbo 协议,以及老生常谈的由当当贡献给 Dubbo 的 rest 协议,或者是今天的主角 http。截止到目前,Dubbo 最新版本演进到了 2.7.3,已经支持了:dubbo,hessain,http,injvm,jsonrpc,memcached,native-thrift,thrift,redis,rest,rmi,webservice,xml 等协议,有些协议的使用方式还没有补全到官方文档中。原来 Dubbo 支持这么多协议,是不是有点出乎你的意料呢?
创新互联建站自2013年创立以来,先为昌邑等服务建站,昌邑等地企业,进行企业商务咨询服务。为昌邑企业网站制作PC+手机+微官网三网同步一站式服务解决您的所有建站问题。这么多 RPC 协议,可能有人会产生如下的疑问:rest,jsonrpc,webservice 不都是依靠 http 通信吗?为什么还单独有一个 http 协议?先不急着回答这个问题,而是引出今天的话题,先来介绍下 Dubbo 框架中所谓的 http 协议。
在 Dubbo 使用 http 协议和其他协议基本一样,只需要指定 protocol 即可。
server 属性可选值:jetty,tomcat,servlet。
配置过后,当服务消费者向服务提供者发起调用,底层便会使用标准的 http 协议进行通信。可以直接在 https://github.com/apache/dubbo-samples 中找到官方示例,其中的子模块:dubbo-samples-http 构建了一个 http 协议调用的例子。
为避免大家误解,特在此声明:本文中,所有的 http 协议特指的是 dubbo 中的 http 协议,并非那个大家耳熟能详的通用的 http 协议。
从默认的 dubbo 协议改为 http 协议是非常简单的一件事,上面便是使用者视角所看到的全部的内容了,接下来我们将会探讨其底层实现原理。
翻看 Dubbo 的源码,找到 HttpProtocol 的实现,你可能会吃惊,基本就依靠 HttpProtocol 一个类,就实现了 http 协议
要知道实现自定义的 dubbo 协议,有近 30 个类!http 协议实现的如此简单,背后主要原因有两点:
Spring 提供的 HttpInvoker 是何方神圣呢?的确是一个比较生僻的概念,但并不复杂,简单来说,就是使用 Java 序列化将对象转换成字节,通过 http 发送出去,在 server 端,Spring 能根据 url 映射,找到容器中对应的 Bean 反射调用的过程,没见识过它也不要紧,可以通过下面的示例快速掌握这一概念。
本节内容可参见 Spring 文档:https://docs.spring.io/spring/docs/4.3.24.RELEASE/spring-framework-reference/htmlsingle/#remoting-httpinvoker-server
下面的示例将会展示如何使用 Spring 原生的 HttpInvoker 实现远程调用。
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 为实现类向外提供服务。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 的底层实现,就没必要深究了,但大家肯定还是会好奇一些细节:dubbo 中的 http 报文体是怎么组织的?如何序列化对象的?
我们使用 wireshark 可以抓取到客户端发送的请求以及服务端响应的报文。
追踪报文流,可以看到详细的请求和响应内容
从ContentType: application/x-java-serialized-object
和报文 Body 部分的 ASCII 码可以看出,使用的是 Java Serialize 序列化。我们将 Body 部分导出成文件,使用 Java Serialize 反序列化响应,来验证一下它的庐山真面目:
使用 Java Serialize 可以正常反序列化报文,得到结果是 Spring 内置的包装类 RemoteInvocationResult,里面装饰着实际的业务返回结果。
Dubbo 提供的众多协议有各自适用的场景,例如
所有协议的具体使用场景和其特性,我可能会单独写文章来分析,而如今我们要思考的是 dubbo 提供 http 协议到底解决什么问题,什么场景下用户会考虑使用 dubbo 的 http 协议。
我个人认为 dubbo 现如今的 http 协议比较鸡肋,原生 http 通信的优势在于其通用性,基本所有语言都有配套的 http 客户端和服务端支持,但是 dubbo 的 http 协议却使用了application/x-java-serialized-object
的格式来做为默认的 payload,使得其丧失了跨语言的优势。可能有读者会反驳:HttpInvoker 支持配置序列化格式,不能这么草率的诟病它。但其实我们所关注的恰恰是默认实现,正如 dubbo:// 协议也可以配置 fastjson 作为序列化方案,但是我们同样不认为 dubbo:// 协议是一个优秀的跨语言方案,理由是一样的。当然,评价一个应用层协议是否是优秀的,是否适合做 mesh 等等,需要多种方向去分析,这些我不在本文去分析。
说到底,本文花了一定的篇幅向大家介绍了 dubbo 的 http 协议,到头来却是想告诉你:这是一个比较鸡肋的协议,是不是有些失望呢?不要失望,dubbo 可能在 2.7.4 版本废弃现有的 http 协议,转而使用 jsonrpc 协议替代,其实也就是将 jsonrpc 协议换了个名字而已,而关于 jsonrpc 的细节,我将会在下一篇文章中介绍,届时,我也会分析,为什么 jsonrpc 比现有的 http 协议更适合戴上 http 协议的帽子,至于现有的 http 协议,我更倾向于称之为:spring-httpinvoker 协议。
总结,dubbo 现有 http 协议的意义是什么?如果你习惯于使用 Spring HttpInvoker,那或许现有的 http 协议还有一定的用处,但从 dubbo 交流群和 Spring 文档介绍其所花费的篇幅来看,它还是非常小众的。同时也可以让我们更好地认识协议发展的历史,知道一个协议为什么存在,为什么会被淘汰。
当然,我说了不算,最终还是要看 dubbo 社区的决策,如果你对这个迁移方案感兴趣,想要参与讨论,欢迎大家在 dubbo 社区的邮件列表中发表你的见解
Topic:[Proposal] replace the protocol="http" with protocol="jsonrpc"
欢迎关注我的微信公众号:「Kirito的技术分享」,关于文章的任何疑问都会得到回复,带来更多 Java 相关的技术分享。
创新互联www.cdcxhl.cn,专业提供香港、美国云服务器,动态BGP最优骨干路由自动选择,持续稳定高效的网络助力业务部署。公司持有工信部办法的idc、isp许可证, 机房独有T级流量清洗系统配攻击溯源,准确进行流量调度,确保服务器高可用性。佳节活动现已开启,新人活动云服务器买多久送多久。