使用RPC与Restful接口调用服务

  created  by  鱼鱼 {{tag}}
创建于 2019年05月07日 15:49:56 最后修改于 2021年01月13日 10:10:46

        在SOA和微服务架构中,远程通信是无法避免的,最常用的远程通信有两种方式:

  1. restful的接口,使用Http通信

  2. 使用dubbo或是Spring Cloud组件进行 RPC协议远程调用,可选地使用socket通信

RPC准没错?

    不同的人对 RPC调用会有不同的看法,甚至对rpc本身的理解都不甚相同,但我认为 RPC有两种倾向:

  • 一为语义化的 RPC。没有统一的请求规范,数据格式在开发人员中很难达成一致,在使用传统Http调用时,交互的双方需要约定一份“API文档”以保证数据格式的唯一性,这样API格式本身就成为了一道大墙,耽误研发双方的时间。但如果服务间采用语义化 RPC进行交互,双方可能并不需要一份文档,只要一份约定好的代码,并以此作为双方的依赖,在请求时也仅仅是直接调用方法本身,如此强的语义性怎能让人不爱。语义化 RPC的背后其实仍旧是被封装的Http请求调用,但接口本身的定义已经不重要,约定都体现在了封装方法定义上。

  • 二为真正的 RPC,Http请求要经过七层协议,有一套复杂的序列化和握手过程,其数据包封装本身其实已经有大量的损耗了,通过自定义协议,可以约定不同的序列化方式,从而达到真正的 RPC,可能只需走四层协议,由于数据包更小,服务间通过此种方式通信可能会有更高的性能和吞吐量。

    语义化 RPC的代表就是Feign,本质上与Http请求调用无异,而后者的代表是Dubbo,通过选择不同的协议绕开了控制层。其余还有为了追求极致性能自己编写protobuf等rpc。

    为了解决请求的约定不一致问题,除去 RPC框架,还有人使用Restful接口标准来限定接口标准,语义化 RPC与Restful接口规范二者没有好坏之说,也可以共同使用。当然使用 RPC框架能提高后台服务间调用的编码效率是毋庸置疑的,如果我们只考虑使用语义化的 RPC调用,尽可以直接替换。至于本质的 RPC,譬如Dubbo,需要进行预先的调研,服务端模块化和一个私有的依赖服务器应当是必备的,并且相比语义化的 RPC可能需要更多的工作量,发布方也需要做相应的注册,同时,如果我们使用自定义的协议,序列化与反序列化会消耗多余的cpu,如果既有服务不存在架构解决不掉的吞吐量上的瓶颈问题或不是性能敏感的服务,不建议做真· RPC改造

语义化 RPC-OpenFeign

    语义化 RPC本质上是在客户端做了一层方法封装,语义上看是调用了本地的方法,实际与通过HttpClient等类直接调用相应的接口无异,能天然的结合Ribbon服务发现也是一个优势。

在SpringBoot中集成OpenFeign

    暂且忽略客户端负载均衡层面,假定服server端已经注册上去了。我们只要在启动类添加注解:

@EnableFeignClients
@EnableDiscoveryClient

    然后便可以封装接口的调用,path即为项目的接口根目录(context-path),value为server注册的服务名,接口部分只需要与server服务中代码保持一致即可:

@FeignClient(value = "server1",path = "/")
public interface TestCustFeignClient { 
    @RequestMapping("/demo")
    @ResponseBody 
    public String demo(@RequestParam String param); 
}

    这样直接调用demo方法,便可进行远程调用,封装了调用的细节。

本质的 RPC-Dubbo(版本略有过时)

    Dubbo是阿里巴巴提供的服务化治理框架,它省略了API方式调用的API侵入,并且通过一个注册中心实现服务的注册与发现,流程架构图为:

    dubbo需与Spring共同使用,当provider在注册中心注册了一个服务(Sevice)后,consumer中可以申请获取这个Service,它将作为一个bean存在于项目中。

    Dubbo的基本配置

<!-- 使用dubbo发布服务 -->
	<!-- 提供方应用信息,用于计算依赖关系,无关provider还是consumer -->
	<dubbo:application name="provider" />
	<!-- 注册dubbo的服务
	,注册中心可以有多个 -->
	<dubbo:registry protocol="zookeeper"
		address="192.168.25.137:2181" />
	<!-- 各配置项缺省值设置 -->
	<dubbo:provider retries="0" timeout="20000" />
	<!-- 表明用dubbo协议在20880端口暴露服务 -->
	<dubbo:protocol name="dubbo" port="20880" />
	<!-- 声明需要暴露的服务接口,作为provider -->
	<dubbo:service interface="cn.XXXX.service.ItemService" ref="itemServiceImpl" timeout="600000" />
        <!-- 引用服务配置,用于创建一个远程服务代理,一个引用可以指向多个注册中心。-->
        <dubbo:reference id="demoService" interface="com.unj.dubbotest.provider.DemoService" />

    接下来详细说一下这些配置项的参数,注意有一些共通的参数:

        -Dubbo:service

  • interface:服务接口名,必填项,指向具体的class

  • ref:服务的实现引用(实现类),必填项,类名并且首字母小写

  • group:服务分组

  • version:服务版本

  • registry:指定注册中心,使用","分割多个注册中心的id,"N/A"表示空,默认向所有中心注册

  • timeout:设定超时时间(ms),默认1000

  • retries:重试次数(不重试为0,默认为2)

  • protocol:引用的协议,对应protocol的id

        -Dubbo:reference

  • id:服务的bean id,必填项,作为bean的id

  • interface:服务的接口名,必填项,是服务提供方的接口的首字母小写类名

  • registry、group、version、timeout、retries

  • check:检查是否存在服务,为true会报错,反之忽略

        -Dubbo:protocol

  • name:协议名称,必填项

  • port:端口,默认20880

  • id:协议的id,默认dubbo

        -Dubbo:registry

  • address:注册中心地址,含端口,必填项,默认端口9090

  • port:服务端口,根据协议不同有不同的默认端口

  • protocol:注册中心地址协议,默认dubbo,还有html、local协议


        -Dubbo:application

  • name:当前应用的名称,必填项

        -Dubbo:provider

  • id:可在service的provider中引用id值


参考链接:dubbo的配置及java代码使用Dubbo之XML配置详解

评论区
评论
{{comment.creator}}
{{comment.createTime}} {{comment.index}}楼
评论

使用RPC与Restful接口调用服务

使用RPC与Restful接口调用服务

        在SOA和微服务架构中,远程通信是无法避免的,最常用的远程通信有两种方式:

  1. restful的接口,使用Http通信

  2. 使用dubbo或是Spring Cloud组件进行 RPC协议远程调用,可选地使用socket通信

RPC准没错?

    不同的人对 RPC调用会有不同的看法,甚至对rpc本身的理解都不甚相同,但我认为 RPC有两种倾向:

    语义化 RPC的代表就是Feign,本质上与Http请求调用无异,而后者的代表是Dubbo,通过选择不同的协议绕开了控制层。其余还有为了追求极致性能自己编写protobuf等rpc。

    为了解决请求的约定不一致问题,除去 RPC框架,还有人使用Restful接口标准来限定接口标准,语义化 RPC与Restful接口规范二者没有好坏之说,也可以共同使用。当然使用 RPC框架能提高后台服务间调用的编码效率是毋庸置疑的,如果我们只考虑使用语义化的 RPC调用,尽可以直接替换。至于本质的 RPC,譬如Dubbo,需要进行预先的调研,服务端模块化和一个私有的依赖服务器应当是必备的,并且相比语义化的 RPC可能需要更多的工作量,发布方也需要做相应的注册,同时,如果我们使用自定义的协议,序列化与反序列化会消耗多余的cpu,如果既有服务不存在架构解决不掉的吞吐量上的瓶颈问题或不是性能敏感的服务,不建议做真· RPC改造

语义化 RPC-OpenFeign

    语义化 RPC本质上是在客户端做了一层方法封装,语义上看是调用了本地的方法,实际与通过HttpClient等类直接调用相应的接口无异,能天然的结合Ribbon服务发现也是一个优势。

在SpringBoot中集成OpenFeign

    暂且忽略客户端负载均衡层面,假定服server端已经注册上去了。我们只要在启动类添加注解:

@EnableFeignClients
@EnableDiscoveryClient

    然后便可以封装接口的调用,path即为项目的接口根目录(context-path),value为server注册的服务名,接口部分只需要与server服务中代码保持一致即可:

@FeignClient(value = "server1",path = "/")
public interface TestCustFeignClient { 
    @RequestMapping("/demo")
    @ResponseBody 
    public String demo(@RequestParam String param); 
}

    这样直接调用demo方法,便可进行远程调用,封装了调用的细节。

本质的 RPC-Dubbo(版本略有过时)

    Dubbo是阿里巴巴提供的服务化治理框架,它省略了API方式调用的API侵入,并且通过一个注册中心实现服务的注册与发现,流程架构图为:

    dubbo需与Spring共同使用,当provider在注册中心注册了一个服务(Sevice)后,consumer中可以申请获取这个Service,它将作为一个bean存在于项目中。

    Dubbo的基本配置

<!-- 使用dubbo发布服务 -->
	<!-- 提供方应用信息,用于计算依赖关系,无关provider还是consumer -->
	<dubbo:application name="provider" />
	<!-- 注册dubbo的服务
	,注册中心可以有多个 -->
	<dubbo:registry protocol="zookeeper"
		address="192.168.25.137:2181" />
	<!-- 各配置项缺省值设置 -->
	<dubbo:provider retries="0" timeout="20000" />
	<!-- 表明用dubbo协议在20880端口暴露服务 -->
	<dubbo:protocol name="dubbo" port="20880" />
	<!-- 声明需要暴露的服务接口,作为provider -->
	<dubbo:service interface="cn.XXXX.service.ItemService" ref="itemServiceImpl" timeout="600000" />
        <!-- 引用服务配置,用于创建一个远程服务代理,一个引用可以指向多个注册中心。-->
        <dubbo:reference id="tmpdemoService" interface="com.unj.dubbotest.provider.DemoService" />

    接下来详细说一下这些配置项的参数,注意有一些共通的参数:

        -Dubbo:service

        -Dubbo:reference

        -Dubbo:protocol

        -Dubbo:registry

        -Dubbo:application

        -Dubbo:provider


参考链接:dubbo的配置及java代码使用Dubbo之XML配置详解


使用RPC与Restful接口调用服务2021-01-13鱼鱼

{{commentTitle}}

评论   ctrl+Enter 发送评论