网易首页 > 网易号 > 正文 申请入驻

这个程序员用247行代码,把API网关的底裤扒了

0
分享至


API网关一直是基础设施里的黑箱。你知道它管认证、限流、路由,但内部怎么运转,大多数人只能猜。一位开发者决定亲手拆掉这个黑箱——用Go的标准库net/http(网络/超文本传输协议),从零写了一个网关。没有框架,247行代码,全在GitHub上公开。

这个项目叫simple-api-gateway。作者的核心洞察很直白:API网关本质上就是一个可配置的http.Handler(超文本传输协议处理器)。认证、限流、链路追踪,全是包在反向代理外面的中间件。堆够多,就是网关。

中间件链:俄罗斯套娃式编程

Go的中间件模式长这样:

type Middleware func(http.Handler) http.Handler

一个中间件接收一个处理器,返回一个新处理器,在新处理器里干点前置或后置的事。这种设计让测试变得极其简单——不需要起真服务器,直接调ServeHTTP(服务超文本传输协议)方法就能跑单元测试。

Gateway结构体直接实现了http.Handler接口:

type Gateway struct { config *types.Config router *Router middleware map[string]Middleware }

ServeHTTP方法里只做三件事:匹配路由、组装中间件链、执行。没有魔法,纯结构体加方法。作者特意强调这一点,因为市面上太多网关把简单问题复杂化,搞得开发者以为必须上Kubernetes(容器编排平台)才能玩。

路由设计:精确度优先的暴力匹配

路由器支持三种路径模式:精确匹配(/users)、参数化(/users/:id)、前缀通配(/users/*)。启动时按精确度排序,确保更具体的规则永远优先。

匹配逻辑是遍历:

func (ro *Router) Match(r *http.Request) (*types.Route, map[string]string) { for _, route := range ro.routes { // sorted: exact > param > prefix if matched, params := matchPath(route.Path, r.URL.Path); matched { if methodAllowed(route.Methods, r.Method) { return &route, params } } } return nil, nil }

作者承认这里有个故意留下的缺口::param片段能匹配并用于路由,但提取出的参数值不会注入请求上下文。对学习网关模式来说,这个取舍可以接受,但生产环境肯定得补。


路由命中后,buildChain方法把配置的中间件组装成链。注意循环是倒着走的——这样第一个列出的中间件会成为最外层,最后列出的紧贴上游服务。这个细节很容易写反,导致中间件执行顺序和配置顺序不一致。

反向代理:标准库就够了

核心转发逻辑用了net/http/httputil里的ReverseProxy(反向代理)。作者原话是:「Go的标准库已经做了90%的工作,很多人却不知道。」

代理配置里有个细节:Director函数负责修改请求,把原始URL换成上游地址。Transport(传输层)可以自定义,比如加连接池、TLS(传输层安全)配置。作者用了默认的,但留了扩展点。

错误处理也走标准库:上游返回5xx时,ReverseProxy会自动把错误写回响应。想要自定义错误页?包一层中间件拦截状态码就行。

限流实现:令牌桶的朴素版

项目里带了个基于内存的限流中间件,用令牌桶算法。每个路由独立计数,桶大小和填充速率从配置读。

实现用了sync.Mutex(互斥锁)保护状态,简单粗暴。作者备注:「生产环境应该用Redis(远程字典服务)集群状态,但这里为了演示核心模式,单机的够了。」

令牌桶的代码不到50行,关键逻辑是每次请求先尝试消耗令牌,不够就返回429状态码(请求过多)。没有滑动窗口的精确,但实现成本极低,适合作为教学示例。

认证中间件:JWT(JSON网页令牌)的极简解析

JWT验证中间件展示了怎么在不引入第三方库的情况下做认证。作者用了golang.org/x/crypto(加密库)的子包,手动解析token结构。

流程很标准:从Authorization头提取Bearer token,base64解码header和payload,验证签名,检查exp字段是否过期。没有刷新机制,没有权限角色,只有「这token是不是你签的」和「过期没」。

作者特意没做完整的OIDC(开放ID连接)或OAuth2(开放授权第二版)集成,理由是:「网关层的认证应该只做网关层的事。权限校验交给上游服务,否则网关会变成另一个单体。」

配置即代码:YAML(YAML ain't markup language)的取舍


路由和中间件配置用YAML文件,启动时加载。作者试过用Go代码直接写配置,但发现「改个路由要重新编译」在开发期太烦人。

YAML结构分层:顶层是网关监听地址,然后是routes数组,每个route指定路径、方法、上游地址、中间件列表。中间件参数用map[string]interface{}(字符串到任意类型的映射),类型安全靠运行时检查。

作者承认这里可以做得更好:「理想状态是配置有Schema校验,启动时就把错报出来。现在只能祈祷写YAML的人别手抖。」

测试策略:表驱动覆盖全路径

测试文件比实现文件还长。作者用了表驱动测试,每个测试用例包含请求构造、期望响应、中间件状态断言。

一个典型测试长这样:

tests := []struct { name string req *http.Request wantStatus int wantBody string }{ {"exact match", newRequest("GET", "/users"), 200, "upstream"}, {"param route", newRequest("GET", "/users/123"), 200, "123"}, {"method not allowed", newRequest("POST", "/users"), 405, ""}, }

这种写法让新增测试用例成本极低,也强迫开发者把边界情况想清楚。作者跑了90%的覆盖率,没覆盖的大多是错误分支——「比如配置文件解析失败直接log.Fatal(致命日志),这种测了也没意义。」

生产差距:作者自己列了7条

README里有个诚实的章节「Not Production Ready」。作者逐条列了缺口:没有持久化配置、没有分布式限流、没有健康检查、没有优雅关闭、没有指标暴露、没有请求日志结构化、没有TLS自动证书。

最扎心的一条:「没有文档。你现在看的这个README就是全部。」

但作者认为这些缺口恰恰是价值所在:「看完代码你就知道一个网关到底要解决哪些问题。下次用Kong或Envoy(服务代理)时,你能猜出它们内部大概怎么实现,出了问题也知道往哪挖。」

项目发布后,Hacker News(黑客新闻)上有条评论被顶到最高:「我维护了三年Kong,今天才第一次真正理解plugins是怎么加载的。」

如果让你从零写一个网关,你会先实现哪个功能——路由匹配、中间件链,还是反向代理本身?

特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相关推荐
热点推荐
光通信再出黑马!1600吨光棒+57亿订单硬核支撑

光通信再出黑马!1600吨光棒+57亿订单硬核支撑

Thurman在昆明
2026-04-10 17:37:20
霍思燕带狗泰国夺冠!肥肚三层、发际线好假,女儿出镜像女版杜江

霍思燕带狗泰国夺冠!肥肚三层、发际线好假,女儿出镜像女版杜江

冷紫葉
2026-04-08 18:12:43
世界上最穷国家:一辈子吃不上肉、自行车是豪车,靠中国逆天改命

世界上最穷国家:一辈子吃不上肉、自行车是豪车,靠中国逆天改命

椰青美食分享
2026-04-10 17:25:01
这双手,那片天(大国小家·关注就业友好型发展方式)

这双手,那片天(大国小家·关注就业友好型发展方式)

北青网-北京青年报
2026-04-10 11:44:02
新宙邦:一季度净利同比预增100.11%~117.51%

新宙邦:一季度净利同比预增100.11%~117.51%

每日经济新闻
2026-04-10 17:50:02
痛心 | 余红李牺牲!年仅45岁!

痛心 | 余红李牺牲!年仅45岁!

天津广播
2026-04-10 10:25:57
骑士不用输球了!尼克斯拿下绿军,塔图姆24+13+8,哈特成功臣

骑士不用输球了!尼克斯拿下绿军,塔图姆24+13+8,哈特成功臣

老梁体育漫谈
2026-04-10 10:05:05
吴邦国委员长之父吴忠性简介:解放前拒绝去台湾,被誉为测绘将军

吴邦国委员长之父吴忠性简介:解放前拒绝去台湾,被誉为测绘将军

兴趣知识
2026-03-24 16:24:08
刘烨也没料到,一直被自己忽视的14岁女儿,如今给他迎来无上荣光

刘烨也没料到,一直被自己忽视的14岁女儿,如今给他迎来无上荣光

揽星河的笔记
2026-04-09 17:35:39
万科前高管出任顺丰房地产总裁

万科前高管出任顺丰房地产总裁

地产微资讯
2026-04-10 16:44:30
解放台湾:上午发动统一之战,下午就发身份证?第一步登陆就很难

解放台湾:上午发动统一之战,下午就发身份证?第一步登陆就很难

人类的关注
2026-04-06 15:36:26
央视下场,官方表态,全红婵网暴风波再发酵,陈芋汐做法太高明

央视下场,官方表态,全红婵网暴风波再发酵,陈芋汐做法太高明

郭蛹包工头
2026-04-10 18:25:55
游戏厅最欠揍的玩家,宁愿放弃游戏也要把他解决了

游戏厅最欠揍的玩家,宁愿放弃游戏也要把他解决了

街机时代
2026-04-10 18:00:03
政变只是一个开始,伊朗要变天了,中国最担心的事情,恐将发生

政变只是一个开始,伊朗要变天了,中国最担心的事情,恐将发生

鱼语昱雨轩
2026-04-09 15:43:10
深圳最危险的95个旧改项目被踢出局,3年内拆不了,以后也难拆了

深圳最危险的95个旧改项目被踢出局,3年内拆不了,以后也难拆了

流苏晚晴
2026-04-10 19:04:38
中美已大吵一架,沉默6天,巴拿马外长出面,要求中国做一件事

中美已大吵一架,沉默6天,巴拿马外长出面,要求中国做一件事

策略述
2026-04-10 13:56:04
1公里路司机结算出5000元车费?上海警方破获一起诈骗网约车平台案

1公里路司机结算出5000元车费?上海警方破获一起诈骗网约车平台案

澎湃新闻
2026-04-10 12:02:27
许家印最后防线崩塌!高院下死命令:20日不交钱就彻底禁言!

许家印最后防线崩塌!高院下死命令:20日不交钱就彻底禁言!

历史伟人录
2026-03-30 18:00:12
曝曼联接触前皇马名帅,俱乐部高层冷血惹众怒,多将逼宫留卡里克

曝曼联接触前皇马名帅,俱乐部高层冷血惹众怒,多将逼宫留卡里克

体坛鉴春秋
2026-04-10 11:54:58
七十年代推行的“二简字”,虽失败,很多人的姓氏因此改变!

七十年代推行的“二简字”,虽失败,很多人的姓氏因此改变!

史之铭
2026-04-09 15:32:11
2026-04-10 21:32:49
碳基打工人
碳基打工人
坐标北京,靠咖啡续命,靠小红书下饭的普通人类。
1143文章数 8关注度
往期回顾 全部

科技要闻

马斯克狂发大火箭也养不起AI 年亏50亿美元

头条要闻

73岁骑友抄近路摔倒身亡 女儿:赔偿问题无法达成共识

头条要闻

73岁骑友抄近路摔倒身亡 女儿:赔偿问题无法达成共识

体育要闻

17岁赚了一百万美元,25岁被CBA裁员

娱乐要闻

黄景瑜王玉雯否认恋情!聚会细节被扒

财经要闻

李强主持召开经济形势专家和企业家座谈会

汽车要闻

搭载第二代刀片电池及闪充技术 腾势N8L闪充版预售35万起

态度原创

数码
艺术
时尚
游戏
公开课

数码要闻

雷神推出显示器支架机械臂N3UW-Pro,329元

艺术要闻

于小冬2026年4月油画新作《花季》

续集真的超越不了前作吗?

大话西游手游交易服热销物资第三期!一组仙器龙马号多少钱?

公开课

李玫瑾:为什么性格比能力更重要?

无障碍浏览 进入关怀版