{"id":21091307,"url":"https://github.com/lyouthzzz/ws-gateway","last_synced_at":"2026-03-02T22:02:27.393Z","repository":{"id":64299428,"uuid":"569132960","full_name":"lyouthzzz/ws-gateway","owner":"lyouthzzz","description":null,"archived":false,"fork":false,"pushed_at":"2023-03-22T08:32:15.000Z","size":814,"stargazers_count":32,"open_issues_count":1,"forks_count":5,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-05-16T13:44:49.679Z","etag":null,"topics":["gateway","go","golang","grpc","kratos","websocket"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lyouthzzz.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-11-22T06:37:17.000Z","updated_at":"2025-05-01T12:30:51.000Z","dependencies_parsed_at":"2024-06-20T10:18:59.317Z","dependency_job_id":"4e175b94-8d6e-4fac-ae95-8aed6ccda078","html_url":"https://github.com/lyouthzzz/ws-gateway","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/lyouthzzz/ws-gateway","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lyouthzzz%2Fws-gateway","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lyouthzzz%2Fws-gateway/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lyouthzzz%2Fws-gateway/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lyouthzzz%2Fws-gateway/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lyouthzzz","download_url":"https://codeload.github.com/lyouthzzz/ws-gateway/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lyouthzzz%2Fws-gateway/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":272878320,"owners_count":25008336,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-30T02:00:09.474Z","response_time":77,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["gateway","go","golang","grpc","kratos","websocket"],"created_at":"2024-11-19T21:44:59.937Z","updated_at":"2026-03-02T22:02:22.299Z","avatar_url":"https://github.com/lyouthzzz.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ws-gateway\n\n## design\n\n- [谈谈对长连接网关架构的设计](https://younman.com/2022/11/10/%E8%B0%88%E8%B0%88%E5%AF%B9%E9%95%BF%E8%BF%9E%E6%8E%A5%E7%BD%91%E5%85%B3%E6%9E%B6%E6%9E%84%E7%9A%84%E8%AE%BE%E8%AE%A1/)\n- [谈谈对长连接网关架构的设计（二）](https://younman.com/2022/11/24/%E8%B0%88%E8%B0%88%E5%AF%B9%E9%95%BF%E8%BF%9E%E6%8E%A5%E7%BD%91%E5%85%B3%E6%9E%B6%E6%9E%84%E7%9A%84%E8%AE%BE%E8%AE%A1%EF%BC%88%E4%BA%8C%EF%BC%89/)\n\n## architecture\n\n![架构图.png](docs/architecture.png)\n\n## build\n\n### 生成proto go 文件\n\n```\nprotoc -I. --go_out=paths=source_relative:. pkg/client/config.proto\nprotoc -I. --go_out=paths=source_relative:. pkg/server/config.proto\nprotoc -I. --proto_path=/Users/y.liu/go/src/github.com/lyouthzzz/ws-gateway/pkg --go_out=paths=source_relative:. app/ws-gateway/internal/config/config.proto\nkratos proto client --proto_path=/Users/y.liu/go/src/github.com/lyouthzzz/ws-gateway/api api/wsapi\n```\n\n### ws-gateway\n\n```bash\ndocker build --build-arg APP_NAME=ws-gateway -f deploy/docker/Dockerfile -t ws-gateway .\n```\n\n### ws-api\n\n```bash\ndocker build --build-arg APP_NAME=ws-api -f deploy/docker/Dockerfile -t ws-api .\n```\n\n## run\n\n```bash\ncd deploy/docker-compose\ndocker-compose up\n\nStarting ws-api ... done\nStarting ws-gateway ... done\nAttaching to ws-api, ws-gateway\nws-api        | 2022/11/23 15:27:42 maxprocs: Updating GOMAXPROCS=1: determined from CPU quota\nws-api        | 2022/11/23 15:27:42 gRPC server serve :8081\nws-api        | 2022/11/23 15:27:42 gateway [172.20.0.3] gRPC streaming connect\nws-gateway    | 2022/11/23 15:27:42 maxprocs: Updating GOMAXPROCS=1: determined from CPU quota\nws-gateway    | 2022/11/23 15:27:42 HTTP server serve :8080\n\n```\n\n## benchmark\n\n### 安装压测工具\n\n```bash\ngo get github.com/lyouthzzz/websocket-benchmark-cli@main\n```\n\n### case - 1\n\n- websocket客户端：1w\n- 发送间隔：1s\n- 数据大小：50b\n- 单个gRPC Streaming连接\n\n```bash\n websocket-benchmark-cli message --file testdata/50b.txt  --interval 1s --times 10000 --user 10000 --host 127.0.0.1:8080 --path /gateway/ws\n```\n\n服务客户端表现稳定\n\n```bash\ndocker stats ws-gateway\n\nCONTAINER ID   NAME         CPU %     MEM USAGE / LIMIT   MEM %     NET I/O         BLOCK I/O   PIDS\n7144b1c4efff   ws-gateway   6.86%     380.4MiB / 2GiB     18.58%    854MB / 593MB   0B / 0B     6\n```\n\n![统计图.png](docs/benchmark-50b.png)\n\n### case - 2\n\n- websocket客户端：1w\n- 发送间隔：1s\n- 数据大小：1k\n- 单个gRPC Streaming连接\n\n```bash\nwebsocket-benchmark-cli message --file testdata/1k.txt  --interval 1s --times 10000 --user 10000 --host 127.0.0.1:8080 --path /gateway/ws\n```\n\n出现瓶颈，客户端报错：write: connection timed out 原因：服务端处理消息出现瓶颈（可能是 ws-gateway -\u003e ws-api出现问题，\n但是内网gRPC-Streaming流量支持不会那么差），导致客户端写入超时。\n\n解决方案：\n\n- ws-gateway -\u003e ws-api benchmark\n- 增加ws-api节点\n\n![统计图.png](docs/benchmark-1k.png)\n\n### case-3\n\n- websocket客户端：1w\n- 发送间隔：1s\n- 数据大小：1k\n- 单个gRPC Streaming连接\n\ncase-2版本的性能问题发现了，罪魁祸首是锁争用。\n\nhttps://github.com/lyouthzzz/ws-gateway/blob/main/app/ws-gateway/internal/upstream/grpc_streaming.go#L81\n\n```go\nfunc (upstream *gRPCStreamingUpstream) Send(msg *exchange.Msg) error {\nreturn upstream.msgc.SendMsg(msg)\n}\n```\n\n1w个websocket goroutine会调用gRPCStreaming.SendMsg()，里面会存在锁争用问题。\n\n优化方案：\n使用chan buffer缓冲（channel实现对锁有做优化手段），增加吞能力。开单独的写goroutine发送消息，避免锁争用。\n\n```go\nfunc NewGRPCStreamingUpstream(opts ...GRPCStreamingUpstreamOption) (Upstream, error) {\nup := \u0026gRPCStreamingUpstream{}\n...\n\ngo up.sendMsg()\ngo up.recvMsg()\n\nreturn up, nil\n}\n\n// todo ??? use chan buffer or send gRPC Streaming sync\nfunc (upstream *gRPCStreamingUpstream) sendMsg() {\nfor msg := range upstream.sendMsgChan {\n_ = upstream.msgc.SendMsg(msg)\n}\n}\n```\n\n![统计图.png](docs/benchmark-1k-2.png)\n\n## 性能瓶颈\n\n## 优化\n\n- ws-gateway \u003c-\u003e ws-api使用多个gRPC Streaming通道交换数据\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flyouthzzz%2Fws-gateway","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flyouthzzz%2Fws-gateway","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flyouthzzz%2Fws-gateway/lists"}