Go语言学习 - RPC篇:gRPC-Gateway示例代码概览

简介: gRPC-Gateway是gRPC生态的一环,用于对HTTP协议的扩展,是一套高性能、高扩展的开源RPC框架。因此,要掌握gRPC-Gateway,必须要对gRPC有一定的基础,才能明白它的定位与价值。

概览

gRPC-Gateway是gRPC生态的一环,用于对HTTP协议的扩展,是一套高性能、高扩展的开源RPC框架。

因此,要掌握gRPC-Gateway,必须要对gRPC有一定的基础,才能明白它的定位与价值。

方案概览

整个方案分为两个方向:

纵向 - RPC协议调用

三个模块:

  • 调用方 - API Client
  • HTTP服务 - Reverse Proxy
  • gRPC服务 - Your gRPC service

两个协议:

  • HTTP - 客户端发起的是HTTP协议,传输到反向代理
  • gRPC - 反向代理与gRPC服务之间的协议是gRPC

关键点:

  1. Reverse Proxy实现了的关键能力是:将HTTP协议转化为gRPC协议
  2. 可同时提供2个服务:HTTP和gRPC,只是HTTP服务的最终实现还是调用到了gRPC

横向 - Protobuf的代码生成

  • gRPC-Gateway部分:自动生成反向代理
  • gRPC部分:自动生成stub

stub这个单词很有意思,相对准确的翻译是存根、残端,和面向对象中的 接口 有异曲同工之妙:提供了实现的框架,但具体实现仍交由开发者

开发工作

对开发者来说,整个方案的工作分为两部分:

  1. RPC部分 - 编写proto文件
  2. 业务逻辑部分 - 编写gRPC中的stub的实现

开发思路

1. RPC开发 - proto文件的编写

我们看一个官方github上的示例proto文件:

syntax = "proto3";
package your.service.v1;
option go_package = "github.com/yourorg/yourprotos/gen/go/your/service/v1";

import "google/api/annotations.proto";

message StringMessage {
  string value = 1;
}

service YourService {
  rpc Echo(StringMessage) returns (StringMessage) {
    option (google.api.http) = {
      post: "/v1/example/echo"
      body: "*"
    };
  }
}

我们从上到下,对里面的语法做简单的分析:

  • proto3版本
  • proto的包名称
  • 生成Go语言代码后的Go Package
  • 导入依赖的proto文件
  • Message - 表示RPC的数据结构,按规则生成到各语言的代码
  • Service - 一组RPC的抽象
  • rpc - 一个具体方法,包括 方法名(请求Message) returns (返回Message)
  • google.api.http - HTTP协议的定义,如示例中的方法和URL

2. 代码生成

如何将proto文件生成为Go语言的stub代码,官方提供了两个路径:

  • buf(新方式,配置简单,推荐)
  • protoc(经典方式,配置较为复杂)

具体的操作方法可以参考: https://github.com/grpc-ecosystem/grpc-gateway#usage

3. 业务实现

代码生成的只是一个stub,具体实现需要我们自己编码。上述方法生成的函数签名大致如下:

func Echo(ctx context.Context, request *proto.StringMessage) returns (response *proto.StringMessage, err error){
   
   
  // 自己实现的业务逻辑
}

关于其中的context与error,我在上一讲已经讲过大致的规范。而在gRPC-Gateway中怎么使用呢?我们会在具体示例中再去讲。

4. main函数框架

1~3步骤将一个RPC请求的开发过程串联了起来,作为web服务的高频迭代部分。

但如果要作为一个完整的服务,还需要包括基础的server启动代码,很少需要改动。我们接着看官方的示例代码:

package main

import (
  "context"
  "flag"
  "net/http"

  "github.com/golang/glog"
  "github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
  "google.golang.org/grpc"
  "google.golang.org/grpc/credentials/insecure"

  gw "github.com/yourorg/yourrepo/proto/gen/go/your/service/v1/your_service"  // Update
)

var (
  // command-line options:
  // gRPC server endpoint
  grpcServerEndpoint = flag.String("grpc-server-endpoint",  "localhost:9090", "gRPC server endpoint")
)

func run() error {
   
   
  ctx := context.Background()
  ctx, cancel := context.WithCancel(ctx)
  defer cancel()

  // Register gRPC server endpoint
  // Note: Make sure the gRPC server is running properly and accessible
  mux := runtime.NewServeMux()
  opts := []grpc.DialOption{
   
   grpc.WithTransportCredentials(insecure.NewCredentials())}
  err := gw.RegisterYourServiceHandlerFromEndpoint(ctx, mux,  *grpcServerEndpoint, opts)
  if err != nil {
   
   
    return err
  }

  // Start HTTP server (and proxy calls to gRPC server endpoint)
  return http.ListenAndServe(":8081", mux)
}

func main() {
   
   
  flag.Parse()
  defer glog.Flush()

  if err := run(); err != nil {
   
   
    glog.Fatal(err)
  }
}

我们要明确一点:这部分代码并没有包括gRPC服务的启动代码,它已经默认在grpcServerEndpoint这个地址+端口上启动了。如果没有进程隔离的强要求,我们可以在main函数中同时启动 gRPC server和gRPC-Gateway server。

gRPC-Gateway启动时有4个重要参数:

  • mux,多路复用,功能最为强大,可以添加各种自定义的拦截器等
  • grpcServerEndpoint,将HTTP转换成gRPC,再发给gRPC的地址
  • opts,服务的启动选项
  • :8081,启动地址

关于gRPC部分内容可以参考: https://grpc.io/docs/languages/go/quickstart/

参考示例

整套框架的完整示例可以参考这个文件 - https://github.com/Junedayday/micro_web_service/blob/master/main.go

结论

本篇重点是对gRPC-Gateway最基础的原理和使用进行了分析。

如果你能通过本篇文章,对这个方案有一个基本认识,那么接下来我会带你玩转这个框架。你也无需担心无法实践到日常项目中:gRPC-Gateway中的能力与gin等框架都是共通的,可以轻松地举一反三。

目录
相关文章
|
安全 Java 编译器
对比Java学习Go——基础理论篇
本章介绍了Java开发者学习Go语言的必要性。Go语言以简单、高效、并发为核心设计哲学,摒弃了传统的类继承和异常机制,采用组合、接口和多返回值错误处理,提升了代码清晰度与开发效率。Go直接编译为静态二进制文件,启动迅速、部署简便,其基于Goroutine和Channel的并发模型相较Java的线程与锁机制更轻量安全。此外,Go Modules简化了依赖管理,与Java的Maven/Gradle形成鲜明对比,提升了构建与部署效率。
743 1
|
11月前
|
存储 安全 Java
【Golang】(4)Go里面的指针如何?函数与方法怎么不一样?带你了解Go不同于其他高级语言的语法
结构体可以存储一组不同类型的数据,是一种符合类型。Go抛弃了类与继承,同时也抛弃了构造方法,刻意弱化了面向对象的功能,Go并非是一个传统OOP的语言,但是Go依旧有着OOP的影子,通过结构体和方法也可以模拟出一个类。
491 2
|
12月前
|
存储 Java Go
对比Java学习Go——函数、集合和OOP
Go语言的函数支持声明与调用,具备多返回值、命名返回值等特性,结合`func`关键字与类型后置语法,使函数定义简洁直观。函数可作为一等公民传递、赋值或作为参数,支持匿名函数与闭包。Go通过组合与接口实现面向对象编程,结构体定义数据,方法定义行为,接口实现多态,体现了Go语言的简洁与高效设计。
348 4
|
存储 Java 编译器
对比Java学习Go——程序结构与变量
本节对比了Java与Go语言的基础结构,包括“Hello, World!”程序、代码组织方式、入口函数定义、基本数据类型及变量声明方式。Java强调严格的面向对象结构,所有代码需置于类中,入口方法需严格符合`public static void main(String[] args)`格式;而Go语言结构更简洁,使用包和函数组织代码,入口函数为`func main()`。两种语言在变量声明、常量定义、类型系统等方面也存在显著差异,体现了各自的设计哲学。
406 0
|
Cloud Native Go API
Go:为云原生而生的高效语言
Go:为云原生而生的高效语言
699 0
|
Cloud Native Java Go
Go:为云原生而生的高效语言
Go:为云原生而生的高效语言
534 0
|
Cloud Native Java 中间件
Go:为云原生而生的高效语言
Go:为云原生而生的高效语言
570 0
|
Cloud Native Java Go
Go:为云原生而生的高效语言
Go:为云原生而生的高效语言
1626 0
|
存储 缓存 Linux
【实战指南】嵌入式RPC框架设计实践:六大核心类构建高效RPC框架
在先前的文章基础上,本文讨论如何通过分层封装提升一个针对嵌入式Linux的RPC框架的易用性。设计包括自动服务注册、高性能通信、泛型序列化和简洁API。框架分为6个关键类:BindingHub、SharedRingBuffer、Parcel、Binder、IBinder和BindInterface。BindingHub负责服务注册,SharedRingBuffer实现高效数据传输,Parcel处理序列化,而Binder和IBinder分别用于服务端和客户端交互。BindInterface提供简单的初始化接口,简化应用集成。测试案例展示了客户端和服务端的交互,验证了RPC功能的有效性。
984 102
|
Dubbo 网络协议 Java
RPC框架:一文带你搞懂RPC
这篇文章全面介绍了RPC(远程过程调用)的概念、原理和应用场景,解释了RPC如何工作以及为什么在分布式系统中广泛使用,并探讨了几种常用的RPC框架如Thrift、gRPC、Dubbo和Spring Cloud,同时详细阐述了RPC调用流程和实现透明化远程服务调用的关键技术,包括动态代理和消息的编码解码过程。
RPC框架:一文带你搞懂RPC