gRPC 使用 protobuf 构建微服务

发表于 2018-05-02 | 阅读次数: 2997 | 字数统计: 1,805

gRPC 使用 protobuf 通信构建微服务

本文目录:

微服务架构

单一的代码库

以前使用 Laravel 做 web 项目时,是根据 MVC 去划分目录结构的,即 Controller 层处理业务逻辑,Model 层处理数据库的 CURD,View 层处理数据渲染与页面交互。以及 MVP、MVVM 都是将整个项目的代码是集中在一个代码库中,进行业务处理。这种单一聚合代码的方式在前期实现业务的速度很快,但在后期会暴露很多问题:

  • 开发与维护困难:随着业务复杂度的增加,代码的耦合度往往会变高,多个模块相互耦合后不易横向扩展
  • 效率和可靠性低:过大的代码量将降低响应速度,应用潜在的安全问题也会累积

拆分的代码库

微服务是一种软件架构,它将一个大且聚合的业务项目拆解为多个小且独立的业务模块,模块即服务,各服务间使用高效的协议(protobuf、JSON 等)相互调用即是 RPC。这种拆分代码库的方式有以下特点:

  • 每个服务应作为小规模的、独立的业务模块在运行,类似 Unix 的 Do one thing and do it well
  • 每个服务应在进行自动化测试和(分布式)部署时,不影响其他服务
  • 每个服务内部进行细致的错误检查和处理,提高了健壮性

二者对比

本质上,二者只是聚合与拆分代码的方式不同。

参考:微服务架构的优势与不足

构建微服务

UserInfoService 微服务

接下来创建一个处理用户信息的微服务:UserInfoService,客户端通过 name 向服务端查询用户的年龄、职位等详细信息,需先安装 gRPC 与 protoc 编译器:

go get -u google.golang.org/grpcgo get -u github.com/golang/protobuf/protoc-gen-go

目录结构

├── proto│ ├── user.proto// 定义客户端请求、服务端响应的数据格式│ └── user.pb.go// protoc 为 gRPC 生成的读写数据的函数├── server.go// 实现微服务的服务端└── client.go// 调用微服务的客户端

调用流程

Protobuf 协议

每个微服务有自己独立的代码库,各自之间在通信时需要高效的协议,要遵循一定的数据结构来解析和编码要传输的数据,在微服务中常使用 protobuf 来定义。

Protobuf(protocal buffers)是谷歌推出的一种二进制数据编码格式,相比 XML 和 JSON 的文本数据编码格式更有优势:

读写更快、文件体积更小

它没有 XML 的标签名或 JSON 的字段名,更为轻量,更多参考

语言中立

只需定义一份 .proto 文件,即可使用各语言对应的 protobuf 编译器对其编译,生成的文件中有对 message 编码、解码的函数

对于 JSON

  • 在 PHP 中需使用 json_encode() 和 json_decode() 去编解码,在 Golang 中需使用 json 标准库的 Marshal() 和 Unmarshal() … 每次解析和编码比较繁琐
  • 优点:可读性好、开发成本低
  • 缺点:相比 protobuf 的读写速度更慢、存储空间更多

对于 Protobuf

  • .proto 可生成 .php 或 *.pb.go … 在项目中可直接引用该文件中编译器生成的编码、解码函数
  • 优点:高效轻量、一处定义多处使用
  • 缺点:可读性差、开发成本高

定义微服务的 user.proto 文件

syntax = "proto3";// 指定语法格式,注意 proto3 不再支持 proto2 的 required 和 optionalpackage proto;// 指定生成的 user.pb.go 的包名,防止命名冲突// service 定义开放调用的服务,即 UserInfoService 微服务service UserInfoService { // rpc 定义服务内的 GetUserInfo 远程调用 rpc GetUserInfo (UserRequest) returns (UserResponse) { }}// message 对应生成代码的 struct// 定义客户端请求的数据格式message UserRequest {// [修饰符] 类型 字段名 = 标识符;string name = 1;}// 定义服务端响应的数据格式message UserResponse { int32 id = 1; string name = 2; int32 age = 3; repeated string title = 4;// repeated 修饰符表示字段是可变数组,即 slice 类型}

编译 user.proto 文件

# protoc 编译器的 grpc 插件会处理 service 字段定义的 UserInfoService# 使 service 能编码、解码 message$ protoc -I . --go_out=plugins=grpc:. ./user.proto

生成 user.pb.go

package protoimport (context "golang.org/x/net/context"grpc "google.golang.org/grpc")// 请求结构type UserRequest struct {Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`}// 为字段自动生成的 Getterfunc (m *UserRequest) GetName() string {if m != nil {return m.Name}return ""}// 响应结构type UserResponse struct {Id int32 `protobuf:"varint,1,opt,name=id" json:"id,omitempty"`Name string `protobuf:"bytes,2,opt,name=name" json:"name,omitempty"`Age int32 `protobuf:"varint,3,opt,name=age" json:"age,omitempty"`Title []string `protobuf:"bytes,4,rep,name=title" json:"title,omitempty"`}// ...// 客户端需实现的接口type UserInfoServiceClient interface {GetUserInfo(ctx context.Context, in *UserRequest, opts ...grpc.CallOption) (*UserResponse, error)}// 服务端需实现的接口type UserInfoServiceServer interface {GetUserInfo(context.Context, *UserRequest) (*UserResponse, error)}// 将微服务注册到 grpc func RegisterUserInfoServiceServer(s *grpc.Server, srv UserInfoServiceServer) {s.RegisterService(&_UserInfoService_serviceDesc, srv)}// 处理请求func _UserInfoService_GetUserInfo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {...}

服务端实现微服务

实现流程

代码参考

package mainimport (...)// 定义服务端实现约定的接口type UserInfoService struct{}var u = UserInfoService{}// 实现 interfacefunc (s *UserInfoService) GetUserInfo(ctx context.Context, req *pb.UserRequest) (resp *pb.UserResponse, err error) {name := req.Name// 模拟在数据库中查找用户信息// ...if name == "wuYin" {resp = &pb.UserResponse{Id: 233,Name: name,Age: 20,Title: []string{"Gopher

protobuf协议_gRPC 使用 protobuf 构建微服务相关推荐

  1. Spring Boot+gRPC构建微服务并部署到Istio(详细教程)

    点击关注公众号,实用技术文章及时了解 作为Service Mesh和云原生技术的忠实拥护者,我却一直没有开发过Service Mesh的应用.正好最近受够了Spring Cloud的"折磨& ...

  2. 基于Spring Cloud及K8S构建微服务应用

    摘要 广发证券蔡波斯先生通过三个大方向来为我们分享基于Spring Cloud及K8S构建微服务应用. 内容来源:2017年6月10日,广发证券蔡波斯在"Spring Cloud中国社区技术 ...

  3. Spring微服务实战第2章 使用Spring Boot构建微服务

    第2章 使用Spring Boot构建微服务 基于微服务的架构具有以下特点. 有约束的--微服务具有范围有限的单一职责集.微服务遵循UNIX的理念,即应用程序是服务的集合,每个服务只做一件事,并只做好 ...

  4. 使用Spring Boot构建微服务(文末福利)

    本文主要内容 学习微服务的关键特征 了解微服务是如何适应云架构的 将业务领域分解成一组微服务 使用Spring Boot实现简单的微服务 掌握基于微服务架构构建应用程序的视角 学习什么时候不应该使用微 ...

  5. 构建微服务时的三大常见错误

      来自:分布式实验室 公众号,作者:解博 想在网上挨骂,最简单的方法就是写点关于微服务架构的东西.每个人对微服务都有自己的一套见解:无论我们是赞扬还是批评,总会有人跳出来强调"你错了&qu ...

  6. 使用Quarkus在Openshift上构建微服务的快速指南

    点击蓝色"程序猿DD"关注我 回复"资源"获取独家整理的学习资料! [重磅]到底是什么野生海鲜美味,惹得人们都往泥瓦匠老家买? 作者 | 康仔 来源 | 公众号 ...

  7. Spring Cloud构建微服务架构:分布式服务跟踪(整合zipkin)【Dalston版】

    通过上一篇<分布式服务跟踪(整合logstash)>,我们虽然已经能够利用ELK平台提供的收集.存储.搜索等强大功能,对跟踪信息的管理和使用已经变得非常便利.但是,在ELK平台中的数据分析 ...

  8. Spring Cloud构建微服务架构:分布式服务跟踪(整合logstash)【Dalston版】

    通过之前的<入门示例>,我们已经为两个由SpringCloud构建的微服务项目 trace-1和 trace-2引入了Spring Cloud Sleuth的基础模块 spring-clo ...

  9. Spring Cloud构建微服务架构:分布式服务跟踪(跟踪原理)

    通过上一篇<分布式服务跟踪(入门)>的例子,我们已经通过Spring Cloud Sleuth往微服务应用中添加了实现分布式跟踪具备的基本要素.下面通过本文来详细说说实现分布式服务跟踪的一 ...

最新文章

  1. 软件包管理 之 软件在线升级更新yum 图形工具介绍
  2. Linux查看/var/log/wtmp文件查看可疑IP登陆
  3. lsmod modinfo ....
  4. 前端常见知识点三之HTML
  5. Vue的模板字符串${}用法
  6. SAP Spartacus 的页面模型在SAP 电商云后台WCMS里的模型
  7. Jquery中如何获取元素的文本,值,属性和内容
  8. 数据显示,中国近一半的独角兽企业由“BATJ”四巨头投资
  9. Spring @PostConstruce 和 @PreDestroy 实例化\销毁 bean 时
  10. 2018程序员必备的4大网站推荐(代码、编程、SQL等)
  11. visual studio 11开发Win8模板
  12. jenkins vue 打包特别慢_Jenkins 自动化部署
  13. MATLAB下载+安装教程
  14. 【visio 绘图矢量图素材网站】
  15. java项目目录_Java项目目录解释
  16. java窗口设计_java简单窗口设计(源代码)
  17. 劉筱娟:人工智能名片能在移动互联网营销上发挥什么作用?
  18. java微信多客服_微信多客服聊天功能怎么实现?
  19. python统计英文单词个数_统计英文单词的个数的python代码 及 字符串分割
  20. 微软官方原版WindowsXP Pro With Sp2简体中文VOL版

热门文章

  1. ssas 层次结构_分析服务(SSAS)多维设计技巧–关系和层次结构
  2. 在使用静态构造函数的时候应该注意几点
  3. 白化(Whitening): PCA 与 ZCA (转)
  4. 找换硬币问题 与 0-1背包问题区别
  5. UILabel---.tff格式字体
  6. zabbix 的安装
  7. linux 输入子系统(4)---- input子系统的初始化
  8. netstat mysql_mysql-netstat
  9. ajax常见的面试题
  10. 结队编程1-四则运算(107、120)