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中间件编程与跨域配置](