本文講述 OpenResty api網關設計,主要涉及api網關介紹、openresty api網關 請求路由(路由判斷、路由重寫、服務判斷、限流)、授權驗證(統一認證)、動態Upstream 以及這三部分理論簡單實現的Api網關和Api網關admin。
1、什么是api網關
在這個微服務這么火的時代,隨之api網關常常被提到。我們知道在微服務架構風格中,一個大應用被拆分成為了多個小的服務並提供 Rest Api 風格的接口來被 H5, Android, IOS 應用調用,由api網統一關管理這些接口的方方面面,那么什么才是api網關?
百度上針對於 API 網關有如下介紹:
API網關是一個服務器,是系統的唯一入口。從面向對象設計的角度看,它與外觀模式類似。API網關封裝了系統內部架構,為每個客戶端提供一個定制的API。它可能還具有其它職責,如身份驗證、監控、負載均衡、緩存、請求分片與管理、靜態響應處理。 API網關方式的核心要點是,所有的客戶端和消費端都通過統一的網關接入微服務,在網關層處理所有的非業務功能。通常,網關也是提供REST/HTTP的訪問API。服務端通過API-GW注冊和管理服務。
2、OpenResty api網關
OpenResty 是一個基於 Nginx 與 Lua 的高性能 Web 平台,其內部集成了大量精良的 Lua 庫、第三方模塊以及大多數的依賴項。用於方便地搭建能夠處理超高並發、擴展性極高的動態 Web 應用、Web 服務和動態網關。
OpenResty 通過匯聚各種設計精良的 Nginx 模塊(主要由 OpenResty 團隊自主開發),從而將 Nginx 有效地變成一個強大的通用 Web 應用平台。這樣,Web 開發人員和系統工程師可以使用 Lua 腳本語言調動 Nginx 支持的各種 C 以及 Lua 模塊,快速構造出足以勝任 10K 乃至 1000K 以上單機並發連接的高性能 Web 應用系統。
開發api網關使用到的 OpenResty 一個重要知識:OpenResty 對於一個請求的處理流程。Nginx 把一個請求分為不同的階段,從而讓第三方模塊通過掛載行為在不同的階段來定制自己的行為;OpenResty 擁有同樣的特性,不過在不同階段掛載的是 Lua 腳本。

在不同的階段直接完成大部分典型處理了。
set_by_lua: 流程分之處理判斷變量初始化
rewrite_by_lua: 轉發、重定向、緩存等功能(例如特定請求代理到外網)
access_by_lua: IP准入、接口權限等情況集中處理(例如配合iptable完成簡單防火牆)
content_by_lua: 內容生成
header_filter_by_lua: 應答HTTP過濾處理(例如添加頭部信息)
body_filter_by_lua: 應答BODY過濾處理(例如完成應答內容統一成大寫)
log_by_lua: 回話完成后本地異步完成日志記錄(日志可以記錄在本地,還可以同步到其他機器)
那么我們可以開始的api網關設計了:
init_by_lua_block 加載路由信息、服務信息到lua_shared_dict。
init_worker_by_lua_block 持久化通過apiadmin新增或者修改的路由、服務信息到磁盤、服務健康檢查。
rewrite_by_lua_block 根據url規則匹配路由信息和服務信息並賦值到ngx上下文
access_by_lua_block 進行統一授權
opengate_upstream 通過ngx上下文的url服務信息通過ngx_balancer.set_current_peer對服務進行轉發。
adminapi 提供路由、服務信息管理restful接口
示例代碼如下:
lua_shared_dict url_dict 5m;
lua_shared_dict balancer_dict 5m;
init_by_lua_block {
opengate = require 'opengate.openpoint'
opengate.init()
}
init_worker_by_lua_block{
opengate.cofigsync()
opengate.heathcheck()
}
upstream opengate_upstream {
server 0.0.0.1;
balancer_by_lua_block {
opengate.balancer()
}
keepalive 60;
}
server {
listen 443 http2 ssl default_server;
server_name _;
ssl on;
ssl_certificate server.crt;
ssl_certificate_key server.key;
location / {
default_type application/json;
rewrite_by_lua_block {
opengate.rewrite()
}
access_by_lua_block {
opengate.access()
}
proxy_pass http://opengate_upstream;
proxy_intercept_errors on;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
error_page 404 /404.html;
location = /404.html {
root html;
}
}
server {
listen 8800;
server_name _;
location / {
default_type application/json;
content_by_lua_block {
opengate.adminapi()
}
}
location /robots.txt {
return 200 'User-agent: *\nDisallow: /';
}
}
通過如上我們就實現一個簡單的api網關。
最后推薦下github上一個開源的openresty大作 https://github.com/Kong/kong
