如果一个应用需要同时对外提供 HTTP 和 gRPC 服务,通常情况下我们会为两个服务绑定不同的监听端口,而本文要介绍的 cmux 为我们提供了一种连接多路复用的新选择,使用 cmux 可以将不同服务绑定在同一个网络端口上!

简介

多路复用是个很常见的概念,我们在编写 HTTP 服务时通常会用 http.ServeMux 或类似的三方工具实现请求与 handler 的匹配和绑定,这类多路复用一般作用在某个服务内部。而 cmux(github.com/soheilhy/cmux) 则提供了基于请求内容对连接进行多路复用的能力,使用 cmux 我们可以在同一个 TCP 监听(端口)上提供包括 gRPC、SSH、HTTPS、HTTP、Go RPC 在内的几乎任何协议。

cmux 通过扩展 net.Listener 的方式实现了连接多路复用能力,在接收到客户端请求后,cmux 会根据注册的规则对客户端请求进行鉴别和匹配,并根据匹配结果将请求转发给相应的服务。

使用举例

cmux 的使用特别简单,我们只需要为每个服务指定相应的匹配规则即可:

package mainimport ("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:50051")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 httphttpL := mux.Match(cmux.Any())// gRPC servergrpcS := grpc.NewServer()pb.RegisterGreeterServer(grpcS, &server{})// HTTP serverhttpS := &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
}

先来试试 http 访问是否正常

$ curl -D - http://localhost:50051
HTTP/1.1 200 OK
Date: Mon, 21 Mar 2022 08:20:15 GMT
Content-Length: 16
Content-Type: text/plain; charset=utf-8greet from HTTP

再来试试 gRPC 访问

$ ${GOPATH}/bin/greeter_client -addr localhost:50051
2022/03/21 16:12:11 Greeting: greet from gRPC

测试客户端安装:go install google.golang.org/grpc/examples/helloworld/greeter_client

如上,我们通过 50051 这个端口同时承载了 HTTP 和 gRPC 两个服务,是不是特别神奇!

总结

使用 cmux 我们可以轻松实现对服务端连接的多路复用,cmux 仅会在连接建立之初读取少量请求样本进行路由匹配,因此在客户端长连接场景下的性能损失几乎可以忽略不计。大家来试试吧!

参考资料

  • https://github.com/soheilhy/cmux

《酷Go推荐》招募:

各位Gopher同学,最近我们社区打算推出一个类似GoCN每日新闻的新栏目《酷Go推荐》,主要是每周推荐一个库或者好的项目,然后写一点这个库使用方法或者优点之类的,这样可以真正的帮助到大家能够学习到

新的库,并且知道怎么用。

大概规则和每日新闻类似,如果报名人多的话每个人一个月轮到一次,欢迎大家报名!戳「阅读原文」,即可报名

想要了解更多 Golang 相关的内容,欢迎扫描下方

「GoCN酷Go推荐」使用 cmux 实现服务端连接多路复用相关推荐

  1. 「GoCN酷Go推荐」​QQ机器人 go-cqhttp

    什么是 go-cqhttp?✦ QQ机器人,可以做的事儿太多了,比如一个UP主需要群发多个QQ群,以便通知粉丝们开播:再比如可以检测群内或发给自己的消息,而通过代码直接回复做的简单回复.比如检测群内有 ...

  2. 「GoCN酷Go推荐」go语言位操作库 — bitset

    bitset库实现了bitsets数据结构,这是一种正整数和布尔值映射关系的结构,它比map[uint]bool更高效 什么是bitsets✦ bitsets基本思想是用一个bit位来标记某个元素对应 ...

  3. 「GoCN酷Go推荐」高性能内存缓存 ristretto

    背景 ristretto 是 dgraph 团队开源的一款高性能内存缓存库,旨在解决高并发场景下的缓存性能和吞吐瓶颈.dgraph 专攻的方向是高性能图数据库,ristretto 就是其图数据库和 K ...

  4. 「GoCN酷Go推荐」快速搭建私有云服务 go-btfs

    # 1. go-btfs 是什么?# go-btfs 是一个去中心化的文件存储平台,无论图片.文件.视频等等各类文件.每个人都可以在自己电脑上安装部署 BTFS 节点,然后大家的节点相互连接,构成一个 ...

  5. 「GoCN酷Go推荐」后现代时代远程办公网络问题的golang开源解决方案 —— PairMesh...

    PairMesh是什么? Pairmesh是一款先进的虚拟局域网(VPN)工具,用来搭建与访问安全,易用,高性能的点对点的软件定义虚拟局域网,为远程办公的网络连接问题提供了开箱即用的解决方案. 拥抱开 ...

  6. 「GoCN酷Go推荐」JSON 数据获取器 JID

    01 推荐理由   JSON 格式数据适用范围非常广泛,一个内容丰富的json数据可能很大,使用 JID 可以让你非常舒服的获取到想要到数据. 02 简介 JID 是一个过滤JSON格式数据 cli ...

  7. 「GoCN酷Go推荐」Golang轻量级桌面程序wails2教学

    01 推荐理由 不依赖cgo!不依赖cgo!不依赖cgo!真的不依赖cgo,且跨平台,原生渲染 无嵌入式浏览器,轻量级,生成的文件很小,而且只有一个可执行文件就可运行. 02 功能介绍 后端使用标准 ...

  8. 「GoCN酷Go推荐」简单易用的性能分析工具——nitro

    #1 推荐理由 Golang官方在程序性能分析方面提供了用来分析cpu/内存等采样信息的pprof,以及用来追踪和分析运行时事件的trace,这两个工具对于分析程序的性能瓶颈可以说是得心应手.但是,对 ...

  9. 「GoCN酷Go推荐」漏桶限流库 — uber-go/ratelimit

    上次有同学分享了 单机限流器 time/rate 库,讲了 Golang 标准库中基于令牌桶实现限流组件的 time/rate 使用,同时也讲了一些限流算法原理. 这里分享一个 uber 开源的一套基 ...

最新文章

  1. c/c++ ide clion安装编译器
  2. 【Android 逆向】Android 逆向通用工具开发 ( 静态库项目中的网络操作核心类 CNetwork 分析 )
  3. 任务和特权级保护(三)——《x86汇编语言:从实模式到保护模式》读书笔记34
  4. kotlin sealed 中_Kotlin sealed class
  5. ImportError: cannot import name HTTPSHandler
  6. 7.4 流水线的冒险
  7. CentOS源码安装消息队列ActiveMQ
  8. 普林斯顿大学计算机科学研究生条件,普林斯顿大学之计算机科学系
  9. 如何让.Net线程支持超时后并自动销毁!
  10. Windows网络编程之(二)Socket通信非阻塞模式Select(TCP和UDP)
  11. 图神经网络——node2vec
  12. journalctl日志管理
  13. 4.3.5 导频插入
  14. Exception in thread main java.lang.OutOfMemoryError: Java heap space(Java堆空间内存溢出)解决方法...
  15. sis最新ip地址2020入口一_2020云南高考成绩公布时间最新 云南高考查成绩方式入口大全...
  16. 页面布局中遇到菱形图片时的处理办法
  17. matlab冲激激励,实验一 阶跃响应与冲激响应.doc
  18. xampp is currently only availably as 32 bit applic
  19. Tomcat7.0源码分析——server.xml文件的加载与解析
  20. Error: Can‘t find Python executable “python“, you can set the PYTHON env variable

热门文章

  1. 雪崩时没有一片雪花是无辜的
  2. appium安装说明
  3. 【计算机网络】信道的极限容量——奈氏准则、奈圭斯特公式、信噪比、香农公式
  4. win7打开信息服务器,Win7怎么打开系统服务查看系统服务信息的方法
  5. 2021年安全员-B证考试题及安全员-B证模拟考试题
  6. Python二维列表list初始化,不限定维度长度
  7. Movi 数据集介绍
  8. spacedesk使用,让你体验分屏的快乐
  9. android log.v,MVlog短视频
  10. postgresql 吕宏庆_吕宏庆:用网络汇聚爱心 用行动传递温情