首页 > 其他分享 >go实现gPRC服务

go实现gPRC服务

时间:2024-03-14 11:33:06浏览次数:18  
标签:pb 服务 proto gRPC helloworld gPRC go

go实现gRPC服务

本文介绍如何使用go语言搭建简单的gRPC服务,内容比较基础,记录自己的踩坑过程。

1. 背景知识

gRPC是一种高效的远程过程调用(RPC)框架,用于不同计算机之间的通信和远程服务调用。gRPC的目标是让客户端向调用本地方法一样调用其他机器上的服务端应用程序提供的方法,能够帮助开发者更方便高效的构建分布式应用程序和服务。

protocol buffers是实现gRPC服务的基础,gRPC使用protocol buffers提供了一种简洁而强大的接口定义语言(IDL),gRPC通过.proto文件定义服务和消息类型,由于protocol buffers是一种用于序列化结构化数据的与语言无关的格式,因此,使用.proto文件定义的服务可以使用任意语言编写业务逻辑,从而实现该服务。

2. gRPC服务实现过程

  1. 实现一个gRPC服务主要包括以下步骤:

  2. 定义服务接口:定义服务,服务的方法,接收和返回的消息类型

  3. 编译proto文件:使用protoc编译器编译生成服务相关的go文件

  4. 开发业务逻辑:实现proto中定义的方法

  5. 创建gRPC服务:创建gRPC服务器,并绑定业务逻辑

3. 基础环境配置

3.1 go get配置代理

golang默认的代理 https://proxy.golang.org 在国内下载速度很慢,使用以下命令设置golang代理为 https://goproxy.cn

go env -w GOPROXY=https://goproxy.cn,direct

参考:Go 国内加速:Go 国内加速镜像 | Go 技术论坛 (learnku.com)

3.2. protoc安装

protoc是一款命令行工具,用于自动根据proto后缀的protobuf文件生成相关的go文件,从以下github仓库中下载可执行文件

Releases · protocolbuffers/protobuf · GitHub

img

将下载完成的可执行文件放入%GOPATH%/bin目录下(也可以放入其他目录并添加环境变量)

img

在命令行中运行 protoc --version 成功显示版本号则说明安装成功

img

3.3 protocol compiler plugin安装

使用一下命令安装相关的插件,go install命令会下载依赖源码并进行编译,编译完成的可执行文件位于GOPATH下。

$ go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
$ go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest

安装完成后,能够在%GOPATH%/bin目录下找到刚刚安装完成的插件可执行文件

img

后续的自动生成proto代码时,会调用到当前目录下的可执行文件。一般go安装时会自动将GOPATH添加到环境变量,如果没有,则需要手动添加。

img

参考:Quick start | Go | gRPC

2. 定义服务

2.1 编写proto代码

定义服务接口、接收和响应的消息类型均在.proto文件中定义,以下代码中,定义了一个服务Greeter,服务中定义了一个rpc方法SayHello,该方法接收一个HelloRequest类型的消息,并返回一个HelloReply类型的响应。

syntax = "proto3";    // 指定protoc版本

option go_package = "gRPC_demo/protos/helloworld";   // 指定自动生成go代码时的包名

package helloworld;   // 指定包名,防止命名冲突

// 定义Greeter服务
service Greeter {
  // 定义SayHello方法
  rpc SayHello (HelloRequest) returns (HelloReply) {}
}

// 定义HelloRequest消息,消息中包括一个string类型的name字段
message HelloRequest {
  string name = 1;    // 1代表该字段的排序编号,如该消息还有第2个字段pass,则定义为 string pass = 2;
}

// 定义HelloReply消息,消息中包括一个string类型的message字段
message HelloReply {
  string message = 1;
}
}

2.2. 编译.proto文件

protocol buffers是一种与语言无关的接口定义语言,在使用不同的语言实现时,都可以通过对应的插件将.proto定义代码编译成对应语言的代码。为了适应开发过程中.proto文件的频繁变更,可以将编译命令写入gen.bat文件,方便后续发生变更时快速重新生成代码,注意将.proto文件和.bat文件放在同一层目录,并cd到bat文件所在目录执行bat文件,防止代码生成到其他目录造成目录结构混乱

// gen.bat
protoc --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go grpc_opt=paths=source_relative .helloworld.proto

执行bat文件后,将自动生成了两个go文件,**.grpc.pb.go**.pb.go,它们包含的内容如下:

  1. **.grpc.pb.go:该文件包含gRPC服务端和客户端的代码框架,后续将基于该框架编写服务的业务逻辑,实现.proto文件中定义的服务。

  2. **.pb.go: 该文件保险消息类型的定义和相关的序列化/反序列化方法,通信过程中,将调用这些方法对消息进行处理。

img

2.3 同步依赖

生成的代码由于依赖未同步,可能存在大范围飘红,在命令行执行go mod tidy自动同步依赖即可

img

3. 实现业务逻辑

打开helloworld_grpc.pb.go,可以看到SayHello方法定义如下,会返回一个SayHello方法没有实现的错误,我们可以在SayHello中编写业务逻辑,但是由于helloworld_grpc.pb.go是自动生成的代码,在后续发生变更时,重新编译会覆盖我们编写的业务逻辑代码,因此强烈不建议在helloworld_grpc.pb.go中直接编写业务逻辑代码。

func (UnimplementedGreeterServer) SayHello(context.Context, *HelloRequest) (*HelloReply, error) {
	return nil, status.Errorf(codes.Unimplemented, "method SayHello not implemented")
} nil
}

推荐的方法是在项目根目录下创建一个services/helloworld目录,在目录中创建一个helloworld.go,新建一个结构体Server,继承UnimplementedGreeterServer结构体中的所有方法,并重写UnimplementedGreeterServer.SayHello方法,实现业务逻辑。

package helloworld

import (
    "context"
    pb "gRPC_demo/protos/helloworld"
    "log"
)

// 创建Server结构体,将SayHello方法注册为它的成员函数
type Server struct {
    pb.UnimplementedGreeterServer    // Server结构体继承了pb.UnimplementedGreeterServer结构体的所有方法
}

// 重写pb.GreeterServer.SayHello方法,实现业务逻辑
func (s *Server) SayHello(ctx context.Context, hellorequest *pb.HelloRequest) (*pb.HelloReply, error) {
    log.Printf("Received message from %v", hellorequest.GetName())
    return &pb.HelloReply{Message: "Hello " + hellorequest.GetName()}, nil
}

项目目录结构如下:
img

4. 编写main函数

在项目根目录编写以下main函数,新建一个gRPC服务,将gRPC服务和我们实现的Server结构体中的业务逻辑绑定到Greeter服务上,并开启监听。

package main

import (
    "fmt"
    pb "gRPC_demo/protos/helloworld"
    "gRPC_demo/services/helloworld"
    "log"
    "net"
    "google.golang.org/grpc"
)

func main() {
    // 绑定地址和端口
    grpcAddress := "0.0.0.0"
    grpcPort := 8090
    lis, err := net.Listen("tcp", fmt.Sprintf("%s:%d", grpcAddress, grpcPort))
    if err != nil {
        log.Fatalf("failed to listen: %v", err)
    }
    // 初始化gRPC服务
    s := grpc.NewServer()
    // 将gRPC服务和自定义的业务逻辑注册到Greeter服务中
    pb.RegisterGreeterServer(s, &helloworld.Server{})
    log.Printf("serving gRPC on %v", lis.Addr())
    // 将gRPC服务绑定在上面创建的tcp端口上,并开启监听
    err = s.Serve(lis)
    if err != nil {
        log.Fatalf("启动gRPC服务失败(%v)", err)
    }
}

5. 运行gRPC服务

使用一下命令启动gRPC服务

go run main.go

img

7. 调用测试

将proto文件导入apifox后调用SayHello方法

img

服务端也打印了调用的日志信息
img

以上是go实现gRPC服务的简单示例,如有疏漏,欢迎评论区指正。

下节预告: 下一节将讲解如何使用grpc-gateway实现http协议访问grpc服务。

标签:pb,服务,proto,gRPC,helloworld,gPRC,go
From: https://www.cnblogs.com/bypass/p/18072434

相关文章

  • 如何在Nginx服务器上配置访问静态文件目录并提供文件下载功能
    引言在搭建网站的过程中,我们经常需要让访客通过URL直接访问或下载存储在服务器特定目录下的静态文件。本文将详细介绍如何在Nginx服务器环境中配置一个名为"download"的文件目录,以便用户能够通过浏览器访问并下载其中的手册和其他文档。1.目录结构与权限设置首先,请确保您的Ngi......
  • MongoDB数据库之主从复制配置实战【转】
    一、MongoDB介绍 1.1MongoDB简介MongoDB是一个开源的文档数据库,使用JSON格式存储和操作数据,具有高度灵活性和可扩展性。MongoDB的数据模型是面向文档的,这意味着它可以存储各种类型的数据,如数组、嵌套文档和二进制数据。MongoDB是一种NoSQL数据库,不需要使用传统的表格结构。M......
  • python基于flask房产中介房屋供求系统django毕业设计项目lw附源码
    本设计要设计一个简单的网页,在研究的过程中具体有以下5个步骤:下面简要分析房产中介系统的业务:(1)注册、登录:注册普通账号登录。(2)用户个人信息修改:登录后可以修改用户的基本信息,也可以退出。(3)用户留言管理:用户填写留言的主题、联系人、电话、邮箱、留言内容。 (4)房屋......
  • django-crontab项目源码阅读
    文章同步首发个人公众号菩提老鹰,欢迎大家订阅一、知识点这边源码阅读分析,可以获得如下知识点1、django-crontab的原理2、django-crontab任务ID如何生产3、django-crontab使用限制很早之前写过关于django-crontab的文章,比如django任务管理之crontabDjango实现c......
  • docker-compose部署prometheus+grafana进行服务器监控
    1、创建prometheus【prometheus.yml】配置global:scrape_interval:15sevaluation_interval:15sscrape_configs:-job_name:'prometheus'static_configs:-targets:['192.168.2.216:9090']ViewCode2、创建【docker-com......
  • 高颜值、免服务费、安全的自助发卡/数字商品寄售网站(idatariver.com)
    iDataRiver平台https://idatariver.com/zh-cn可支持商户无门槛入驻,使用usdt结算,可上架数字商品与API项目,本文介绍其数字商品的上架流程。感兴趣可直接前往官方文档术语解释数字商品数字商品是指可以自动交付的虚拟商品,例如:礼品卡、会员卡、授权/兑换码等等。数据项在实际......
  • 微服务,从放弃到入门
    微服务,从放弃到入门在软件开发的世界里,微服务已经逐渐成为一个热门的话题。它代表了一种将大型、复杂的应用程序分解为一系列小型、独立的服务的方法,每个服务都运行在自己的进程中,通过轻量级通信机制进行通信。尽管微服务架构带来了许多好处,但在学习和实践的过程中,我也曾经......
  • golang内存管理
     解释定义:mheap:用于管理整个堆内存,mheap管理多个arena,arena管理多个span,一个span由多个page组成,一个arena有8192个page,page由内存块组成mspan:一个span对应一个mspanmcentral:mheap里有一个全局的mspan管理中心包含mcentral数组,0-135mcentral,一个mcentral(管理对应类型的spa......
  • Godot 4.1 学习笔记
    godot%启用场景唯一名称这个怎么用的,给我举点例子。onreadyvarsect_rect=$"%SectRect这个节点可以在场景中的任意位置通过在节点路中为其加上”%”前缀来访问。点击禁用。什么“场景中的任意位置通过在节点路中”???好的,用更具体的例子来说明如何在Godot中使用%前缀......
  • 使用Golong轻松实现JWT身份验证
    使用Golong轻松实现JWT身份验证JSON Web Tokens (JWT)是一种流行的安全方法,用于在两个方之间表示声明。在Web应用程序领域,它们通常用作从客户端向服务器传输身份信息(声明)的方式。本教程将引导您逐步实现Go应用程序中的JWT身份验证过程。什么是JWT?JSONWebToken(JWT......