GRPC是一个高性能、通用的开源RPC框架,基于HTTP/2协议标准和Protobuf序列化协议开发,支持众多的开发语言。html
@[TOC]java
在GRPC框架中,客户端能够像调用本地对象同样直接调用位于不一样机器的服务端方法,如此咱们就能够很是方便的建立一些分布式的应用服务。c++
在服务端,咱们实现了所定义的服务和可供远程调用的方法,运行一个gRPC server来处理客户端的请求;在客户端,gRPC实现了一个stub(能够简单理解为一个client),其提供跟服务端相同的方法。 gRPC使用protocol buffers做为接口描述语言(IDL)以及底层的信息交换格式,通常状况下推荐使用 proto3由于其可以支持更多的语言,并减小一些兼容性的问题。 因为gRPC涉及到几个比较重要的技术点http二、protobuf,正是这几个技术点才使得gRPC获得普遍应用,这里也顺带讲一下这几个技术点git
HTTP/2是最新的HTTP协议,提升了资源访问效率。经过本篇科普小文,能够了解HTTP/2协议的概念以及优点。github
HTTP/2也被称为HTTP 2.0,相对于HTTP 1.1新增多路复用、压缩HTTP头、划分请求优先级、服务端推送等特性,解决了在HTTP 1.1中一直存在的问题,优化了请求性能,同时兼容了HTTP 1.1的语义。算法
2015年,HTTP/2 发布。HTTP/2是现行HTTP协议(HTTP/1.1)的替代,但它不是重写,HTTP方法、状态码、语义都与HTTP/1.1同样。HTTP/2 相比于 HTTP/1.1,能够说是大幅度提升了网页的性能,只须要升级到该协议就能够减小不少以前须要作的性能优化工做。HTTP/2基于SPDY,专一于性能,最大的一个目标是在用户和网站间只用一个链接(connection)。spring
HTTP/2新特性编程
HTTP/2传输数据量的大幅减小,主要有两个缘由:以二进制方式传输和Header 压缩。先来介绍一下二进制传输,HTTP/2 采用二进制格式传输数据,而非HTTP/1.1 里纯文本形式的报文 ,二进制协议解析起来更高效。HTTP/2 将请求和响应数据分割为更小的帧,而且它们采用二进制编码。HTTP/2全部性能加强的核心在于新的二进制分帧层,它定义了如何封装http消息并在客户端与服务器之间传输。json
HTTP/1.1的header带有大量信息,并且每次都要重复发送,HTTP/2并无使用传统的压缩算法,而是开发了专门的“HPACK”算法,在客户端和服务器两端创建“字典”,用索引号表示重复的字符串,还采用哈夫曼编码来压缩整数和字符串,能够达到50%~90%的高压缩率。api
多路复用容许同时经过单一的HTTP/2链接发起多重的请求-响应信息,很好的解决了浏览器限制同一个域名下的请求数量的问题,同时也更容易实现全速传输。
HTTP2还在必定程度上改变了传统的“请求-应答”工做模式,服务器再也不是彻底被动地响应请求,也能够新建“流”主动向客户端发送消息。好比,在浏览器刚请求HTML的时候就提早把可能会用到的JS、CSS文件发给客户端,减小等待的延迟,这被称为”服务器推送”( Server Push,也叫 Cache push)。
Protocol buffers 是一种语言中立,平台无关,可扩展的序列化数据的格式,可用于通讯协议,数据存储等。
Protocol buffers 在序列化数据方面,它是灵活的,高效的。相比于 XML 来讲,Protocol buffers 更加小巧,更加快速,更加简单。一旦定义了要处理的数据的数据结构以后,就能够利用 Protocol buffers 的代码生成工具生成相关的代码。甚至能够在无需从新部署程序的状况下更新数据结构。只需使用 Protobuf 对数据结构进行一次描述,便可利用各类不一样语言或从各类不一样数据流中对你的结构化数据轻松读写。
Protocol buffers 很适合作数据存储或 RPC 数据交换格式。可用于通信协议、数据存储等领域的语言无关、平台无关、可扩展的序列化结构数据格式。
一、性能好/效率高
时间开销: XML格式化(序列化)的开销还好;可是XML解析(反序列化)的开销就不敢恭维了。 可是protobuf在这个方面就进行了优化。可使序列化和反序列化的时间开销都减短。
空间开销:也减小了不少
二、有代码生成机制
好比你你写个一下相似结构体的内容
message testA { required int32 m_testA = 1; }
像写一个这样的结构,protobuf能够自动生成它的.h 文件和点.cpp文件。 protobuf将对结构体testA的操做封装成一个类。
三、支持向后兼容和向前兼容
当客户端和服务器同事使用一块协议的时候, 当客户端在协议中增长一个字节,并不会影响客户端的使用
四、支持多种编程语言
在Google官方发布的源代码中包含了c++、java、Python三种语言
一、二进制格式致使可读性差
为了提升性能,protobuf采用了二进制格式进行编码。这直接致使了可读性差。这个直接影响开发测试时候的效率。固然,通常状况下,protobuf很是可靠,并不会出现太大的问题。
二、缺少自描述
通常来讲,XML是自描述的,而protobuf格式则不是。 给你一段二进制格式的协议内容,不配合你写的结构体是看不出来什么做用的。
三、通用性差
protobuf虽然支持了大量语言的序列化和反序列化,但仍然并非一个跨平台和语言的传输标准。在多平台消息传递中,对其余项目的兼容性并非很好,须要作相应的适配改造工做。相比json 和 XML,通用性仍是没那么好。
protobuf处理整型特别快,若是须要了解原理能够查看高效的数据压缩编码方式 Protobuf
至于与其余序列化方式以及使用场景的对比能够参考下面的文章 Protobuf有没有比JSON快5倍?用代码来击破pb性能神话
全方位评测:Protobuf性能到底有没有比JSON快5倍?
1,简单模式:简单模式只是使用参数和返回值做为服务器与客户端传递数据的方式,最简单。
2,客户端流模式:即从客户端往服务器端发送数据使用的是流,即服务器端的参数为流类型,然而在服务器相应后返还数据给客户端,使用的也是流的send方法。通常在服务器端的代码,须要先recv再send,而客户端与此相反。可是在后面的双向模式中可使用go的协程协做。
3,服务器端流模式:即服务器端返回结果的时候使用的是流模式,即传入的数据是经过参数形式传入的。可是在往客户端发送数据时使用send方法,与客户端返回数据的方式大同小异。
4,双向模式:客户端若是不适用协程,那么发送必须在接收以前。若是使用协程,发送与接收并无前后顺序。为了保证协程的同步,可使用互斥量进行约束。
若是想要了解详细demo,能够查看gRPC 官方文档中文版
这里集成grpc建议有两种方案,
这个方案就是不用编写protobuf了,能够直接相似dubbo同样提供java api就能够实现rpc调用,这里详情能够参考github上的demo ttps://github.com/ChinaSilence/spring-boot-starter-grpc
facade:独立的 Maven 模块,依赖 spring-boot-starter-grpc
,须要远程调用的方法,都定义在此模块,形式能够为接口(interface) 或者抽象类(abstract class)
server:服务提供方,依赖 facade
模块,需实现 facade
模块定义的接口或者抽象类的抽象方法
client:服务调用方,依赖 facade
模块,使用时,直接调用便可
优势:
不须要编写probuff文件,以java api形式来定义接口
不依赖于eureka,完美适用于k8s
缺点:
这里内容还比较多,详情能够参考个人博客 springcloud集成grpc(一) 这种方式集成每次都须要编写proto接口文件并自动生成代码,客户端和服务端都须要另外组装参数。
不过优点是,有详细的接口规范(protobuf),而且能够支持异构语言调用。
gRPC开源组件官方并未直接提供服务注册与发现的功能实现,但其设计文档已提供实现的思路,并在不一样语言的gRPC代码API中已提供了命名解析和负载均衡接口供扩展。
其基本实现原理:
服务启动后gRPC客户端向命名服务器发出名称解析请求,名称将解析为一个或多个IP地址,每一个IP地址标示它是服务器地址仍是负载均衡器地址,以及标示要使用那个客户端负载均衡策略或服务配置。
客户端实例化负载均衡策略,若是解析返回的地址是负载均衡器地址,则客户端将使用grpclb策略,不然客户端使用服务配置请求的负载均衡策略。
负载均衡策略为每一个服务器地址建立一个子通道(channel)。
当有rpc请求时,负载均衡策略决定那个子通道即grpc服务器将接收请求,当可用服务器为空时客户端的请求将被阻塞。
根据gRPC官方提供的设计思路,基于进程内LB方案(即第2个案,阿里开源的服务框架 Dubbo 也是采用相似机制),结合分布式一致的组件(如Zookeeper、Consul、Etcd),可找到gRPC服务发现和负载均衡的可行解决方案。接下来以GO语言为例,简单介绍下基于Etcd3的关键代码实现:
上面有描述,dubbo支持grpc,方案相似本文3.1提出的方案,不过是阿里提供了一整套微服务体系,包括注册中心nacas、dubbo、sentinel都支持grpc
这个方案一样是相似3.2章,上面是集成了net.devh.grpc, 该插件最新版本,一样支持springcloud全家桶,详细能够参考github: https://github.com/yidongnan/grpc-spring-boot-starter。 若是是异构语言则须要集成springcloud中的sidecar来实现服务发现,这里也仅仅是支持java调用其余异构语言,若是须要其余语言也支持相互调用,则须要对应语言按照开源组件官方说的方案二来实现相应组件
Istio是什么:Istio是Google/IBM/Lyft联合开发的开源项目,2017年5月发布第一个release 0.1.0, 官方定义为:
Istio:一个链接,管理和保护微服务的开放平台。
按照isito文档中给出的定义:
Istio提供一种简单的方式来创建已部署的服务的网络,具有负载均衡,服务到服务认证,监控等等功能,而不须要改动任何服务代码。
简单的说,有了Istio,你的服务就再也不须要任何微服务开发框架(典型如Spring Cloud,Dubbo),也再也不须要本身动手实现各类复杂的服务治理的功能(不少是Spring Cloud和Dubbo也不能提供的,须要本身动手)。只要服务的客户端和服务器能够进行简单的直接网络访问,就能够经过将网络层委托给Istio,从而得到一系列的完备功能。 Istio的关键功能:
能够近似的理解为:Istio = 微服务框架 + 服务治理 如下是 Istio 的官方拓扑图: 这里的前提是使用了k8s,在k8s中能够无缝集成istio。具体操做步骤我这里不作详细描述,详情能够参考下面连接使用Istio和Envoy实践服务网格gRPC度量
grpc自带认证,不过有时候也须要在调用前,或者调用后作一些操做,好比说记录监控信息、或者透传header等等,这时就须要用到grpc的拦截器,这里仅以java语言来讲一下拦截器用法。
public class MyServerInsterceptor implements ServerInterceptor{ @Override public <reqt, respt> ServerCall.Listener<reqt> interceptCall(ServerCall<reqt, respt> call, Metadata headers, ServerCallHandler<reqt, respt> next) { return next.startCall(call,headers); } }
这里能够设置全局拦截器
@Configuration public class GrpcOpenConfig { //grpc-spring-boot-starter provides @GrpcGlobalInterceptor to allow server-side interceptors to be registered with all //server stubs, we are just taking advantage of that to install the server-side gRPC tracer. @Bean ServerInterceptor grpcServerInterceptor() { return new MyServerInterceptor(); } @Bean public GlobalServerInterceptorConfigurer globalInterceptorConfigurerAdapter(ServerInterceptor grpcServerInterceptor) { return registry -> registry.addServerInterceptors(grpcServerInterceptor); } }
同时若是集成了grpc-spring-boot-starter,也可使用@GrpcGlobalInterceptor来增长全局拦截器,hi须要将该注解加到类名上
public class MyClientInterceptor implements ClientInterceptor { Metadata.Key<string> token = Metadata.Key.of("token", Metadata.ASCII_STRING_MARSHALLER); @Override public <reqt, respt> ClientCall<reqt, respt> interceptCall(MethodDescriptor<reqt, respt> method, CallOptions callOptions, Channel next) { return new SimpleForwardingClientCall<reqt, respt>(next.newCall(method, callOptions)) { @Override public void start(Listener<respt> responseListener, Metadata headers) { //此处为你登陆后得到的token的值 headers.put(token, "A2D05E5ED2414B1F8C6AEB19F40EF77C"); super.start(new SimpleForwardingClientCallListener<respt>(responseListener) { @Override public void onHeaders(Metadata headers) { super.onHeaders(headers); } }, headers); } }; } }
这里能够设置全局拦截器
@Order(Ordered.LOWEST_PRECEDENCE) @Configuration @Slf4j public class GrpcOpenTracingConfig { //We also create a client-side interceptor and put that in the context, this interceptor can then be injected into gRPC clients and //then applied to the managed channel. @Bean ClientInterceptor grpcClientInterceptor() { return new MyclientInterceptor(); } @Bean public GlobalClientInterceptorConfigurer globalInterceptorConfigurerAdapter(ClientInterceptor grpcClientInterceptor) { return registry -> registry.addClientInterceptors(grpcClientInterceptor); } }
同时若是集成了grpc-spring-boot-starter,也可使用@GrpcGlobalInterceptor来增长全局拦截器,hi须要将该注解加到类名上
关于全链路监控,能够参考个人全链路系列博客
微服务全链路跟踪:jaeger集成istio,并兼容uber-trace-id与b3
若是是集成了 grpc-spring-boot-starter,则只须要访问 http://服务域名/actuator/prometheus ,能够看到grpc相关监控指标
若是是集成了grafana,就能看到下面的效果:
grpc断路器有几种方案:
一、istio断路器 参考相关博客istio-断路器示例
二、hystrix 参考个人博客grpc断路器之hystrix
三、sentinel grpc断路器之sentinel
这里能够参考个人博客 springcloud线上发布超时之grpc优化
参考个人博客:
grpc坑之Could not find TLS ALPN provider; no working netty-tcnative
未完待续