https://blog.csdn.net/wangyunpeng0319/article/details/78651998
很长时间以来都没有怎么好好搞清楚RPC(即Remote Procedure Call,远程过程调用)和HTTP调用的区别,不都是写一个服务然后在客户端调用么?这里请允许我迷之一笑~Naive!本文简单地介绍一下两种形式的C/S架构,先说一下他们最本质的区别,就是RPC主要是基于TCP/IP协议的,而HTTP服务主要是基于HTTP协议的,我们都知道HTTP协议是在传输层协议TCP之上的,所以效率来看的话,RPC当然是要更胜一筹啦!下面来具体说一说RPC服务和HTTP服务。
在说RPC和HTTP的区别之前,我觉的有必要了解一下OSI的七层网络结构模型(虽然实际应用中基本上都是五层),它可以分为以下几层: (从上到下)
实际应用过程中,五层协议结构里面是没有表示层和会话层的。应该说它们和应用层合并了。我们应该将重点放在应用层和传输层这两个层面。因为HTTP是应用层协议,而TCP是传输层协议。好,知道了网络的分层模型以后我们可以更好地理解为什么RPC服务相比HTTP服务要Nice一些!
从三个角度来介绍RPC服务:分别是RPC架构,同步异步调用以及流行的RPC框架。
先说说RPC服务的基本架构吧。允许我可耻地盗一幅图哈~我们可以很清楚地看到,一个完整的RPC架构里面包含了四个核心的组件,分别是Client ,Server,Client Stub以及Server Stub,这个Stub大家可以理解为存根。分别说说这几个组件:
RPC主要是用在大型企业里面,因为大型企业里面系统繁多,业务线复杂,而且效率优势非常重要的一块,这个时候RPC的优势就比较明显了。实际的开发当中是这么做的,项目一般使用maven来管理。比如我们有一个处理订单的系统服务,先声明它的所有的接口(这里就是具体指Java中的interface
),然后将整个项目打包为一个jar
包,服务端这边引入这个二方库,然后实现相应的功能,客户端这边也只需要引入这个二方库即可调用了。为什么这么做?主要是为了减少客户端这边的jar
包大小,因为每一次打包发布的时候,jar
包太多总是会影响效率。另外也是将客户端和服务端解耦,提高代码的可移植性。
什么是同步调用?什么是异步调用?同步调用
就是客户端等待调用执行完成并返回结果。异步调用
就是客户端不等待调用执行完成返回结果,不过依然可以通过回调函数等接收到返回结果的通知。如果客户端并不关心结果,则可以变成一个单向的调用。这个过程有点类似于Java中的callable
和runnable
接口,我们进行异步执行的时候,如果需要知道执行的结果,就可以使用callable
接口,并且可以通过Future
类获取到异步执行的结果信息。如果不关心执行的结果,直接使用runnable
接口就可以了,因为它不返回结果,当然啦,callable
也是可以的,我们不去获取Future
就可以了。
目前流行的开源RPC框架还是比较多的。下面重点介绍三种:
偷偷告诉你
集团内部已经不怎么使用dubbo啦,现在用的比较多的叫HSF,又名“好舒服”。后面有可能会开源,大家拭目以待。
其实在很久以前,我对于企业开发的模式一直定性为HTTP接口开发,也就是我们常说的RESTful风格的服务接口。的确,对于在接口不多、系统与系统交互较少的情况下,解决信息孤岛初期常使用的一种通信手段;优点就是简单、直接、开发方便。利用现成的http协议进行传输。我们记得之前本科实习在公司做后台开发的时候,主要就是进行接口的开发,还要写一大份接口文档,严格地标明输入输出是什么?说清楚每一个接口的请求方法,以及请求参数需要注意的事项等。比如下面这个例子:POST http://www.httpexample.com/restful/buyer/info/share
接口可能返回一个JSON字符串或者是XML文档。然后客户端再去处理这个返回的信息,从而可以比较快速地进行开发。但是对于大型企业来说,内部子系统较多、接口非常多的情况下,RPC框架的好处就显示出来了,首先就是长链接,不必每次通信都要像http一样去3次握手什么的,减少了网络开销;其次就是RPC框架一般都有注册中心,有丰富的监控管理;发布、下线接口、动态扩展等,对调用方来说是无感知、统一化的操作。
RPC服务和HTTP服务还是存在很多的不同点的,一般来说,RPC服务主要是针对大型企业的,而HTTP服务主要是针对小企业的,因为RPC效率更高,而HTTP服务开发迭代会更快。总之,选用什么样的框架不是按照市场上流行什么而决定的,而是要对整个项目进行完整地评估,从而在仔细比较两种开发框架对于整个项目的影响,最后再决定什么才是最适合这个项目的。一定不要为了使用RPC而每个项目都用RPC,而是要因地制宜,具体情况具体分析。
============================================
https://blog.csdn.net/douliw/article/details/52592188
看到知乎上有这样一个问题
WEB开发中,使用JSON-RPC好,还是RESTful API好?
还有其他优秀的推荐方案吗?
-----------------------------------------------------------------
先科普一下
REST 和 RESTful 什么区别?
REST,即Representational State Transfer的缩写。翻译过来是表现层状态转换。
如果一个架构符合REST原则,就称它为RESTful架构。
啥叫json-rpc?
接口调用通常包含两个部分,序列化和通信协议。常见的序列化协议包括json、xml、hession、protobuf、thrift、text、bytes等;通信比较流行的是http、soap、websockect,RPC通常基于TCP实现,常用框架例如netty。
RESTful通常采用http+JSON实现。
JSON-RPC是指通信协议采用二进制方式,而不是http,序列化采用JSON的形式。
被赞的最多的一个回答
翁伟 262 人赞同
JSON-RPC比RESTful API好很多。
======
我厌恶restful API如同我厌恶OOP;但与其说我厌恶restful,倒不如说我厌恶鼓吹restful API的一些伪·程序员。
很多鼓吹restful API的程序员,实际上并不理解restful的设计理念,纯粹是在人言亦言,随便看了几篇网文在说restful,自己便也更着鼓吹。
做为一个合格的技术人员,最基础的要求是要对自己所使用的技术有了解,明白各种技术的适用场景,然后因地制宜。
restful首先是要求必须把所有的应用定义成为“resource”,然后只能针对资源做有限的四种操作。
这是对API一个非常糟糕的抽象,有太多现实中需要的API,无法顺当的融入到restful所定义的规范中。
比方说,user login / resetpassword等等。
restful的信徒,他们会说可以根据这个那个规范,把login / password等也纳入为某种资源,然后进行增删改查。这在我看来,纯粹是在解决一些原本不存在,根本不需要解决的问题,纯浪费。
所有的接口,服务器端原本就存在有相应的函数,它们本来就有自身的命名空间,接受的参数、返回值、异常等等。
采用轻便的方式暴露出来即可。
无需把一堆函数重新归纳到“资源”,再削减脑袋把所有的操作都映射为“增删改查”。
对应到web上,rpc的成熟方案非常多,有古老的soap,也有轻量的json rpc。
JSON rpc基本上仅是要求所有的请求必须有msg id,有函数名,然后可定义参数,并且区分返回值与异常;也可定义『命名空间』来对函数模块做划分。
这与大多数语言的模块、函数定义相符,使用起来是非常便利的。
很多json rpc是供web前端ajax调用,若前端调用抽象得当,调用远程API,实际上与调用本地函数无甚区别。
实际上,json rpc也未必需要跟http绑定,即便是在web上,它也可以走web socket,这样子,前端可以使用同一web socket管道批量发送请求,而服务器端乱序返回结果时,前端也可以根据msg id做准确的回调。
websocket,批量调用,乱序返回,这些都可以显著提高API的输出吞吐,这些是在json rpc的设计考量内。
调用更方便,性能也更好,两全其美是完全可能的。
想当然的为了“快”,为了“简单”就必须牺牲别的,这是严重的思维误区。
有些方案,纯粹就是糟糕的方案。
restful API仅适用与业务非常简单的场景,比方说,就是为了提供少量数据表单的增删改查。而这种场景实在是太过简单,实际中几乎找不到。
----------------------------------------------------------
我的观点
实际上,这个问题本质上是RESTful和RPC之争。这两种风格都是随着架构发展而来。分别适用不同的场景。
http vs 高性能二进制协议
http相对更规范,更标准,更通用,无论哪种语言都支持http协议。如果你是对外开放API,例如开放平台,外部的编程语言多种多样,你无法拒绝对每种语言的支持,相应的,如果采用http,无疑在你实现SDK之前,支持了所有语言,所以,现在开源中间件,基本最先支持的几个协议都包含RESTful。
RPC协议性能要高的多,例如Protobuf、Thrift、Kyro等,(如果算上序列化)吞吐量大概能达到http的二倍。响应时间也更为出色。千万不要小看这点性能损耗,公认的,微服务做的比较好的,例如,netflix、阿里,曾经都传出过为了提升性能而合并服务。如果是交付型的项目,性能更为重要,因为你卖给客户往往靠的就是性能上微弱的优势。
RESTful的规范到底是不是鸡肋?
我认为,微服务的盛行,开放平台的盛行,的确让RESTful过于“流行”了。你可以看看,无论是Google、Amazon、netflix(据说很可能转向grpc),还是阿里,实际上内部都是采用性能更高的RPC方式。而对外开放的才是RESTful。
如果你的应用非常简单,无论用哪种都无所谓了,基本都能满足要求。
关于无状态、幂等
这个跟你是否采用RESTful无关,主要还是看接口内部实现,所以,把这个作为RESTful优点的可以闭嘴了。
安全性
显然,基于Http更安全一些,默认80端口,防火墙友好。
RESTful也分为严格的和自由的
RESTful还有个好处是制定了一系列规范,但是大多数使用者都是自由风格的,根本不是严格按照RESTful规范实现。当然存在就是道理,这样做更高效,但是不够通用。
无疑,严格按照资源抽象,API看起来更清晰,更容易被大家理解。同时,开发人员的复杂度也更高。
最后建议
对外开放给全世界的API推荐采用RESTful,是否严格按照规范是一个要权衡的问题。要综合成本、稳定性、易用性、业务场景等等多种因素。
内部调用推荐采用RPC方式。当然不能一概而论,还要看具体的业务场景。
另外一个因素是人,关键是你有什么人,postgresql、mysql都有用的不错的,迁来迁去,关键是你的人对哪个更熟悉。
感兴趣的可以去知乎看原文:http://www.zhihu.com/question/28570307
======================================
https://blog.csdn.net/zwx19921215/article/details/79804379
既然springcloud是一个微服务架构生态体系,而且上一章我们也介绍了 微服务体系中一个核心组件“服务的发现与注册”eureka,接下来我们来简单探索以下微服务体系中另一个核心组件“rpc”;在springcloud体系中实现rpc的组件有2个,一个是ribbon,另一个是feign,而且feign在底层封装了ribbon,以更友好,更灵活的形式展现在了我们眼前,所以今天我们研究的重心放在了feign身上。
(摘抄一段话,帮助大家更清晰的认识feign)
feign是netflix提供的服务间基于http的rpc调用框架,在spring cloud得到广泛应用。默认情况下,一个feign client是在hystrix断路器中执行,并利用ribbon进行软负载选择远程服务(service),所以可以想象出一个feign client的层次架构是包裹的层次,hystrix控制整个rpc从调用到方法返回,而ribbon控制从选址到socket返回;
那么什么是hystrix呢?
首先我们先置身于这样一个场景在微服务架构中,我们将业务拆分成一个个的服务,而服务与服务之间可以相互调用(RPC方式)。为了保证其高可用,单个服务又可能回事集群环境部署。所以可能存在由于网络原因或者自身的原因,并不能保证服务的100%可用,如果单个服务出现问题,调用这个服务就会出现网络延迟,此时若有大量的网络涌入,会形成任务累计,导致服务瘫痪,甚至导致服务“雪崩”。
为了解决这个问题,就出现断路器模型。
而hystrix就是Netflix的一个库并且实现了断路器模式。
(摘抄自一位网友的图)
较底层的服务如果出现故障,会导致连锁故障。当对特定的服务的调用达到一个阀值(hystric 是5秒20次) 断路器将会被打开。
断路打开后,可用避免连锁故障,fallback方法可以直接返回一个固定值。
好了,接下来我们来配置一下实际环境中我们应该怎样使用feign + hystrix?
注:基于test项目(我新建的另一个springboot项目)和demo-springboot项目;
1.打开test项目的pom.xml加入相关依赖:
org.springframework.cloud spring-cloud-starter-feign 1.3.4.RELEASE
2.打开application-dev.properties加入以下内容:
#feign read timeout(10s) hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=10000 #feign read timout disable(该配置,用于禁用Hystrix的超时时间 ) #hystrix.command.default.execution.timeout.enabled=false #关闭hystrix功能 #feign.hystrix.enabled=false
切记feign read timeout配置一个合适的超时时间,不要用默认的,我刚开始的时候没有配置,结构一直调用返回error,发现是超时了。
3.在demo-springboot中添加测试controller:
package com.example.demo.controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; /** * @author xiaofeng * @version V1.0 * @title: TestController.java * @package: com.example.demo.controller * @description: TODO * @date 2018/4/3 0003 下午 2:10 */ @RestController @RequestMapping(value = "/test") public class TestController { @RequestMapping(value = "/info") public String info(@RequestParam(value = "msg") String msg) { return "welcome to demo-springboot: " + msg; } }
4.在test项目中增加rpc相关服务类:
@FeignClient(value = "demo-springboot", fallback = RpcServiceImpl.class) public interface RpcService { /** * 查询test * * @param msg * @return */ @RequestMapping(value = "/test/info", method = RequestMethod.GET) String query(@RequestParam(value = "msg") String msg); }
@Service public class RpcServiceImpl implements RpcService { /** * 查询test * * @param msg * @return */ @Override public String query(String msg) { return "error"; } }
5.在test项目中编写测试controller:
@RestController public class TestController { @Autowired RpcService rpcService; @RequestMapping(value = "/test/index") public String index(@RequestParam(value = "msg") String msg) { return rpcService.query(msg); } }
然后再启动类中开启注解@EnableFeignClients(basePackages = {"com.xx.xx.test.service"}):表示feign 需要扫描的package路径(我的rpcService放在service包下)。
@EnableFeignClients(basePackages = {"com.xx.xx.test.service"}) @EnableAutoConfiguration @EnableEurekaClient @SpringBootApplication public class Xsignal2TestApplication { public static void main(String[] args) { SpringApplication.run(Xsignal2TestApplication.class, args); } }
6.最后分别启动discover-server、demo-springboot、test三个服务
查看eureka控制面板三个服务是否都已经启动:
ok,接下来开始测试,首先是正常测试,打开浏览器:
出现的是我们理想的结果,说明我们的rpc已经走通了哦,是不是有点小鸡冻啊。
7.介绍一些常用配置
以上这种配置也是全局配置,如果我们想针对某一个接口配置,比如/hello接口,那么可以按照下面这种写法,如下:
# 设置熔断超时时间
hystrix.command.hello.execution.isolation.thread.timeoutInMilliseconds=10000
# 关闭熔断功能
hystrix.command.hello.execution.timeout.enabled=false
# 配置请求GZIP压缩
feign.compression.request.enabled=true
# 配置响应GZIP压缩
feign.compression.response.enabled=true
# 配置压缩支持的MIME TYPE
feign.compression.request.mime-types=text/xml,application/xml,application/json
# 配置压缩数据大小的下限
feign.compression.request.min-request-size=2048
注意点:
1.有些公共的组件抽出来其他模块的maven依赖,此时要在使用的项目中加载此jar包的spring component以及feign组件,仅仅依靠@ComponentScan是不够的,还需要在@EnableFeignClients(basePackages = {"com.xx.xx.test.service"})中标注basekPackages。
2.springcloud feign 注入bean null问题
解决办法:
1. 如果swagger版本是v1.x,那么请参考:https://segmentfault.com/a/1190000006595187
2. 如果swagger版本是v2.x,那么请将升级swagger版本到2.5.0以上即可。
io.springfox springfox-swagger2 2.5.0 io.springfox springfox-swagger-ui 2.5.0
3.feign rpc返回的json对象转换失败
1.复杂对象转换失败(Response
2.接口返回对象转换:
ResponseModel
new TypeReference