微服务开发手册之grpc(代码片段)

woshidanzi woshidanzi     2023-03-17     538

关键词:

> GRPC是一个高性能、通用的开源RPC框架,基于HTTP/2协议标准和Protobuf序列化协议开发,支持众多的开发语言。

@[TOC]

1 简介

在GRPC框架中,客户端可以像调用本地对象一样直接调用位于不同机器的服务端方法,如此我们就可以非常方便的创建一些分布式的应用服务。

在服务端,我们实现了所定义的服务和可供远程调用的方法,运行一个gRPC server来处理客户端的请求;在客户端,gRPC实现了一个stub(可以简单理解为一个client),其提供跟服务端相同的方法。 技术图片 gRPC使用protocol buffers作为接口描述语言(IDL)以及底层的信息交换格式,一般情况下推荐使用 proto3因为其能够支持更多的语言,并减少一些兼容性的问题。 由于gRPC涉及到几个比较重要的技术点http2、protobuf,正是这几个技术点才使得gRPC得到广泛应用,这里也顺带讲一下这几个技术点

1.1 http2

HTTP/2是最新的HTTP协议,提高了资源访问效率。通过本篇科普小文,可以了解HTTP/2协议的概念以及优势。

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)。

HTTP/2新特性

1.1.1二进制传输

HTTP/2传输数据量的大幅减少,主要有两个原因:以二进制方式传输和Header 压缩。先来介绍一下二进制传输,HTTP/2 采用二进制格式传输数据,而非HTTP/1.1 里纯文本形式的报文 ,二进制协议解析起来更高效。HTTP/2 将请求和响应数据分割为更小的帧,并且它们采用二进制编码。HTTP/2所有性能增强的核心在于新的二进制分帧层,它定义了如何封装http消息并在客户端与服务器之间传输。

1.1.2 Header压缩

HTTP/1.1的header带有大量信息,而且每次都要重复发送,HTTP/2并没有使用传统的压缩算法,而是开发了专门的“HPACK”算法,在客户端和服务器两端建立“字典”,用索引号表示重复的字符串,还采用哈夫曼编码来压缩整数和字符串,可以达到50%~90%的高压缩率。

1.1.3 多路复用

多路复用允许同时通过单一的HTTP/2连接发起多重的请求-响应信息,很好的解决了浏览器限制同一个域名下的请求数量的问题,同时也更容易实现全速传输。

1.1.4 服务器推送

HTTP2还在一定程度上改变了传统的“请求-应答”工作模式,服务器不再是完全被动地响应请求,也可以新建“流”主动向客户端发送消息。比如,在浏览器刚请求HTML的时候就提前把可能会用到的JS、CSS文件发给客户端,减少等待的延迟,这被称为”服务器推送”( Server Push,也叫 Cache push)。

1.2 Protobuf

Protocol buffers 是一种语言中立,平台无关,可扩展的序列化数据的格式,可用于通信协议,数据存储等。

Protocol buffers 在序列化数据方面,它是灵活的,高效的。相比于 XML 来说,Protocol buffers 更加小巧,更加快速,更加简单。一旦定义了要处理的数据的数据结构之后,就可以利用 Protocol buffers 的代码生成工具生成相关的代码。甚至可以在无需重新部署程序的情况下更新数据结构。只需使用 Protobuf 对数据结构进行一次描述,即可利用各种不同语言或从各种不同数据流中对你的结构化数据轻松读写。

Protocol buffers 很适合做数据存储或 RPC 数据交换格式。可用于通讯协议、数据存储等领域的语言无关、平台无关、可扩展的序列化结构数据格式。

1.2.1 优点

1、性能好/效率高

时间开销: XML格式化(序列化)的开销还好;但是XML解析(反序列化)的开销就不敢恭维了。 但是protobuf在这个方面就进行了优化。可以使序列化和反序列化的时间开销都减短。

空间开销:也减少了很多

2、有代码生成机制

比如你你写个一下类似结构体的内容


 message testA  
  
    required int32 m_testA = 1;  
  

像写一个这样的结构,protobuf可以自动生成它的.h 文件和点.cpp文件。 protobuf将对结构体testA的操作封装成一个类。

3、支持向后兼容和向前兼容

当客户端和服务器同事使用一块协议的时候, 当客户端在协议中增加一个字节,并不会影响客户端的使用

4、支持多种编程语言

在Google官方发布的源代码中包含了c++、java、Python三种语言

1.2.2 缺点

1、二进制格式导致可读性差

为了提高性能,protobuf采用了二进制格式进行编码。这直接导致了可读性差。这个直接影响开发测试时候的效率。当然,一般情况下,protobuf非常可靠,并不会出现太大的问题。

2、缺乏自描述

一般来说,XML是自描述的,而protobuf格式则不是。 给你一段二进制格式的协议内容,不配合你写的结构体是看不出来什么作用的。

3、通用性差

protobuf虽然支持了大量语言的序列化和反序列化,但仍然并不是一个跨平台和语言的传输标准。在多平台消息传递中,对其他项目的兼容性并不是很好,需要做相应的适配改造工作。相比json 和 XML,通用性还是没那么好。

1.2.3 与其他序列化方式对比

protobuf处理整型特别快,如果需要了解原理可以查看高效的数据压缩编码方式 Protobuf

至于与其他序列化方式以及使用场景的对比可以参考下面的文章 Protobuf有没有比JSON快5倍?用代码来击破pb性能神话

全方位评测:Protobuf性能到底有没有比JSON快5倍?

2 grpc四种模式

1,简单模式:简单模式只是使用参数和返回值作为服务器与客户端传递数据的方式,最简单。

2,客户端流模式:即从客户端往服务器端发送数据使用的是流,即服务器端的参数为流类型,然而在服务器相应后返还数据给客户端,使用的也是流的send方法。一般在服务器端的代码,需要先recv再send,而客户端与此相反。但是在后面的双向模式中可以使用go的协程协作。

3,服务器端流模式:即服务器端返回结果的时候使用的是流模式,即传入的数据是通过参数形式传入的。但是在往客户端发送数据时使用send方法,与客户端返回数据的方式大同小异。

4,双向模式:客户端如果不适用协程,那么发送必须在接收之前。如果使用协程,发送与接收并没有先后顺序。为了保证协程的同步,可以使用互斥量进行约束。

如果想要了解详细demo,可以查看gRPC 官方文档中文版

3 集成springcloud

这里集成grpc建议有两种方案,

3.1 实现公共protobuf,通过java grpc来远程调用

这个方案就是不用编写protobuf了,可以直接类似dubbo一样提供java api就可以实现rpc调用,这里详情可以参考github上的demo ttps://github.com/ChinaSilence/spring-boot-starter-grpc

技术图片

  • facade:独立的 Maven 模块,依赖 spring-boot-www.yixingylzc.cn starter-grpc,需要远程调用的方法,都定义在此模块,形式可以为接口(interface) 或者抽象类(abstract www.lanboyulezc.cn class)

  • server:服务提供方,依赖 facade 模块,需实现 facade 模块定义的接口或者抽象类的抽象方法

  • client:服务调用方,依赖 facade 模块,使用时,直接调用即可

优缺点分析

优点:

  • 不需要编写probuff文件,以java api形式来定义接口

  • 不依赖于eureka,完美适用于k8s

缺点:

  • 只支持java,如果要支持异构语言需要使用springcloudsidecar 或者 手动注册到eureka
  • eureka支持有限,不支持负载均衡

3.2 每次使用protobuf定义接口(集成net.devh.grpc)

这里内容还比较多,详情可以参考我的博客 springcloud集成grpc(百事2:www.baihuayl7.cn) 这种方式集成每次都需要编写proto接口文件并自动生成代码,客户端和服务端都需要另外组装参数。

不过优势是,有详细的接口规范(protobuf),并且可以支持异构语言调用。

后面会介绍只有java语言调用,但是不用每次都编写proto文件的集成方式。

4 服务发现与负载均衡

gRPC开源组件官方并未直接提供服务注册与发现的功能实现,但其设计文档已提供实现的思路,并在不同语言的gRPC代码API中已提供了命名解析和负载均衡接口供扩展。

其基本实现原理:

服务启动后gRPC客户端向命名服务器发出名称解析请求,名称将解析为一个或多个IP地址,每个IP地址标示它是服务器地址还是负载均衡器地址,以及标示要使用那个客户端负载均衡策略或服务配置。

客户端实例化负载均衡策略,如果解析返回的地址是负载均衡器地址,则客户端将使用grpclb策略,否则客户端使用服务配置请求的负载均衡策略。

负载均衡策略为每个服务器地址创建一个子通道(channel)。

当有rpc请求时,负载均衡策略决定那个子通道即grpc服务器将接收请求,当可用服务器为空时客户端的请求将被阻塞。 根据gRPC官方提供的设计思路,基于进程内LB方案(即第2个案,阿里开源的服务框架 Dubbo 也是采用类似机制),结合分布式一致的组件(如Zookeeper、Consul、Etcd),可找到gRPC服务发现和负载均衡的可行解决方案。接下来以GO语言为例,简单介绍下基于Etcd3的关键代码实现:

4.1 dubbo

上面有描述,dubbo支持grpc,方案类似本文3.1提出的方案,不过是阿里提供了一整套微服务体系,包括注册中心nacas、dubbo、sentinel都支持grpc

4.2 springcloud

这个方案同样是类似3.2章,上面是集成了net.devh.www.shbkrcxzz.cn grpc, 该插件最新版本,同样支持springcloud全家桶,详细可以参考github: https://github.com/yidongnan/grpc-spring-boot-starter。 如果是异构语言则需要集成springcloud中的sidecar来实现服务发现,这里也仅仅是支持java调用其他异构语言,如果需要其他语言也支持相互调用,则需要对应语言按照开源组件官方说的方案二来实现相应组件

4.3 istio

Istio是什么:Istio是Google/IBM/Lyft联合开发的开源项目,2017年5月发布第一个release 0.1.0, 官方定义为:

Istio:一个连接,管理和保护微服务的开放平台。

按照isito文档中给出的定义:

Istio提供一种简单的方式来建立已部署的服务的网络,具备负载均衡,服务到服务认证,监控等等功能,而不需要改动任何服务代码。

简单的说,有了Istio,你的服务就不再需要任何微服务开发框架(典型如Spring Cloud,Dubbo),也不再需要自己动手实现各种复杂的服务治理的功能(很多是Spring Cloud和Dubbo也不能提供的,需要自己动手)。只要服务的客户端和服务器可以进行简单的直接网络访问,就可以通过将网络层委托给Istio,从而获得一系列的完备功能。 Istio的关键功能:

  • HTTP/1.1,www.lanboylpt.cn HTTP/2,gRPC和TCP流量的自动区域感知负载平衡和故障切换。
  • 通过丰富的路由规则,容错和故障注入,对流行为的细粒度控制。
  • 支持访问控制,速率限制和配额的可插拔策略层和配置API。
  • 集群内所有流量的自动量度,日志和跟踪,包括集群入口和出口。
  • 安全的服务到服务身份验证,在集群中的服务之间具有强大的身份标识。

可以近似的理解为:Istio = 微服务框架 + 服务治理 以下是 Istio 的官方拓扑图: 技术图片 这里的前提是使用了k8s,在k8s中可以无缝集成istio。具体操作步骤我这里不做详细描述,详情可以参考下面链接使用Istio和Envoy实践服务网格gRPC度量

5 grpc之拦截器

grpc自带认证,不过有时候也需要在调用前,或者调用后做一些操作,比如说记录监控信息、或者透传header等等,这时就需要用到grpc的拦截器,这里仅以java语言来说一下拦截器用法。

5.1 server拦截器

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 -&gt; registry.addServerInterceptors(grpcServerInterceptor);
    


同时如果集成了grpc-spring-boot-starter,也可以使用@GrpcGlobalInterceptor来增加全局拦截器,hi需要将该注解加到类名上

5.2 client拦截器

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) www.dafengyulept.com
                        super.onHeaders(恒煊2:www.hengxuangyul.com  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(www.jintianxuesha.com);
    

    @Bean
    public GlobalClientInterceptorConfigurer globalInterceptorConfigurerAdapter(ClientInterceptor grpcClientInterceptor) 
        return registry -&gt; registry.addClientInterceptors(grpcClientInterceptor);
    



同时如果集成了grpc-spring-boot-starter,也可以使用@GrpcGlobalInterceptor来增加全局拦截器,hi需要将该注解加到类名上

6 grpc监控之全链路

关于全链路监控,可以参考我的全链路系列博客

微服务全链路跟踪:grpc集成zipkin

微服务全链路跟踪:jaeger集成grpc

微服务全链路跟踪:jaeger集成istio,并兼容uber-trace-id与b3

7 grpc监控之prometheus

如果是集成了 grpc-spring-boot-starter,则只需要访问 http://服务域名/actuator/prometheus,可以看到grpc相关监控指标 技术图片技术图片技术图片 如果是集成了grafana,就能看到下面的效果: 技术图片技术图片

8 grpc断路器

grpc断路器有几种方案:

1、istio断路器 参考相关博客istio-断路器示例

2、hystrix 参考我的博客grpc断路器之hystrix

3、sentinel grpc断路器之sentinel

9 grpc高并发优化之预热

这里可以参考我的博客 springcloud线上发布超时之grpc优化

10 grpc报错集锦以及解决方案

参考我的博客: grpc报错合集以及解决方案

grpc坑之Could not find TLS ALPN provider; no working netty-tcnative

未完待续</respt></respt></reqt,></reqt,></reqt,></reqt,></string></reqt,></reqt,></reqt></reqt,>

go微服务grpc(代码片段)

gRPC教程RPC算是近些年比较火热的概念了,随着微服务架构的兴起,RPC的应用越来越广泛。本文介绍了RPC和gRPC的相关概念,并且通过详细的代码示例介绍了gRPC的基本使用。gRPC是什么gRPC是一种现代化开源的高性能RPC框... 查看详情

go微服务grpc(代码片段)

gRPC教程RPC算是近些年比较火热的概念了,随着微服务架构的兴起,RPC的应用越来越广泛。本文介绍了RPC和gRPC的相关概念,并且通过详细的代码示例介绍了gRPC的基本使用。gRPC是什么gRPC是一种现代化开源的高性能RPC框... 查看详情

3.微服务--grpc(代码片段)

...中立、平台中立、开源的远程过程调用系统gRPC客户端和服务端可以在多种环境中运行和交互,例如用java写一个服务端,可以用go语言写客户端调用1.2gRPC与Protobuf介绍微服务架构中,由于每个服务对应的代码库是独立运行的,无... 查看详情

微服务与rpc/grpc(代码片段)

微服务(microservices)微服务概述微服务简介微(micro)狭义来讲就是体积小,著名的"2pizza团队"很好的诠释了这一解释(2pizza团队最早是亚马逊CEOBezos提出来的,意思是说单个服务的设计,所有参与人从设计、开发、测试、运维... 查看详情

微服务架构设计基础之领域驱动设计(代码片段)

DDD早于微服务「出道」十年,这两个「忘年交」的软件设计哲学是如何相爱相杀的?背景微服务现在可以说是软件研发领域无人不提的话题,然而业界流行的对比多数都是所谓的Monolithic(单体应用),而大量的系统在十几年前都已... 查看详情

10.微服务全局配置中心之config(代码片段)

微服务全局配置中心之Config什么是ConfigConfigServer开发gitee仓库登录|注册创建仓库拷贝地址Server端开发1.新建Module2.pom.xml3.ConfigServerApplication.java4.application.properties5.启动ConfigClient开发1.新建Module2.pom.xml3.ConfigClientApplicat 查看详情

springboot+grpc构建微服务并部署到istio(详细教程)(代码片段)

...rnetes也可以熟练使用了,而且网上几乎没有SpringBoot微服务部署到Istio的案例,我就开始考虑用SpringBoot写个微 查看详情

springboot+grpc构建微服务并部署到istio(详细教程)(代码片段)

...rnetes也可以熟练使用了,而且网上几乎没有SpringBoot微服务部署到Istio的案例,我就开始考虑用SpringBoot写个微 查看详情

grpc怎样节省您的开发时间(代码片段)

...中至少一次)。在本文中,我将着重介绍采用gRPC作为微服务之间的通信介质的好处。首先,我将尝试简要介绍一下架构演变的历史。其次,我将重点介绍使用REST(作为媒介)和可能出现的问题。第三,gRPC启动。最后,我将以我... 查看详情

微服务之servicefabric系列(代码片段)

...微软官方文档 servicefabric  百家号  大话微服务架构之微服务框架微软ServiceFabric正式开源一、概述  1.概念     AzureServiceFabric是一款分布式系统平台,可方便用户轻松打包、部署和管理可缩放的可靠微服... 查看详情

《云原生入门级开发者认证》学习笔记之微服务架构介绍(代码片段)

...对云原生整个体系一直都很模糊作为Java开发来讲,微服务是大多数行业都要涉及的开源技术栈博文主要内容涉及:企业应用架构的演进:单体地狱、SOA,微服务架构,当然微服务并不是“银弹"典型的微服务框架介绍S... 查看详情

grpc入门(代码片段)

...程调用协议,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。相比HTTP协议来说,它主要是基于TCP/IP协议的的,传输效率更高,能够跨语言,典型的RPC框架有RMI、Hessian、Dubbo等。想要深入了解... 查看详情

go微服务工具包gokit怎么集成grpc?(代码片段)

大家好,我是frank。欢迎大家点击标题下方rpcRegister(RegisterReq)returns(RegisterRes)...生成pb文件protoc -I proto \\> --go_out ./pb/user --go_opt paths=source_relative \\>  查看详情

springcloud系列教程汇总整理手册

1、微服务之DubboSpringBoot系列之集成Dubbo实现微服务教程    >>sourcedownloadSpringBoot系列之集成Dubbo的方式    >>sourcedownload2、微服务之SpringCloud2.1服务治理实现SpringCloud系列使用NetflixEureka进行服务治理2.2声明式服务调用Spr... 查看详情

基于go/grpc/kubernetes/istio开发微服务的最佳实践尝试(代码片段)

基于Go/Grpc/kubernetes/Istio开发微服务的最佳实践尝试-1/3基于Go/Grpc/kubernetes/Istio开发微服务的最佳实践尝试-2/3基于Go/Grpc/kubernetes/Istio开发微服务的最佳实践尝试-3/3项目地址:https://github.com/janrs-io/Jgrpc转载请注明来源:https://janrs.com/... 查看详情

grpc入门(代码片段)

...P/2协议,支持多路复用和流控制等特性,能够在客户端和服务器之间高效地传输大量数据。同时,gRPC还使用了基于平台优化的序列化和反序列化技术,提高了通信的效率。简单易用:gRPC的IDL语言简单易懂,同时提供了自动生成... 查看详情

istio微服务架构实现服务间grpc通信(代码片段)

...f0c;如下图所示:该案例所演示的就是我们日常使用微服务架构开发时,服务间最普遍的通信场景。在SpringCloud微服务体系中,服务间可以通过Fegin+Ribbon组合的方式,实现服务间负载均衡方式的Http接口调用;... 查看详情

istio微服务架构实现服务间grpc通信(代码片段)

...f0c;如下图所示:该案例所演示的就是我们日常使用微服务架构开发时,服务间最普遍的通信场景。在SpringCloud微服务体系中,服务间可以通过Fegin+Ribbon组合的方式,实现服务间负载均衡方式的Http接口调用;... 查看详情