grpc 和 restfull 共用一个端口

这个端口对外提供grpc服务,同时对外提供http json格式的服务

需要使用https,  http的话得再开一个端口

完整代码如下

package main

import (
	"io/ioutil"
	"crypto/tls"
	"crypto/x509"
	"net/http"
	"context"
	"strings"
	"github.com/grpc-ecosystem/grpc-gateway/runtime"
	"google.golang.org/grpc"
	
	log "github.com/sirupsen/logrus"
	"github.com/tmc/grpc-websocket-proxy/wsproxy"
	"google.golang.org/grpc/credentials"

	pb "hellogw"
)

const (
	port = ":50051"
	crtFile = "server.crt"
	keyFile = "server.key"
)

type server struct{}

func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
	return &pb.HelloReply{Message: "Hello " + in.Name}, nil
}

func getApiHandle(ctx context.Context) (http.Handler, error) {
	mux := runtime.NewServeMux()

/*	
	dcreds, err := credentials.NewClientTLSFromFile(crtFile, "wjs")
	if err != nil {
		log.Fatalf("Failed to create client TLS credentials %v", err)
	}
	opts := []grpc.DialOption{grpc.WithTransportCredentials(dcreds)}
*/
	
	b, err := ioutil.ReadFile(crtFile)
	if err != nil {
		return nil, err
	}
	cp := x509.NewCertPool()
	if !cp.AppendCertsFromPEM(b) {
		return nil, err
	}
	opts := []grpc.DialOption{grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{
		// given the grpc-gateway is always connecting to localhost, does
		// InsecureSkipVerify=true cause any security issues?
		InsecureSkipVerify: true,
		RootCAs:            cp,
	}))}

	err = pb.RegisterHelloHandlerFromEndpoint(ctx, mux, "localhost"+port, opts)
	if err != nil {
		return nil, err
	}
	
	// curl -X POST https://localhost:50051/v1/example/echo -d  '{"name":"lj"}'
	return mux,nil
}

func main() {
	ctx := context.Background()
	ctx, cancel := context.WithCancel(ctx)
	defer cancel()

	api := grpc.NewServer()
	pb.RegisterHelloServer(api, &server{})

	var apiHttp http.Handler
	
	handler := http.HandlerFunc(func (w http.ResponseWriter, r *http.Request) {
		if r.ProtoMajor == 2 && strings.Contains(r.Header.Get("Content-Type"), "application/grpc") {
			api.ServeHTTP(w, r)
		} else {
			if apiHttp  == nil {
				w.WriteHeader(http.StatusNotImplemented)
				return
			}
			apiHttp.ServeHTTP(w, r)
		}
	})
	
	mux,_ := getApiHandle(ctx)
	apiHttp = wsproxy.WebsocketProxy(mux)

	err := http.ListenAndServeTLS(port, crtFile, keyFile, handler)
	log.Println(err)
}
openssl genrsa -out server.key 2048
openssl req -new -x509 -key server.key -out server.crt -days 365
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:wjs
string is too long, it needs to be less than  2 bytes long
Country Name (2 letter code) [AU]:ch
State or Province Name (full name) [Some-State]:gd
Locality Name (eg, city) []:gz
Organization Name (eg, company) [Internet Widgits Pty Ltd]:zlg
Organizational Unit Name (eg, section) []:zlab
Common Name (e.g. server FQDN or YOUR name) []:wjs
Email Address []:xxx

生成 本示例的rpc文件请参考  grcp 简单示例

下面的函数可以把 grpc 的日志hook过来 打到 logrus 中

	"github.com/grpc-ecosystem/go-grpc-middleware"
	"github.com/grpc-ecosystem/go-grpc-middleware/logging/logrus"
	"github.com/grpc-ecosystem/go-grpc-middleware/tags"


func gRPCLoggingServerOptions() []grpc.ServerOption {
	logrusEntry := log.NewEntry(log.StandardLogger())
	logrusOpts := []grpc_logrus.Option{
		grpc_logrus.WithLevels(grpc_logrus.DefaultCodeToLevel),
	}

	return []grpc.ServerOption{
		grpc_middleware.WithUnaryServerChain(
			grpc_ctxtags.UnaryServerInterceptor(grpc_ctxtags.WithFieldExtractor(grpc_ctxtags.CodeGenRequestFieldExtractor)),
			grpc_logrus.UnaryServerInterceptor(logrusEntry, logrusOpts...),
		),
		grpc_middleware.WithStreamServerChain(
			grpc_ctxtags.StreamServerInterceptor(grpc_ctxtags.WithFieldExtractor(grpc_ctxtags.CodeGenRequestFieldExtractor)),
			grpc_logrus.StreamServerInterceptor(logrusEntry, logrusOpts...),
		),
	}
}

// 创建 rpc服务的时候 加入日志 hook 函数即可

api := grpc.NewServer(gRPCLoggingServerOptions()...)

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值