Go 使用 cmux 實現網絡端口複用
cmux 的作用
一般情況下, 每個端口只能爲一個服務所用, 如果複用, 會報 "port is already in use"
如果需要複用某個端口, 那麼可以使用 cmux 來實現 (其實大多數情況下必要性不大. 比如我就圖 8888 端口吉利, http/grpc 等服務都用這個端口)
cmux[1] 全稱 Connection Mux, 是 Go 生態來複用端口的庫, 可以在同一個 TCP 監聽器上服務 gRPC、SSH、HTTPS、HTTP、Go RPC 等幾乎任何其他協議。
實現原理
cmux 的實現原理主要是通過 "查看" 連接的第一個數據包來確定連接的類型。每種類型的連接都有一個匹配器,這個匹配器可以是自定義的,也可以使用 cmux 庫提供的一些內置匹配器。
當一個連接進來時,cmux 會將其數據包傳遞給所有匹配器,看看哪個匹配器會匹配這個數據包。一旦找到一個匹配的匹配器,cmux 就會將該連接傳遞給對應的服務去處理。
cmux 源碼分析 [2]
示例代碼
以下示例創建了一個主監聽器,然後爲該監聽器創建了一個 cmux,然後匹配不同的連接併爲每種類型的連接創建對應的服務。
package main
import (
"context"
"log"
"net"
"net/http"
"google.golang.org/grpc"
pb "google.golang.org/grpc/examples/helloworld/helloworld"
"github.com/soheilhy/cmux"
)
func main() {
lis, err := net.Listen("tcp", "localhost:8888")
if err != nil {
log.Fatalf("failed to listen: %v", err)
}
mux := cmux.New(lis)
// gRPC 匹配規則
grpcL := mux.MatchWithWriters(
cmux.HTTP2MatchHeaderFieldSendSettings("content-type", "application/grpc"),
)
// otherwise serve http
httpL := mux.Match(cmux.Any())
// gRPC server
grpcS := grpc.NewServer()
pb.RegisterGreeterServer(grpcS, &server{})
// HTTP server
httpS := &http.Server{
Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("greet from HTTP\n"))
}),
}
// start serving!
go grpcS.Serve(grpcL)
go httpS.Serve(httpL)
log.Printf("serve both grpc and http at %v", lis.Addr())
if err := mux.Serve(); err != nil {
log.Fatalf("failed to serve: %v", err)
}
}
type server struct {
pb.UnimplementedGreeterServer
}
func (server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
return &pb.HelloReply{Message: "greet from gRPC"}, nil
}
go mod tidy
而後 go run main.go
運行如上代碼,
在瀏覽器地址欄中輸入 http://localhost:8888/
在命令行中執行 greeter_client -addr localhost:8888
如果沒有安裝 greeter_client, 可以 go install google.golang.org/grpc/examples/helloworld/greeter_client,
然後再 ${GOPATH}/bin/greeter_client -addr localhost:8888
更多可參考 Go 每日一庫之 139:cmux (連接多路複用)[3]
參考資料
[1]
cmux: https://github.com/soheilhy/cmux
[2]
cmux 源碼分析: https://wadevan.github.io/post/cmux/
[3]
Go 每日一庫之 139:cmux (連接多路複用): https://cloud.tencent.com/developer/article/2334531
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/_BQjJT8zqvWrXXdO_YR8lA