【GO开发工程师】grpc进阶#golang

【GO开发工程师】grpc进阶#golang

在这里插入图片描述

推荐个人主页:席万里的个人空间

文章目录

  • 【GO开发工程师】grpc进阶#golang
    • 1、protobuf
    • 2、grpc
      • 2.1、gRPC 的 Metadata机制
      • 2.2、grpc拦截器

1、protobuf

syntax = "proto3"; // 指定使用的 protobuf 版本为 proto3
import "google/protobuf/timestamp.proto"; // 导入 Google 提供的时间戳类型定义
option go_package = ".;proto_bak"; // 生成的 Go 语言代码的包名设定为当前目录下的 proto_bak

service Greeter { // 定义一个名为 Greeter 的服务
    rpc SayHello (HelloRequest) returns (HelloReply); // 在 Greeter 服务中定义一个远程过程调用 SayHello,接收 HelloRequest 参数,返回 HelloReply 结果
}

enum Gender { // 定义一个枚举类型 Gender
    MALE = 0; // 枚举值 MALE,值为 0
    FEMALE = 1; // 枚举值 FEMALE,值为 1
}

message HelloRequest { // 定义消息类型 HelloRequest
    string name = 1; // 姓名字段,用于存储姓名信息,字段标签为 1
    string url = 2; // URL 字段,用于存储 URL 信息,字段标签为 2
    Gender g = 3; // Gender 类型的字段,用于存储性别信息,字段标签为 3
    map<string, string> mp = 4; // 字符串键值对映射字段,用于存储键值对信息,字段标签为 4
    google.protobuf.Timestamp addTime = 5; // 时间戳字段,用于存储添加时间信息,字段标签为 5,使用了导入的时间戳类型定义
}

message HelloReply { // 定义消息类型 HelloReply
    string message = 1; // 消息字段,用于存储消息内容,字段标签为 1
}

2、grpc

2.1、gRPC 的 Metadata机制

gRPC 的 Metadata 机制是一种用于在 gRPC 请求和响应中传递元数据的机制。元数据是键值对的集合,可以包含请求的附加信息,比如身份验证凭据、请求标识符、客户端信息等。

在 gRPC 中,元数据可以分为两类:

  1. 请求元数据(Request Metadata):这些是客户端在发起 gRPC 请求时发送的元数据。它们可以用于传递关于请求的附加信息,比如身份验证凭据、请求标识符、客户端信息等。

  2. 响应元数据(Response Metadata):这些是服务端在响应 gRPC 请求时发送的元数据。它们可以用于传递关于响应的附加信息,比如服务端处理结果、附加的状态信息等。

元数据以键值对的形式存在,键是字符串,值可以是任意的序列化数据。在 gRPC 中,元数据通常使用 HTTP/2 格式编码,并在 HTTP/2 标头中传输。

Metadata 机制的使用使得 gRPC 具有灵活的扩展性和自定义能力。开发者可以根据自己的需求,在请求和响应中传递任意类型的元数据,以实现各种功能,比如身份验证、流量控制、跟踪、日志记录等。

2.2、grpc拦截器

我想在每一个 RPC 方法的前面或后面做某些操作,我想针对某个业务模块的 RPC 方法进行统一的特殊处理,我想对 RPC 方法进行鉴权校验,我想对 RPC 方法进行上下文的超时控制,我想对每个 RPC 方法的请求都做日志记录,怎么做呢?

gRPC 的拦截器(Interceptors)是一种强大的功能,它允许在 gRPC 请求处理过程中注入自定义逻辑,类似于中间件。拦截器可以用于实现各种功能,如身份验证、日志记录、性能监控、流量控制等。在 gRPC 中,拦截器是通过使用 gRPC 的拦截器接口来实现的。

以下是一些常见的 gRPC 拦截器:

  1. 认证拦截器(Authentication Interceptor):用于对 gRPC 请求进行身份验证,以确保请求的安全性和合法性。

  2. 授权拦截器(Authorization Interceptor):用于在请求处理之前验证客户端是否具有执行请求操作的权限。

  3. 日志记录拦截器(Logging Interceptor):用于记录请求和响应的日志,以便进行故障排查、审计和性能分析。

  4. 性能监控拦截器(Performance Monitoring Interceptor):用于监控 gRPC 服务的性能指标,如请求处理时间、请求速率等。

  5. 流量控制拦截器(Traffic Control Interceptor):用于限制客户端请求的速率或配额,以确保服务端不会被过多的请求压力影响。

  6. 异常处理拦截器(Exception Handling Interceptor):用于捕获并处理 gRPC 服务中的异常情况,以提供更好的错误处理和用户体验。

有关go-grpc-middleware的使用:go-grpc-middleware下载地址

MD和拦截器案例

client.go

package main

import (
	"OldPackageTest/grpc_test/proto" // 导入 protobuf 自动生成的代码包
	"context"                        // 导入 context 包
	"fmt"                            // 导入 fmt 包
	"google.golang.org/grpc"         // 导入 gRPC 包
)

// customCredential 是一个自定义的 gRPC 凭据类型
type customCredential struct{}

// GetRequestMetadata 实现了凭据接口中的 GetRequestMetadata 方法,
// 用于返回请求所需的元数据。
func (c customCredential) GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error) {
	// 返回一个包含应用程序 ID 和密钥的元数据
	return map[string]string{
		"appid":  "101010",
		"appkey": "i am key",
	}, nil
}

// RequireTransportSecurity 实现了凭据接口中的 RequireTransportSecurity 方法,
// 返回该凭据是否需要传输安全性。
func (c customCredential) RequireTransportSecurity() bool {
	return false // 此示例中不需要传输安全性
}

func main() {
	// 创建 gRPC 客户端连接选项数组
	var opts []grpc.DialOption
	// 添加使用不安全连接的 Dial 选项
	opts = append(opts, grpc.WithInsecure())
	// 添加使用自定义凭据的 Dial 选项
	opts = append(opts, grpc.WithPerRPCCredentials(customCredential{}))
	// 连接到 gRPC 服务器
	conn, err := grpc.Dial("127.0.0.1:50051", opts...)
	if err != nil {
		panic(err)
	}
	defer conn.Close() // 延迟关闭连接

	// 创建一个 GreeterClient 实例
	c := proto.NewGreeterClient(conn)
	// 向服务器发送 SayHello 请求,并传递 HelloRequest 参数
	r, err := c.SayHello(context.Background(), &proto.HelloRequest{Name: "bobby"})
	if err != nil {
		panic(err)
	}
	fmt.Println(r.Message) // 打印服务器返回的消息
}

helloworld.proto

syntax = "proto3";
option go_package = ".;proto";
service Greeter {
    rpc SayHello (HelloRequest) returns (HelloReply);
}
//将 sessionid放入 放入cookie中 http协议
//这个就好比文档,表单验证
message HelloRequest {
    string name = 1;
}

message HelloReply {
    string message = 1;
}
//go语言中是生成一个文件, 也就只有python会生成两个文件

使用protoc生成go文件:

protoc --go_out=./ *.proto

server.go

package main

import (
	"context"
	"fmt"
	"google.golang.org/grpc/codes" // 导入 gRPC 错误码包
	"google.golang.org/grpc/metadata" // 导入 gRPC 元数据包
	"google.golang.org/grpc/status" // 导入 gRPC 状态包
	"net" // 导入网络包

	"google.golang.org/grpc" // 导入 gRPC 包

	"OldPackageTest/grpc_test/proto" // 导入 protobuf 自动生成的代码包
)

// Server 定义 gRPC 服务端结构体
type Server struct{}

// SayHello 实现了 Greeter 服务中的 SayHello 方法
func (s *Server) SayHello(ctx context.Context, request *proto.HelloRequest) (*proto.HelloReply,
	error) {
	// 根据请求参数构造响应消息
	return &proto.HelloReply{
		Message: "hello " + request.Name,
	}, nil
}

func main() {
	// 定义拦截器函数
	interceptor := func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) {
		fmt.Println("接收到了一个新的请求") // 打印日志,表示接收到新的请求
		md, ok := metadata.FromIncomingContext(ctx) // 从上下文中获取请求的元数据
		fmt.Println(md)
		if !ok {
			// 如果无法获取元数据,则返回未认证错误
			return resp, status.Error(codes.Unauthenticated, "无token认证信息")
		}

		var (
			appid  string // 定义应用程序 ID
			appkey string // 定义应用程序密钥
		)

		// 从元数据中提取应用程序 ID 和密钥
		if va1, ok := md["appid"]; ok {
			appid = va1[0]
		}

		if va1, ok := md["appkey"]; ok {
			appkey = va1[0]
		}

		// 检查应用程序 ID 和密钥是否有效,若无效则返回未认证错误
		if appid != "101010" || appkey != "i am key" {
			return resp, status.Error(codes.Unauthenticated, "无token认证信息")
		}

		// 调用 gRPC 处理函数处理请求
		res, err := handler(ctx, req)
		fmt.Println("请求已经完成") // 打印日志,表示请求处理完成
		return res, err
	}

	// 创建 gRPC 服务器,并设置拦截器
	opt := grpc.UnaryInterceptor(interceptor)
	g := grpc.NewServer(opt)

	// 在 gRPC 服务器上注册 Greeter 服务
	proto.RegisterGreeterServer(g, &Server{})

	// 监听指定地址和端口
	lis, err := net.Listen("tcp", "0.0.0.0:50051")
	if err != nil {
		panic("failed to listen:" + err.Error())
	}

	// 启动 gRPC 服务器
	err = g.Serve(lis)
	if err != nil {
		panic("failed to start grpc:" + err.Error())
	}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/414790.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

配置前端项目到 github-pages

Quickstart for GitHub Pages - GitHub Docs

云计算新宠:探索Apache Doris的云原生策略

文章目录 Apache Doris 特性极简架构高效自运维高并发场景支持MPP 执行引擎明细与聚合模型的统一便捷数据接入 Apache Doris 极速 1.0 时代极速列式内存布局向量化的计算框架Cache 亲和度虚函数调用SIMD 指令集 稳定多源 关于 Apache Doris 开源社区基于云原生向量数据库Milvus…

大模型(LLM)的token学习记录-I

文章目录 基本概念什么是token?如何理解token的长度&#xff1f;使用openai tokenizer 观察token的相关信息open ai的模型 token的特点token如何映射到数值&#xff1f;token级操作&#xff1a;精确地操作文本token 设计的局限性 tokenizationtoken 数量对LLM 的影响训练模型参…

设计模式七:责任链模式

文章目录 1、责任链模式2、spring中的责任链模式Spring InterceptorServlet FilterNetty 1、责任链模式 责任链模式为请求创建了一个接收者对象的链&#xff0c;在这种模式下&#xff0c;通常每个节点都包含对另一个节点者的引用。每个节点针对请求&#xff0c;处理自己感兴趣…

基于springboot+vue的大学城水电管理系统(前后端分离)

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战&#xff0c;欢迎高校老师\讲师\同行交流合作 ​主要内容&#xff1a;毕业设计(Javaweb项目|小程序|Pyt…

特征融合篇 | YOLOv8 引入通用高效层聚合网络 GELAN | YOLOv9 新模块

今天的深度学习方法专注于如何设计最合适的目标函数,以使模型的预测结果最接近真实情况。同时,必须设计一个合适的架构,以便为预测提供足够的信息。现有方法忽视了一个事实,即当输入数据经过逐层特征提取和空间转换时,会丢失大量信息。本文将深入探讨数据通过深度网络传输…

UE 贴地绘制/日历/鼠标光标滚轮位置缩放图片/UMG滚动数据从前后添加新UI/多图片批量下载 收费项目源码资源

基本里面的内容本人CSDN发的都有现成代码.里面大部分是功能实现思路.这里面是把这几个功能合成了一个完整5.1项目源码.拿到即用.收费项目源码资源. 1.贴地绘制 2.日历 3.鼠标光标滚轮位置缩放图片 \ 4.UMG滚动数据从前后添加新UI思路 5.多图片批量下载 这是整合的懒人源码包收…

Rocky Linux 运维工具yum

一、yum的简介 ​​yum​是用于在基于RPM包管理系统的包管理工具。用户可以通过 ​yum​来搜索、安装、更新和删除软件包&#xff0c;自动处理依赖关系&#xff0c;方便快捷地管理系统上的软件。 二、yum的参数说明 1、install 用于在系统的上安装一个或多个软件包 2、seach 用…

【HarmonyOS】鸿蒙开发之Video组件——第3.7章

Video组件内VideoOptions属性简介 src&#xff1a;设置视频地址。currentProgressRate&#xff1a;设置视频播放倍速&#xff0c;参数说明如下&#xff1a; number|string&#xff1a;只支持 0.75 &#xff0c; 1.0 &#xff0c; 1.25 &#xff0c; 1.75 &#xff0c; 2.0 。P…

JavaEE进阶(7)Spring Boot 日志(概述、用途、使用:打印日志,框架介绍,SLF4J 框架介绍、更简单的日志输出)

接上次博客&#xff1a;JavaEE进阶&#xff08;6&#xff09;SpringBoot 配置文件&#xff08;作用、格式、properties配置文件说明、yml配置文件说明、验证码案例&#xff09;-CSDN博客 目录 日志概述 日志的用途 日志使用 打印日志 在程序中获取日志对象 使用日志对象…

androidble蓝牙开发,12道Android高级面试题

Java面试题 1.GC机制 垃圾回收需要完成两件事&#xff1a;找到垃圾&#xff0c;回收垃圾。 找到垃圾一般的话有两种方法&#xff1a; 引用计数法&#xff1a; 当一个对象被引用时&#xff0c;它的引用计数器会加一&#xff0c;垃圾回收时会清理掉引用计数为0的对象。但这种方…

论文笔记:A survey on zero knowledge range proofs and applications

https://link.springer.com/article/10.1007/s42452-019-0989-z 描述了构建零知识区间证明&#xff08;ZKRP&#xff09;的不同策略&#xff0c;例如2001年Boudot提出的方案&#xff1b;2008年Camenisch等人提出的方案&#xff1b;以及2017年提出的Bulletproofs。 Introducti…

SpringBoot案例(黑马学习笔记)

这个案例呢&#xff0c;就是Tlias智能学习辅助系统。 参考接口文档完成后端功能的开 发&#xff0c;然后结合前端工程进行联调测试即可。 完成后的成品效果展示&#xff1a; 准备工作 需求&环境搭建 需求说明 部门管理 部门管理功能开发包括&#xff1a; ● 查询部门列…

【JavaSE】实用类——枚举类型、包装类、数学类

目录 Java API枚举优势代码示例 包装类作用包装类和基本数据类型的对应关系包装类的构造方法包装类的常用方法装箱和拆箱 留一个问题大家猜猜看包装类的特点 Math类Random类代码示例 Java API Java API(Java Application Programming Interface) 即Java应用程序编程接口&#…

设备管理系统解决方案

软件资料获取&#xff1a;软件项目开发全套文档下载_软件项目文档-CSDN博客 1.系统概述 1.1.需求描述 建立设备信息库&#xff0c;对设备相关档案的登录、整理。通过建立完善的设备档案&#xff0c;将设备的各类原始信息进行信息化管理&#xff0c;使设备档案查询工作方便快…

NoReturn与None的区别

问题来源&#xff1a; class xx:def __init__(self) -> NoReturn:passpycharm编译器提示如下问题&#xff1a; init should return None 根因探索&#xff1a; None 是Python的一个特殊的数据类型&#xff0c;用于表示空值或者没有值。当一个函数没有显式返回值时&#x…

模型预测控制MPC算法的讲解-案例(C语言代码)

目录 一、模型预测控制MPC的基本原理 1.1 建立模型 1.2 设定目标和约束条件 1.3 求解优化问题 1.4 应用控制输入 1.5 重复优化 二、模型预测控制MPC的特点 三、应用场景 四、应用案例 一个MPC算法的简化版框架&#xff1a; 4.1 案例系统模型 4.2 控制目标和当前状态…

【JavaWeb】

Javaweb 数据库相关概念MySQL数据库MySQL数据模型SQLDDL--操作数据库图形化客户端工具DML--操作数据DQL数据库约束 数据库设计多表查询事务 数据库相关概念 数据库 存储数据的仓库&#xff0c;数据是有组织的进行存储 英文&#xff1a;DataBase&#xff0c;简称DB 数据库管理系…

自然语言:信息抽取技术在CRM系统中的应用与成效

一、引言 在当今快速变化的商业环境中&#xff0c;客户关系管理&#xff08;CRM&#xff09;已成为企业成功的关键因素。CRM系统的核心在于有效地管理客户信息&#xff0c;跟踪与客户的每一次互动&#xff0c;以及深入分析这些数据以提升客户满意度和忠诚度。在我最近参与的一个…

SpringBoot+Vue全栈开发-刘老师教编程(b站)(一)

课堂内容 Java EE企业级框架&#xff1a;SpringBootMyBatisPlusWeb前端核心框架&#xff1a;VueElementUI公共云部署&#xff1a;前后端项目集成打包与部署 B/S(Browser/Server):浏览器/服务器架构模式 C/S(Client/Server):客户端/服务器架构模式 Maven是一个项目管理工具&…