golang工程— grpc-gateway健康检查和跨域配置

grpc健康检查网关跨域配置

grpc健康检查

grpc健康检查使用

服务端配置
go 复制代码
import (
    "google.golang.org/grpc/health"
    "google.golang.org/grpc/health/grpc_health_v1"
)

//添加健康检查服务,多路复用
grpc_health_v1.RegisterHealthServer(s, health.NewServer())
网关配置

gateway.go

go 复制代码
package gateway

import (
    "context"
    "flag"
    "fmt"
    "google.golang.org/grpc/health/grpc_health_v1"
    "net/http"
    "user/user-server/gateway/middleware"

    "github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
    "google.golang.org/grpc"
    "google.golang.org/grpc/credentials/insecure"
    _ "google.golang.org/grpc/grpclog"

    gw "user/proto"  // Update
)

var (
    // command-line options:
    // gRPC server endpoint
    grpcServerEndpoint = flag.String("grpc-server-endpoint",  "localhost:50051", "gRPC server endpoint")
)

func Run() error {
    ctx := context.Background()
    ctx, cancel := context.WithCancel(ctx)
    defer cancel()
    // 请求时,将http header中某些字段转发到grpc上下文
    inComingOpt :=  runtime.WithIncomingHeaderMatcher(func(s string) (string, bool) {
        fmt.Println("header:" + s)
        switch s {
        case "Service-Authorization":
            fmt.Println("Service-Authorization hit")
            return "Service-Authorization", true
        default:
            return "", false
        }
    })
    // 响应后,grpc上下文转发到http头部
    outGoingOpt := runtime.WithOutgoingHeaderMatcher(func(s string) (string, bool) {
       return "", false
    })


    //创建连接,用于健康检查
    conn, err := grpc.Dial(*grpcServerEndpoint, grpc.WithTransportCredentials(insecure.NewCredentials()))
    if err != nil {
        return err
    }


    // Register gRPC server endpoint
    // Note: Make sure the gRPC server is running properly and accessible
    // runtime.WithHealthEndpointAt() 指定路径, 转发Header到grpc上下文在这是不生效的inCommingOpt 是不生效的,因为我们在这弄了个客户端,需要手动转发操作。或者排除掉,我们这选择排除掉
    mux := runtime.NewServeMux(inComingOpt, outGoingOpt, runtime.WithHealthzEndpoint(grpc_health_v1.NewHealthClient(conn)))
    
    //添加文件上传处理函数
    mux.HandlePath("POST", "/upload", uploadHandler)
    handler := middleware.Cors(mux)
    opts := []grpc.DialOption{grpc.WithTransportCredentials(insecure.NewCredentials())}
    err = gw.RegisterUserHandlerFromEndpoint(ctx, mux,  *grpcServerEndpoint, opts)
    if err != nil {
        return err
    }

    // Start HTTP server (and proxy calls to gRPC server endpoint)
    return http.ListenAndServe(":8081", handler)
}

如果网关中设置了拦截器之类的进行鉴权判断,可以通过FullName="/grpc.health.v1.Health/Check"去忽略鉴权

监控检查默认请求 http://localhost:8081/healthz

grpc网关跨域配置

采用中间件的形式封装httphandler

go 复制代码
package middleware

import "net/http"

func Cors(handler http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        method := r.Method
        origin := r.Header.Get("Origin")
        if origin != "" {
            // 允许来源配置
            w.Header().Set("Access-Control-Allow-Origin", "*") // 可将将 * 替换为指定的域名
            w.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE, UPDATE, PATCH")
            w.Header().Set("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization")
            w.Header().Set("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Cache-Control, Content-Language, Content-Type")
            w.Header().Set("Access-Control-Allow-Credentials", "true")
        }
        if method == "OPTIONS" {
            w.WriteHeader(http.StatusNoContent)
            return
        }
        handler.ServeHTTP(w, r)
    })
}

然后修改gateway

gateway.go

go 复制代码
package gateway

import (
    "context"
    "flag"
    "fmt"
    "google.golang.org/grpc/health/grpc_health_v1"
    "net/http"
    "user/user-server/gateway/middleware"

    "github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
    "google.golang.org/grpc"
    "google.golang.org/grpc/credentials/insecure"
    _ "google.golang.org/grpc/grpclog"

    gw "user/proto"  // Update
)

var (
    // command-line options:
    // gRPC server endpoint
    grpcServerEndpoint = flag.String("grpc-server-endpoint",  "localhost:50051", "gRPC server endpoint")
)

func Run() error {
    ctx := context.Background()
    ctx, cancel := context.WithCancel(ctx)
    defer cancel()
    // 请求时,将http header中某些字段转发到grpc上下文
    inComingOpt :=  runtime.WithIncomingHeaderMatcher(func(s string) (string, bool) {
        fmt.Println("header:" + s)
        switch s {
        case "Service-Authorization":
            fmt.Println("Service-Authorization hit")
            return "Service-Authorization", true
        default:
            return "", false
        }
    })
    // 响应后,grpc上下文转发到http头部
    outGoingOpt := runtime.WithOutgoingHeaderMatcher(func(s string) (string, bool) {
       return "", false
    })


    //创建连接,用于健康检查
    conn, err := grpc.Dial(*grpcServerEndpoint, grpc.WithTransportCredentials(insecure.NewCredentials()))
    if err != nil {
        return err
    }


    // Register gRPC server endpoint
    // Note: Make sure the gRPC server is running properly and accessible
    // runtime.WithHealthEndpointAt() 指定路径, 转发Header到grpc上下文在这是不生效的inCommingOpt 是不生效的,因为我们在这弄了个客户端,需要手动转发操作。或者排除掉,我们这选择排除掉
    mux := runtime.NewServeMux(inComingOpt, outGoingOpt, runtime.WithHealthzEndpoint(grpc_health_v1.NewHealthClient(conn)))
    
    //添加文件上传处理函数
    mux.HandlePath("POST", "/upload", uploadHandler)
    handler := middleware.Cors(mux)
    opts := []grpc.DialOption{grpc.WithTransportCredentials(insecure.NewCredentials())}
    err = gw.RegisterUserHandlerFromEndpoint(ctx, mux,  *grpcServerEndpoint, opts)
    if err != nil {
        return err
    }

    // Start HTTP server (and proxy calls to gRPC server endpoint)
    return http.ListenAndServe(":8081", handler)
}

更多grpc跨域配置的内容见

gin中间件编程与跨域配置(

相关推荐
IvanCodes5 小时前
Python 数据处理(十三):JSON、CSV 与数据序列化
开发语言·python
aramae6 小时前
MySQL复合查询(8)
java·c语言·开发语言·后端·算法
qq_2518364579 小时前
springboot vue3 开发实现 拼豆管理系统
java·开发语言·ai编程
郑州光合科技余经理10 小时前
同城外卖小程序开发:下单成功后,后台导出能不能对上用户端状态
开发语言·前端·git·后端·uni-app·php·ai编程
知识分享小能手10 小时前
C++ 学习教程,从入门到精通,C++ 入门知识 — 完整知识点(1)
开发语言·c++·学习
+VX:Fegn089510 小时前
计算机毕业设计|基于springboot + vue旅游管理系统(源码+数据库+文档)
java·开发语言·vue.js·spring boot·课程设计
阿里嘎多学长11 小时前
2026-09-20 GitHub 热点项目精选
开发语言·程序员·github·代码托管
weixin_3077791313 小时前
C++代码实现MATLAB中的ode23tb函数功能
开发语言·c++·算法·matlab
2601_9669496513 小时前
为什么量化回测中 for 循环比 DataFrame 慢三个数量级?从向量化原理讲起
开发语言·python·pandas·股票数据·quantdash
边境悍匪14 小时前
蜗牛学苑 Java 智能体学习 Day45|Knife4j+SpringBoot3、书城项目整合 MyBatis 思维导图复盘
java·开发语言·vue.js·学习·spring