【go】【rpc】【同一埠,提供多種服務】

Nones發表於2024-06-06

@

目錄
  • 寫在前面
  • 1. 需求
    • 1. 起另外的服務埠
    • 2. 一個埠監聽
    • 3. 同一個埠相同方法監聽
  • 參考資料
    • 基礎/標準庫/第三方庫
    • golang 導航
    • 程式設計規範
    • 演算法|面試
    • 專案


寫在前面

  • 相關博文
  • 個人部落格首頁
  • 免責宣告:僅供學習交流使用!開源框架可能存在的風險和相關後果將完全由使用者自行承擔,本人不承擔任何法律責任。

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
}


參考資料

基礎/標準庫/第三方庫


  • 地鼠文件:比較多資料
  • topgoer
  • go awesome
  • golang 文件學習
  • golang 標準庫
  • go 檔案常用操作

golang 導航


  • golang 收集
  • go-guide
  • golang 導航
  • go-concurrency-guide
  • go-advice
  • golang 知識路線

程式設計規範


  • golang 程式設計規範
  • golang 規範示例

演算法|面試


  • cs 面試
  • 面試網站
  • Golang後端研發崗位相關面試題和簡歷
  • 路人張的面試筆記
  • golang 演算法

專案


  • golang 專案推薦
  • 7天系列
  • go專案推薦
  • go高效能程式設計

相關文章