【go】【grpc】【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 导航


编程规范


算法|面试


项目


posted @ 2024-06-15 20:29  Nones  阅读(4)  评论(0编辑  收藏  举报