最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Go?gRPC服務(wù)進(jìn)階middleware使用教程

 更新時間:2022年06月16日 09:35:32   作者:煙花易冷人憔悴  
這篇文章主要為大家介紹了Go?gRPC服務(wù)進(jìn)階middleware的使用教程,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

前言

之前介紹了gRPC中TLS認(rèn)證和自定義方法認(rèn)證,最后還簡單介紹了gRPC攔截器的使用。gRPC自身只能設(shè)置一個攔截器,所有邏輯都寫一起會比較亂。本篇簡單介紹go-grpc-middleware的使用,包括grpc_zap、grpc_auth和grpc_recovery。

go-grpc-middleware簡介

go-grpc-middleware封裝了認(rèn)證(auth), 日志( logging), 消息(message), 驗(yàn)證(validation), 重試(retries) 和監(jiān)控(retries)等攔截器。

安裝

 go get github.com/grpc-ecosystem/go-grpc-middleware

使用

import "github.com/grpc-ecosystem/go-grpc-middleware"
myServer := grpc.NewServer(
    grpc.StreamInterceptor(grpc_middleware.ChainStreamServer(
        grpc_ctxtags.StreamServerInterceptor(),
        grpc_opentracing.StreamServerInterceptor(),
        grpc_prometheus.StreamServerInterceptor,
        grpc_zap.StreamServerInterceptor(zapLogger),
        grpc_auth.StreamServerInterceptor(myAuthFunction),
        grpc_recovery.StreamServerInterceptor(),
    )),
    grpc.UnaryInterceptor(grpc_middleware.ChainUnaryServer(
        grpc_ctxtags.UnaryServerInterceptor(),
        grpc_opentracing.UnaryServerInterceptor(),
        grpc_prometheus.UnaryServerInterceptor,
        grpc_zap.UnaryServerInterceptor(zapLogger),
        grpc_auth.UnaryServerInterceptor(myAuthFunction),
        grpc_recovery.UnaryServerInterceptor(),
    )),
)

grpc.StreamInterceptor中添加流式RPC的攔截器。

grpc.UnaryInterceptor中添加簡單RPC的攔截器。

grpc_zap日志記錄

1.創(chuàng)建zap.Logger實(shí)例

func ZapInterceptor() *zap.Logger {
	logger, err := zap.NewDevelopment()
	if err != nil {
		log.Fatalf("failed to initialize zap logger: %v", err)
	}
	grpc_zap.ReplaceGrpcLogger(logger)
	return logger
}

2.把zap攔截器添加到服務(wù)端

grpcServer := grpc.NewServer(
	grpc.StreamInterceptor(grpc_middleware.ChainStreamServer(
			grpc_zap.StreamServerInterceptor(zap.ZapInterceptor()),
		)),
		grpc.UnaryInterceptor(grpc_middleware.ChainUnaryServer(
			grpc_zap.UnaryServerInterceptor(zap.ZapInterceptor()),
		)),
	)

3.日志分析

各個字段代表的意思如下:

{
	  "level": "info",						// string  zap log levels
	  "msg": "finished unary call",					// string  log message
	  "grpc.code": "OK",						// string  grpc status code
	  "grpc.method": "Ping",					/ string  method name
	  "grpc.service": "mwitkow.testproto.TestService",              // string  full name of the called service
	  "grpc.start_time": "2006-01-02T15:04:05Z07:00",               // string  RFC3339 representation of the start time
	  "grpc.request.deadline": "2006-01-02T15:04:05Z07:00",         // string  RFC3339 deadline of the current request if supplied
	  "grpc.request.value": "something",				// string  value on the request
	  "grpc.time_ms": 1.345,					// float32 run time of the call in ms
	  "peer.address": {
	    "IP": "127.0.0.1",						// string  IP address of calling party
	    "Port": 60216,						// int     port call is coming in on
	    "Zone": ""							// string  peer zone for caller
	  },
	  "span.kind": "server",					// string  client | server
	  "system": "grpc",						// string
	  "custom_field": "custom_value",				// string  user defined field
	  "custom_tags.int": 1337,					// int     user defined tag on the ctx
	  "custom_tags.string": "something"				// string  user defined tag on the ctx
}

4.把日志寫到文件中

上面日志是在控制臺輸出的,現(xiàn)在我們把日志寫到文件中,修改ZapInterceptor方法。

import (
	grpc_zap "github.com/grpc-ecosystem/go-grpc-middleware/logging/zap"
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
	"gopkg.in/natefinch/lumberjack.v2"
)
// ZapInterceptor 返回zap.logger實(shí)例(把日志寫到文件中)
func ZapInterceptor() *zap.Logger {
	w := zapcore.AddSync(&lumberjack.Logger{
		Filename:  "log/debug.log",
		MaxSize:   1024, //MB
		LocalTime: true,
	})
	config := zap.NewProductionEncoderConfig()
	config.EncodeTime = zapcore.ISO8601TimeEncoder
	core := zapcore.NewCore(
		zapcore.NewJSONEncoder(config),
		w,
		zap.NewAtomicLevel(),
	)
	logger := zap.New(core, zap.AddCaller(), zap.AddCallerSkip(1))
	grpc_zap.ReplaceGrpcLogger(logger)
	return logger
}

grpc_auth認(rèn)證

go-grpc-middleware中的grpc_auth默認(rèn)使用authorization認(rèn)證方式,以authorization為頭部,包括basic, bearer形式等。下面介紹bearer token認(rèn)證。bearer允許使用access key(如JSON Web Token (JWT))進(jìn)行訪問。

1.新建grpc_auth服務(wù)端攔截器

// TokenInfo 用戶信息
type TokenInfo struct {
	ID    string
	Roles []string
}
// AuthInterceptor 認(rèn)證攔截器,對以authorization為頭部,形式為`bearer token`的Token進(jìn)行驗(yàn)證
func AuthInterceptor(ctx context.Context) (context.Context, error) {
	token, err := grpc_auth.AuthFromMD(ctx, "bearer")
	if err != nil {
		return nil, err
	}
	tokenInfo, err := parseToken(token)
	if err != nil {
		return nil, grpc.Errorf(codes.Unauthenticated, " %v", err)
	}
	//使用context.WithValue添加了值后,可以用Value(key)方法獲取值
	newCtx := context.WithValue(ctx, tokenInfo.ID, tokenInfo)
	//log.Println(newCtx.Value(tokenInfo.ID))
	return newCtx, nil
}
//解析token,并進(jìn)行驗(yàn)證
func parseToken(token string) (TokenInfo, error) {
	var tokenInfo TokenInfo
	if token == "grpc.auth.token" {
		tokenInfo.ID = "1"
		tokenInfo.Roles = []string{"admin"}
		return tokenInfo, nil
	}
	return tokenInfo, errors.New("Token無效: bearer " + token)
}
//從token中獲取用戶唯一標(biāo)識
func userClaimFromToken(tokenInfo TokenInfo) string {
	return tokenInfo.ID
}

代碼中的對token進(jìn)行簡單驗(yàn)證并返回模擬數(shù)據(jù)。

2.客戶端請求添加bearer token

實(shí)現(xiàn)和上篇的自定義認(rèn)證方法大同小異。gRPC 中默認(rèn)定義了 PerRPCCredentials,是提供用于自定義認(rèn)證的接口,它的作用是將所需的安全認(rèn)證信息添加到每個RPC方法的上下文中。其包含 2 個方法:

GetRequestMetadata:獲取當(dāng)前請求認(rèn)證所需的元數(shù)據(jù)

RequireTransportSecurity:是否需要基于 TLS 認(rèn)證進(jìn)行安全傳輸

接下來我們實(shí)現(xiàn)這兩個方法

// Token token認(rèn)證
type Token struct {
	Value string
}
const headerAuthorize string = "authorization"
// GetRequestMetadata 獲取當(dāng)前請求認(rèn)證所需的元數(shù)據(jù)
func (t *Token) GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error) {
	return map[string]string{headerAuthorize: t.Value}, nil
}
// RequireTransportSecurity 是否需要基于 TLS 認(rèn)證進(jìn)行安全傳輸
func (t *Token) RequireTransportSecurity() bool {
	return true
}

注意:這里要以authorization為頭部,和服務(wù)端對應(yīng)。

發(fā)送請求時添加token

//從輸入的證書文件中為客戶端構(gòu)造TLS憑證
	creds, err := credentials.NewClientTLSFromFile("../tls/server.pem", "go-grpc-example")
	if err != nil {
		log.Fatalf("Failed to create TLS credentials %v", err)
	}
	//構(gòu)建Token
	token := auth.Token{
		Value: "bearer grpc.auth.token",
	}
	// 連接服務(wù)器
	conn, err := grpc.Dial(Address, grpc.WithTransportCredentials(creds), grpc.WithPerRPCCredentials(&token))

注意:Token中的Value的形式要以bearer token值形式。因?yàn)槲覀兎?wù)端使用了bearer token驗(yàn)證方式。

3.把grpc_auth攔截器添加到服務(wù)端

grpcServer := grpc.NewServer(cred.TLSInterceptor(),
	grpc.StreamInterceptor(grpc_middleware.ChainStreamServer(
	        grpc_auth.StreamServerInterceptor(auth.AuthInterceptor),
			grpc_zap.StreamServerInterceptor(zap.ZapInterceptor()),
		)),
		grpc.UnaryInterceptor(grpc_middleware.ChainUnaryServer(
		    grpc_auth.UnaryServerInterceptor(auth.AuthInterceptor),
			grpc_zap.UnaryServerInterceptor(zap.ZapInterceptor()),
		)),
	)

寫到這里,服務(wù)端都會攔截請求并進(jìn)行bearer token驗(yàn)證,使用bearer token是規(guī)范了與HTTP請求的對接,畢竟gRPC也可以同時支持HTTP請求。

grpc_recovery恢復(fù)

把gRPC中的panic轉(zhuǎn)成error,從而恢復(fù)程序。

1.直接把grpc_recovery攔截器添加到服務(wù)端

最簡單使用方式

grpcServer := grpc.NewServer(cred.TLSInterceptor(),
	grpc.StreamInterceptor(grpc_middleware.ChainStreamServer(
	        grpc_auth.StreamServerInterceptor(auth.AuthInterceptor),
			grpc_zap.StreamServerInterceptor(zap.ZapInterceptor()),
			grpc_recovery.StreamServerInterceptor,
		)),
		grpc.UnaryInterceptor(grpc_middleware.ChainUnaryServer(
		    grpc_auth.UnaryServerInterceptor(auth.AuthInterceptor),
			grpc_zap.UnaryServerInterceptor(zap.ZapInterceptor()),
            grpc_recovery.UnaryServerInterceptor(),
		)),
	)

2.自定義錯誤返回

當(dāng)panic時候,自定義錯誤碼并返回。

// RecoveryInterceptor panic時返回Unknown錯誤嗎
func RecoveryInterceptor() grpc_recovery.Option {
	return grpc_recovery.WithRecoveryHandler(func(p interface{}) (err error) {
		return grpc.Errorf(codes.Unknown, "panic triggered: %v", p)
	})
}

添加grpc_recovery攔截器到服務(wù)端

grpcServer := grpc.NewServer(cred.TLSInterceptor(),
	grpc.StreamInterceptor(grpc_middleware.ChainStreamServer(
	        grpc_auth.StreamServerInterceptor(auth.AuthInterceptor),
			grpc_zap.StreamServerInterceptor(zap.ZapInterceptor()),
			grpc_recovery.StreamServerInterceptor(recovery.RecoveryInterceptor()),
		)),
		grpc.UnaryInterceptor(grpc_middleware.ChainUnaryServer(
		    grpc_auth.UnaryServerInterceptor(auth.AuthInterceptor),
			grpc_zap.UnaryServerInterceptor(zap.ZapInterceptor()),
            grpc_recovery.UnaryServerInterceptor(recovery.RecoveryInterceptor()),
		)),
	)

總結(jié)

本篇介紹了go-grpc-middleware中的grpc_zap、grpc_auth和grpc_recovery攔截器的使用。go-grpc-middleware中其他攔截器可參考GitHub學(xué)習(xí)使用。

教程源碼地址:https://github.com/Bingjian-Zhu/go-grpc-example

以上就是Go gRPC服務(wù)進(jìn)階middleware使用教程的詳細(xì)內(nèi)容,更多關(guān)于Go gRPC服務(wù)middleware的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Go語言實(shí)現(xiàn)布谷鳥過濾器的方法

    Go語言實(shí)現(xiàn)布谷鳥過濾器的方法

    這篇文章主要介紹了Go語言實(shí)現(xiàn)布谷鳥過濾器的方法,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-03-03
  • Golang 并發(fā)讀寫鎖的具體實(shí)現(xiàn)

    Golang 并發(fā)讀寫鎖的具體實(shí)現(xiàn)

    Go語言中的sync.RWMutex提供了讀寫鎖機(jī)制,允許多個協(xié)程并發(fā)讀取共享資源,但在寫操作時保持獨(dú)占性,本文主要介紹了Golang 并發(fā)讀寫鎖的具體實(shí)現(xiàn),感興趣的可以了解一下
    2025-02-02
  • Go語言zip文件的讀寫操作

    Go語言zip文件的讀寫操作

    本文主要介紹了Go語言zip文件的讀寫操作,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-04-04
  • Golang 限流器的使用和實(shí)現(xiàn)示例

    Golang 限流器的使用和實(shí)現(xiàn)示例

    這篇文章主要介紹了Golang 限流器的使用和實(shí)現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-06-06
  • VSCode安裝go相關(guān)插件失敗的簡單解決方案

    VSCode安裝go相關(guān)插件失敗的簡單解決方案

    這篇文章主要給大家介紹了關(guān)于VSCode安裝go相關(guān)插件失敗的簡單解決方案,VSCode是我們開發(fā)go程序的常用工具,最近安裝的時候遇到了些問題,需要的朋友可以參考下
    2023-07-07
  • 使用go xorm來操作mysql的方法實(shí)例

    使用go xorm來操作mysql的方法實(shí)例

    今天小編就為大家分享一篇關(guān)于使用go xorm來操作mysql的方法實(shí)例,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-04-04
  • go循環(huán)依賴的最佳解決方案

    go循環(huán)依賴的最佳解決方案

    ? import cycle not allowed(循環(huán)依賴不被允許)相信作為每一個golang語言使用研發(fā),都遇到過這個令人頭痛的報(bào)錯,循環(huán)依賴是指兩個或多個模塊之間互相依賴,形成了一個閉環(huán)的情況,本文會結(jié)合部分案例對解決方案進(jìn)行講解,需要的朋友可以參考下
    2023-10-10
  • Golang實(shí)現(xiàn)HTTP代理突破IP訪問限制的步驟詳解

    Golang實(shí)現(xiàn)HTTP代理突破IP訪問限制的步驟詳解

    在當(dāng)今互聯(lián)網(wǎng)時代,網(wǎng)站和服務(wù)商為了維護(hù)安全性和保護(hù)用戶隱私,常常會對特定的IP地址進(jìn)行封鎖或限制,本文將介紹如何使用Golang實(shí)現(xiàn)HTTP代理來突破IP訪問限制,需要的朋友可以參考下
    2023-10-10
  • 一文帶你深入了解Go語言中切片的奧秘

    一文帶你深入了解Go語言中切片的奧秘

    切片是數(shù)組的一個引用,因此切片是引用類型。但自身是結(jié)構(gòu)體,值拷貝傳遞。本文將通過示例帶大家一起探索一下Go語言中切片的奧秘,感興趣的可以了解一下
    2022-11-11
  • Go?gRPC服務(wù)proto數(shù)據(jù)驗(yàn)證進(jìn)階教程

    Go?gRPC服務(wù)proto數(shù)據(jù)驗(yàn)證進(jìn)階教程

    這篇文章主要為大家介紹了Go?gRPC服務(wù)proto數(shù)據(jù)驗(yàn)證進(jìn)階教程示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-06-06

最新評論

高雄县| 铜梁县| 柏乡县| 凤台县| 墨竹工卡县| 沙坪坝区| 桑日县| 黄山市| 湄潭县| 西昌市| 五台县| 平南县| 潞西市| 奎屯市| 巨鹿县| 客服| 田东县| 临西县| 凤城市| 光泽县| 揭西县| 平江县| 长顺县| 东乌| 伊宁市| 罗定市| 江西省| 青川县| 南澳县| 哈尔滨市| 北京市| 墨玉县| 舟曲县| 陆川县| 饶河县| 洛扎县| 犍为县| 清流县| 江华| 修水县| 乌拉特后旗|