推荐一个 比 spring cloud 更好用的 API 网关。它是一个低代码 API 网关。
https://github.com/fiber-net-gateway/fiber-net-gateway
同样是使用 java 开发,相比与 SpringCloud Zuul,它有很多 鲜明的特点。
它实现了一个灵活好用的脚本 解释器(interpreter、vm),通过脚本代替配置文件、并且支持动态更新、对于用户来说更加灵活、更加直观。毕竟API 网关的用户都是程序员,看简单的代码比看一堆复杂的 YAML 配置来得更加直观。
脚本解释器是以协程的方式运行的,不占用线程资源。底层也是基于 Netty NIO 开发的,除了 EVENT_LOOP 外无其它业务线程,利用了 NETTY 零拷贝技术,性能非常高,开销很低。
整个项目只依赖 netty 和 jackson 两个第三方库,无其它依赖。核心代码也只有 14000 行,在内部实现了 虚拟机、异步带连接池的?http client ,http server,依赖注入、reactive 异步事件等特性,非常利用阅读和学习。
git clone https://github.com/fiber-net-gateway/fiber-net-gateway.git
cd fiber-net-gateway
mvn package -DskipTests
cd fiber-gateway-example/target
mkdir conf
cat > conf/fiber-net.gs << EOF
directive fy from http "https://fanyi.baidu.com";
directive bd from http "https://www.baidu.com";
if(req.getMethod() == "POST") {
fy.proxyPass({
path: "/v2transapi",
query: "from=en&to=zh",
method: "POST",
headers: {
"X-Fiber-Project": null
}
});
} else {
let res = bd.request({path: "/", headers: {"User-Agent": "curl/7.88.1"}});
resp.setHeader("Content-Type", "text/html");
resp.send(res.status, res.body);
}
EOF
java -jar fiber-gateway-example-1.0-SNAPSHOT.jar conf
# 使用 post 请求,反向代理到百度翻译 (反向代理会透传 downstream 内容)
curl 127.0.0.1:16688 -XPOST
# 使用其它请求,返回百度主页。(请求模式,不会透传 downstream)。
curl 127.0.0.1:16688 -XGET
返回内容:?
$ curl 127.0.0.1:16688 -i
HTTP/1.1 200 OK
Content-Type: text/html
date: Mon, 18 Dec 2023 14:58:40 GMT
server: fiber-net(fn)/1.0-SNAPSHOT/549a404dcaee9bc2
content-length: 2443
<!DOCTYPE html>
<!--STATUS OK--><html> <head><meta http-equiv=content-type content=text/html;charset=utf-8><meta http-equiv=X-UA-Compatible content=IE=Edge><meta content=always name=referrer><link rel=stylesheet type=text/css href=https://ss1.bdstatic.com/5eN1bjq8AAUYm2zgoY3K/r/www/cache/bdorz/baidu.min.css><title>百度一下,你就知道</title></head> <body link=#0000cc> <div id=wrap id=head> <div class=head_wrapper> <div class=s_form> <div class=s_form_wrapper> <div id=lg> <img hidefocus=true src=//www.baidu.com/img/bd_logo1.png width=270 height=129> </div> <form id=form name=f action=//www.baidu.com/s class=fm> <input type=hidden name=bdorz_come value=1> <input type=hidden name=ie value=utf-8> <input type=hidden name=f value=8> <input type=
hidden name=rsv_bp value=1> <input type=hidden name=rsv_idx value=1> <input type=hidden name=tn value=baidu><span class="bg s_ipt_wr"><input id=kw name=wd class=s_ipt value m m
axlength=255 autocomplete=off autofocus=autofocus></span><span class="bg s_btn_wr"><input type=submit id=su value=百度一下 class="bg s_btn" autofocus></span> </form> </div> </div> <di
v id=u1> <a href=http://news.baidu.com name=tj_trnews class=mnav>新闻</a> <a href=https://www.hao123.com name=tj_trhao123 class=mnav>hao123</a> <a href=http://map.baidu.com name=tj_tr
map class=mnav>地图</a> <a href=http://v.baidu.com name=tj_trvideo class=mnav>视频</a> <a href=http://tieba.baidu.com name=tj_trtieba class=mnav>贴吧</a> <noscript> <a href=http://www
.baidu.com/bdorz/login.gif?login&tpl=mn&u=http%3A%2F%2Fwww.baidu.com%2f%3fbdorz_come%3d1 name=tj_login class=lb>登录</a> </noscript> <script>document.write('<a href="http://ww
w.baidu.com/bdorz/login.gif?login&tpl=mn&u='+ encodeURIComponent(window.location.href+ (window.location.search === "" ? "?" : "&")+ "bdorz_come=1")+ '" name="tj_login" class="lb">登录/a>');
</script> <a href=//www.baidu.com/more/ name=tj_briicon class=bri style="display: block;">更多产品</a> </div> </div> </div> <div id=ftCon> <div id=ftConw> <p id=lh> <a
href=http://home.baidu.com>关于百度</a> <a href=http://ir.baidu.com>About Baidu</a> </p> <p id=cp>©2017 Baidu <a href=http://www.baidu.com/duty/>使用百度前必读</a> <a href=http://jianyi.baidu.com/ class=cp-feedback>意见反馈</a> 京ICP证030173号 <img src=//www.baidu.com/img/gs.gif> </p> </div> </div> </div> </body> </html>
每次请求,fiber-net.gs 都会被执行一次。也可以在 conf 目录下放置其它 .gs 文件 通过 request header "X-Fiber-Project" 执行被执行的文件名。(如 ttt.gs)
### conf/ttt.gs 文件会被执行,不指定则执行 fiber-net.gs
curl 127.0.0.1:16688 -H'X-Fiber-Project: ttt'