【go】【rpc】【同一端口,提供多种服务】

@


写在前面

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

1. 需求

当 rpc 的服务启用时,为了更好对外提供服务(测试、监控、心跳等);我们需要多协议支持

    1. 起另外一个端口服务
    1. 同一个端口监听
    1. 同一个端口相同方法监听

1. 起另外的服务端口

package main

import (
	"context"
	"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"
	"strings"
)

func main() {
	port := "8080"
	go handleHttp("8088")
	handleRpc("8080")

}

func handleHttp(port string) *http.ServeMux {
	m := http.NewServeMux()
	m.HandleFunc("/ping", func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("pong")) })
	m.Handle("/", mux)
    m.Serve()
	//s := http.Server{Handler: m, Addr: "localhost:" + port}
	return m
}
func handleRpc()  {
	//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", "string", "string")
	svc := grpc.NewServer()
	proto.RegisterTagSvcServer(svc, tag)
	reflection.Register(svc)
    svc.Serve()
}

2. 一个端口监听

package main

import (
	"context"
    "github.com/soheilhy/cmux"
	"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"
	"strings"
)

func main() {
	port := "8080"
	//go handleHttp("8088")
	//handleRpc("8080")
	//l, err := net.Listen("tcp", "localhost:"+port)
	//if err != nil {
	//	log.Fatalf("Run TCP Server err: %v", err)
	//}

	m := cmux.New(l)
	grpcL := m.MatchWithWriters(cmux.HTTP2MatchHeaderFieldPrefixSendSettings("content-type", "application/grpc"))
	httpL := m.Match(cmux.HTTP1Fast())

	grpcS := handleRpc()
	httpS := handleHttp(port)

	go grpcS.Serve(grpcL)
	go httpS.Serve(httpL)
	//
	err = m.Serve()
	if err != nil {
		log.Fatalf("Run Serve err: %v", err)
	}
}



func handleHttp(port string) *http.ServeMux {
	m := http.NewServeMux()
	m.HandleFunc("/ping", func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("pong")) })
	//s := http.Server{Handler: m, Addr: "localhost:" + port}
	return m
}
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", "string", "string")
	//res, err := tag.TagList()
	//if err != nil {
	//	return
	//}
	//fmt.Printf("%s,%s", res.String(), err)
	svc := grpc.NewServer()
	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
}


3. 同一个端口相同方法监听

# 1. 下载 Google API Proto 文件
git clone https://github.com/googleapis/googleapis.git   

go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
go install github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway@latest

protoc -I . -I  $GOPATH\github.com\googleapis     --grpc-gateway_out=logtostderr=true:.  --go_out=.   --go-grpc_out .  rpc/proto/*.proto
service TagSvc {
  // protoc -I . -I  $GOPATH\github.com\googleapis     --grpc-gateway_out=logtostderr=true:.  --go_out=.   --go-grpc_out .  rpc/proto/*.proto
  rpc TagList(TagRequest) returns (MessageResponse){
    option (google.api.http) = {
      get: "/api/v1/tag"
    };
  }
}
package main

import (
	"context"
	"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"
	"strings"
)

func main() {
	port := "8080"

	grpcS := handleRpc()
	grpcG := handleGrpcGateway(port)
	httpS := handleHttp(port, grpcG)

	err := http.ListenAndServe(":"+port, grpcHandlerFunc(grpcS, httpS))
	if err != nil {
		log.Fatalf("Run Serve err: %v", err)
	}
}

func grpcHandlerFunc(grpcServer *grpc.Server, otherHandler http.Handler) http.Handler {
	return h2c.NewHandler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		if r.ProtoMajor == 2 && strings.Contains(r.Header.Get("Content-Type"), "application/grpc") {
			grpcServer.ServeHTTP(w, r)
		} else {
			otherHandler.ServeHTTP(w, r)
		}
	}), &http2.Server{})
}

func handleHttp(port string, mux *runtime.ServeMux) *http.ServeMux {
	m := http.NewServeMux()
	m.HandleFunc("/ping", func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("pong")) })
	m.Handle("/", mux)
	//s := http.Server{Handler: m, Addr: "localhost:" + port}
	return m
}
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", "string", "string")
	//res, err := tag.TagList()
	//if err != nil {
	//	return
	//}
	//fmt.Printf("%s,%s", res.String(), err)
	svc := grpc.NewServer()
	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
}


参考资料

基础/标准库/第三方库


golang 导航


编程规范


算法|面试


项目


posted @ 2024-06-06 22:13  Nones  阅读(14)  评论(0编辑  收藏  举报