首页 > 其他分享 >【go】【grpc】【interceptor】

【go】【grpc】【interceptor】

时间:2024-06-15 20:32:21浏览次数:18  
标签:return err grpc fmt Println context go interceptor

@

目录


写在前面

  • 相关博文
  • 个人博客首页
  • 免责声明:仅供学习交流使用!开源框架可能存在的风险和相关后果将完全由用户自行承担,本人不承担任何法律责任。

客户端 unary interceptor

import (
    "context"
    "fmt"
    "google.golang.org/grpc"
    pb "path/to/your/protobuf/package"
)

// 客户端一元拦截器函数
func clientUnaryInterceptor(
    ctx context.Context,
    method string,
    req, reply interface{},
    cc *grpc.ClientConn,
    invoker grpc.UnaryInvoker,
    opts ...grpc.CallOption,
) error {
    // 在请求之前处理
    fmt.Println("Before RPC call:", method)
    
    // 调用实际的RPC方法
    err := invoker(ctx, method, req, reply, cc, opts...)
    
    // 在响应之后处理
    fmt.Println("After RPC call:", method)
    
    return err
}

func main() {
    // 创建一个带有拦截器的连接
    conn, err := grpc.Dial(
        "localhost:50051",
        grpc.WithInsecure(),
        grpc.WithUnaryInterceptor(clientUnaryInterceptor),
    )
    if err != nil {
        fmt.Println("Failed to connect:", err)
        return
    }
    defer conn.Close()

    // 创建客户端存根
    client := pb.NewYourServiceClient(conn)

    // 调用服务方法
    resp, err := client.YourMethod(context.Background(), &pb.YourRequest{})
    if err != nil {
        fmt.Println("Error calling service:", err)
        return
    }

    fmt.Println("Response from service:", resp)
}

服务器 nuary interceptor

import (
    "context"
    "fmt"
    "google.golang.org/grpc"
    "net"
    pb "path/to/your/protobuf/package"
)

// 服务器端一元拦截器函数
func serverUnaryInterceptor(
    ctx context.Context,
    req interface{},
    info *grpc.UnaryServerInfo,
    handler grpc.UnaryHandler,
) (interface{}, error) {
    // 在请求处理之前处理
    fmt.Println("Before handling RPC call:", info.FullMethod)
    
    // 调用实际的服务方法
    resp, err := handler(ctx, req)
    
    // 在响应之后处理
    fmt.Println("After handling RPC call:", info.FullMethod)
    
    return resp, err
}

type server struct {
    pb.UnimplementedYourServiceServer
}

func (s *server) YourMethod(ctx context.Context, req *pb.YourRequest) (*pb.YourResponse, error) {
    // 服务逻辑
    return &pb.YourResponse{}, nil
}

func main() {
    // 创建一个gRPC服务器并添加一元拦截器
    grpcServer := grpc.NewServer(grpc.UnaryInterceptor(serverUnaryInterceptor))
    pb.RegisterYourServiceServer(grpcServer, &server{})

    // 启动服务器
    lis, err := net.Listen("tcp", ":50051")
    if err != nil {
        fmt.Println("Failed to listen:", err)
        return
    }
    if err := grpcServer.Serve(lis); err != nil {
        fmt.Println("Failed to serve:", err)
        return
    }
}

客户端 stream interceptor

import (
    "context"
    "fmt"
    "google.golang.org/grpc"
    pb "path/to/your/protobuf/package"
)

// 客户端流式拦截器函数
func clientStreamInterceptor(
    ctx context.Context,
    desc *grpc.StreamDesc,
    cc *grpc.ClientConn,
    method string,
    streamer grpc.Streamer,
    opts ...grpc.CallOption,
) (grpc.ClientStream, error) {
    // 在请求之前处理
    fmt.Println("Before streaming RPC call:", method)
    
    // 调用实际的流式RPC方法
    clientStream, err := streamer(ctx, desc, cc, method, opts...)
    
    // 在响应之后处理
    fmt.Println("After streaming RPC call:", method)
    
    return clientStream, err
}

func main() {
    // 创建一个带有拦截器的连接
    conn, err := grpc.Dial(
        "localhost:50051",
        grpc.WithInsecure(),
        grpc.WithStreamInterceptor(clientStreamInterceptor),
    )
    if err != nil {
        fmt.Println("Failed to connect:", err)
        return
    }
    defer conn.Close()

    // 创建客户端存根
    client := pb.NewYourServiceClient(conn)

    // 调用服务方法
    stream, err := client.YourStreamingMethod(context.Background())
    if err != nil {
        fmt.Println("Error calling service:", err)
        return
    }

    // 处理流数据
    for {
        resp, err := stream.Recv()
        if err != nil {
            if err == io.EOF {
                break
            }
            fmt.Println("Error receiving stream:", err)
            return
        }
        fmt.Println("Received message from stream:", resp)
    }
}

服务器 stream interceptor

import (
    "context"
    "fmt"
    "google.golang.org/grpc"
    "net"
    pb "path/to/your/protobuf/package"
)

// 服务器端流式拦截器函数
func serverStreamInterceptor(
    srv interface{},
    ss grpc.ServerStream,
    info *grpc.StreamServerInfo,
    handler grpc.StreamHandler,
) error {
    // 在请求处理之前处理
    fmt.Println("Before handling streaming RPC call:", info.FullMethod)
    
    // 调用实际的流式RPC方法
    err := handler(srv, ss)
    
    // 在响应之后处理
    fmt.Println("After handling streaming RPC call:", info.FullMethod)
    
    return err
}

type server struct {
    pb.UnimplementedYourServiceServer
}

func (s *server) YourStreamingMethod(stream pb.YourService_YourStreamingMethodServer) error {
    // 服务逻辑
    return nil
}

func main() {
    // 创建一个gRPC服务器并添加流式拦截器
    grpcServer := grpc.NewServer(grpc.StreamInterceptor(serverStreamInterceptor))
    pb.RegisterYourServiceServer(grpcServer, &server{})

    // 启动服务器
    lis, err := net.Listen("tcp", ":50051")
    if err != nil {
        fmt.Println("Failed to listen:", err)
        return
    }
    if err := grpcServer.Serve(lis); err != nil {
        fmt.Println("Failed to serve:", err)
        return
    }
}

服务器 多 unay interceptor

import (
    "context"
    "fmt"
    "google.golang.org/grpc"
    "net"
    pb "path/to/your/protobuf/package"
)

// 第一个服务器端一元拦截器
func firstServerUnaryInterceptor(
    ctx context.Context,
    req interface{},
    info *grpc.UnaryServerInfo,
    handler grpc.UnaryHandler,
) (interface{}, error) {
    fmt.Println("First unary interceptor - Before handling RPC call:", info.FullMethod)
    resp, err := handler(ctx, req)
    fmt.Println("First unary interceptor - After handling RPC call:", info.FullMethod)
    return resp, err
}

// 第二个服务器端一元拦截器
func secondServerUnaryInterceptor(
    ctx context.Context,
    req interface{},
    info *grpc.UnaryServerInfo,
    handler grpc.UnaryHandler,
) (interface{}, error) {
    fmt.Println("Second unary interceptor - Before handling RPC call:", info.FullMethod)
    resp, err := handler(ctx, req)
    fmt.Println("Second unary interceptor - After handling RPC call:", info.FullMethod)
    return resp, err
}

type server struct {
    pb.UnimplementedYourServiceServer
}

func (s *server) YourMethod(ctx context.Context, req *pb.YourRequest) (*pb.YourResponse, error) {
    return &pb.YourResponse{}, nil
}

func main() {
    // 创建一个带有多个拦截器的gRPC服务器
    grpcServer := grpc.NewServer(
        grpc.ChainUnaryInterceptor(firstServerUnaryInterceptor, secondServerUnaryInterceptor),
    )
    pb.RegisterYourServiceServer(grpcServer, &server{})

    // 启动服务器
    lis, err := net.Listen("tcp", ":50051")
    if err != nil {
        fmt.Println("Failed to listen:", err)
        return
    }
    if err := grpcServer.Serve(lis); err != nil {
        fmt.Println("Failed to serve:", err)
        return
    }
}


具体例子

服务器 unary interceptor

	"context"
	assetfs "github.com/elazarl/go-bindata-assetfs"
	"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
	"golang.org/x/net/http2"
	"golang.org/x/net/http2/h2c"
	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials/insecure"
	"google.golang.org/grpc/reflection"
	"log"
	"net/http"
	"path"
	"strings"
)
func handleRpc() *grpc.Server {
	//a := api.Api{Ctx: context.TODO(), Url: "http://localhost", Ak: "string", Sk: "string"}
	//list, err := a.TagList()
	//fmt.Printf("%#v,%s", list, err)
	tag := server.NewTag("http://localhost:8080", "string", "string")
	//res, err := tag.TagList()
	//if err != nil {
	//	return
	//}
	//fmt.Printf("%s,%s", res.String(), err)
	interceptors := []grpc.ServerOption{grpc.UnaryInterceptor(HelloInterceptor)}
	svc := grpc.NewServer(interceptors...)
	proto.RegisterTagSvcServer(svc, tag)
	reflection.Register(svc)
	return svc
}
func handleGrpcGateway(port string) *runtime.ServeMux {
	endpoint := "0.0.0.0:" + port
	g := runtime.NewServeMux()
	dopts := []grpc.DialOption{grpc.WithTransportCredentials(insecure.NewCredentials())}
	_ = proto.RegisterTagSvcHandlerFromEndpoint(context.Background(), g, endpoint, dopts)

	return g
}

func HelloInterceptor(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (any, error) {
	log.Println("你好")
	resp, err := handler(ctx, req)
	log.Println("再见")
	return resp, err
}


多拦截器

func handleRpc() *grpc.Server {
	//a := api.Api{Ctx: context.TODO(), Url: "http://localhost", Ak: "string", Sk: "string"}
	//list, err := a.TagList()
	//fmt.Printf("%#v,%s", list, err)
	tag := server.NewTag("http://localhost:8080", "string", "string")
	//res, err := tag.TagList()
	//if err != nil {
	//	return
	//}
	//fmt.Printf("%s,%s", res.String(), err)
	interceptors := grpc.ChainUnaryInterceptor(HelloInterceptor, WorldInterceptor)
	svc := grpc.NewServer(interceptors)
	proto.RegisterTagSvcServer(svc, tag)
	reflection.Register(svc)
	return svc
}
func handleGrpcGateway(port string) *runtime.ServeMux {
	endpoint := "0.0.0.0:" + port
	g := runtime.NewServeMux()
	dopts := []grpc.DialOption{grpc.WithTransportCredentials(insecure.NewCredentials())}
	_ = proto.RegisterTagSvcHandlerFromEndpoint(context.Background(), g, endpoint, dopts)

	return g
}

func HelloInterceptor(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (any, error) {
	log.Println("你好")
	resp, err := handler(ctx, req)
	log.Println("再见")
	return resp, err
}
func WorldInterceptor(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (any, error) {
	log.Println("你好")
	resp, err := handler(ctx, req)
	log.Println("再见")
	return resp, err
}


参考资料

基础/标准库/第三方库


golang 导航


编程规范


算法|面试


项目


标签:return,err,grpc,fmt,Println,context,go,interceptor
From: https://www.cnblogs.com/nones/p/18249696

相关文章

  • Golang 百题(实战快速掌握语法)_1
    整形转字符串类型实验介绍本实验将展示三种方法来实现整形类型转字符串类型。知识点strconvfmtItoa函数代码实例Go语言中strconv包的itoa函数输入一个int类型,返回转换后的字符串。下面是一个例子。packagemainimport("fmt""strconv")funcmai......
  • WebGoC题解(4) 115.第5题 同心圆(比赛模拟题)
    题目描述学校准备在颁奖会把这次比赛的前10名的成绩用崭新的形状表示出来,这个艰巨的任务交给了小C。为了和以往不同,小C决定用每个学生的成绩作为半径画同心圆来表示。这个创新的举动需要你使用GoC编程,在一个黑色实心圆背景下,用10个红色圆表示成绩。具体形状参见输入输出样例......
  • SCI一区 | Matlab实现NGO-TCN-BiGRU-Attention北方苍鹰算法优化时间卷积双向门控循环
    要在Matlab中实现NGO-TCN-BiGRU-Attention北方苍鹰算法进行多变量时间序列预测,需要按照以下步骤进行:准备数据:首先,准备多变量时间序列数据。确保数据已经进行了预处理,例如归一化或标准化,以便神经网络能够更好地进行学习和预测。构建NGO-TCN-BiGRU-Attention模型:根据算法的......
  • 2024-06-15:用go语言,Alice 和 Bob 在一个环形草地上玩一个回合制游戏。 草地上分布着一
    2024-06-15:用go语言,Alice和Bob在一个环形草地上玩一个回合制游戏。草地上分布着一些鲜花,其中Alice到Bob之间顺时针方向有x朵鲜花,逆时针方向有y朵鲜花。游戏规则如下:1.游戏从Alice开始。2.每个回合中,当前玩家必须选择顺时针或逆时针,并在所选方向上摘取一朵鲜花。......
  • Django 解决 CORS 跨域问题
    Django解决CORS跨域问题★CORS基本概念CORS(Cross-OriginResourceSharing跨域资源共享)是一种用于在Web浏览器中处理跨域请求的机制。跨域请求指的是在浏览器中,从一个域名的网页去请求另一个域名的资源。在默认情况下,浏览器限制了跨域请求,以保护用户的安全和隐私。★CO......
  • go,无法安装 gorilla websocket
    go中没有websocket这个库,需要安装第三方的库,这里选择常用的gorilla/websocket,如下:E:\Projects\CSMS\SK-CSMS\CentralSystem>goget-ugithub.com/gorilla/websocketgo:modulegithub.com/gorilla/websocket:Get"https://proxy.golang.org/github.com/gorilla/websocke......
  • Go-知识并发控制mutex
    Go-知识并发控制mutex1.介绍2.数据结构2.1Mutex结构体2.2Mutex方法3.加锁解锁过程3.1简单加锁3.2加锁被阻塞3.3简单解锁3.4解锁并唤醒协程4.自旋过程4.1什么是自旋4.2自旋条件4.3自旋的优势4.4自旋的问题5.Mutex模式5.1Normal模式5.2Starving模......
  • 大学生如何从0到1学习Go语言
    现在还有人在问,Go语言还可以学习嘛?毫不犹豫的说,可以学,不要怀疑。对于初学者该如何学习呢。初始阶段:了解和准备了解Go语言:研究Go语言的设计哲学、特点(如并发支持、内存管理等)。了解Go语言在云计算、微服务等领域的应用。环境搭建:访问Go语言官网下载并安装Go语言环境。配......
  • Django ORM非空判断、以及通用写法
    django文档DjangoORM中,判断非空(notnull)有多种方式,使用isnull查询方法#查找所有name字段不为空的对象objects=MyModel.objects.filter(name__isnull=False)使用exclude方法排除空值:#查找所有name字段不为空的对象objects=MyModel.objects.exclude(name_......
  • golang select {} 和 for {} 的区别
     select{}与for{}在Go语言中都是循环结构,但它们的行为和用途有所不同: select{}:是一个无限阻塞的select语句,没有指定任何case。主要用于等待通道操作或其他事件,在没有明确的通信或信号需求时保持运行状态。当程序需要在没有明确结束条件的情况下保......