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,可以 go install google.golang.org/grpc/examples/helloworld/greeter_client,
然后再 ${GOPATH}/bin/greeter_client -addr localhost:8888
更多可参考 Go每日一库之139:cmux (连接多路复用)[3]
完整代码: https://github.com/cuishuang/cmux-lab
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
本文由 mdnice 多平台发布