基础使用
apisix路由规则灰度实现
2条规则
规则1 优先级10
规则2 优先级11 配置客户端ip 为公司
效果 公司ip访问规则2 其他ip 访问规则1
注意事项
apisix: 任何匹配多于 uri 的路由都被认为是相等的,并应按优先级加以区分。
注意:当 Route 和 Service 都开启同一个插件时,Route 参数的优先级是高于 Service 的。
插件优先级
Consumer > Route > Service
如果再Consumer 配置了认证,而route没有开启认证,则无法访问
插件:
限流
1 2 3 4 5 6 7 8
| "plugins": { "limit-count": { #限流 "count": 2, #次数 "time_window": 3, # 限流后恢复时间 "rejected_code": 404, #限流返回code "key": "remote_addr" } }
|
ip拦截
1 2 3 4 5 6 7
| "ip-restriction": { "blacklist": [ "xx.xx.xxx.xx" ], "disable": false, "message": "想搞事?" }
|
response-rewrite
添加返回头
可自定义返回跨域头
1 2 3 4 5
| "response-rewrite": { "headers": { "X-Server-AAAAA": 666 } }
|
proxy-rewrite
上游代理信息重写,支持请求头重写
1 2 3 4 5 6
| "proxy-rewrite": { "regex_uri": [ "^/micro/app/xxx(.*)$", "/" ] }
|
跳转
1 2 3 4 5 6
| "redirect": { "append_query_string": false, "encode_uri": false, "ret_code": 307, "uri": "https://xxxx/micro/app/xxx$is_args$args" }
|
一些网关配置错误信息,可据此告警
1 2 3 4 5 6 7
| 2021/12/28 17:15:08 [error] 47#47: *4057755 [lua] config_etcd.lua:569: failed to fetch data from etcd: failed to check item data of [/apisix/routes] err:failed to check the configuration of plugin response-rewrite err: invalid base64 content, etcd key: /apisix/routes, context: ngx.timer 2021/12/28 17:14:58 [error] 46#46: *4065775 [lua] init.lua:520: http_access_phase(): failed to set upstream: no valid upstream node, client: xxxxxxxx, server: _, request: "GET /favicon.png HTTP/1.1", host: "xxxxxxm", referrer: "http://xxxxxxx" 2021/12/28 17:15:08 [error] 46#46: *4057695 [lua] config_etcd.lua:569: failed to fetch data from etcd: failed to check item data of [/apisix/routes] err:failed to check the configuration of plugin response-rewrite err: invalid base64 content, etcd key: /apisix/routes, context: ngx.timer
failed to fetch data from etcd failed to set upstream
|
基于apisix自定义插件实现无上游服务
需求: 前端阿里云的nginx需要迁移至腾讯云
技术选型:apisix充当网关
原因:在原有nginx中维护了大量灰度判断配置,大多是由uri判断+2个参数判断,所以非常繁琐,也不好观测,因为apisix便捷的路由配置管理,实现现有灰度配置非常轻松,且在实测中NGINX网关在高并发下更新配置会出现502的错误
在迁移时发现因为apisix-dashboard本身存在一些缓存的情况,且考虑需要备份和回滚路由,所以单独起了django项目充当apisix管理后台,实现路由的管理
前端情况:大部分应用使用dom https://www.w3cschool.cn/javascript/js-htmldom.html ,每个dom只有10几k大小,在初始选型中,将pod作为单个应用的最小单位,方便单个应用管理,作用是只返回一个dom文件
1 2
| FROM registry.cn-hangzhou.aliyuncs.com/xxxxx/nginx:stable-alpine-v1 COPY index.html /usr/share/nginx/html/index.html
|
导致最后维护了500+ pod,后又因腾讯云托管集群是按照资源管理数量收费的,比较傻逼
插件开发
https://apisix.apache.org/zh/docs/apisix/plugin-develop
https://apisix.apache.org/zh/docs/apisix/architecture-design/apisix/
https://github.com/apache/apisix/blob/35269581e21473e1a27b11cceca6f773cad0192a/apisix/plugins/limit-count.lua#L177
https://apisix.apache.org/zh/blog/2022/02/16/file-logger-api-gateway/
可参考proxy-rewrite插件实现
最初在实践中发现apisix可以实现使用go-runner来实现直接返回前端页面,所以第一版是go-runner做的,上到开发环境压测后,发现性能不佳,达不到生产需求
再到后面,发现可以使用原生lua来实现插件,且apisix提供了请求在各阶段的方法实现
下么是参考官方文档和一些插件写一个直接返回dom的自定义插件,非常简单
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| local ngx = ngx local core = require("apisix.core") local plugin = require("apisix.plugin")
local schema = { type = "object", properties = { body = { description = "body for response must base64", type = "string", } }, required = {"body"}, }
local plugin_name = "return-dom"
local _M = { version = 0.1, priority = -6000, name = plugin_name, schema = schema, }
function _M.check_schema(conf, schema_type) return core.schema.check(schema, conf) end
function _M.rewrite(conf, ctx) core.response.set_header("Content-Type", "text/html") return 200, ngx.decode_base64(conf.body) end
return _M
|
对应service
1 2 3 4 5 6 7 8
| { "name": "xxx", "plugins": { "return-dom": { "body": "BASE_64 STR" } } }
|
对应路由
1 2 3 4 5 6 7 8 9 10
| { "uris": [ "/*" ], "name": "xxx", "priority": 30, "host": "dev.xxx.com", "service_id": "4", "status": 1 }
|
apisix-dashboard临时修改插件内容:
默认dashboard只支持内置的插件,如果要修改,就要改dashboard配置文件
在pod /usr/local/apisix-dashboard/conf/schema.json 文件plugins中添加return-dom的配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| "plugins": { "return-dom": { "schema": { "properties": { "body": { "type": "string" } }, "required": [ "body" ], "type": "object" } } }
|
实现后丢失的功能
- 上游负载均衡所有算法支持(轮询,加权轮询,最小链接等)
- 一些依赖上游的插件可能没法使用了(暂时没有用到这些插件)
权重实现
根据权重返回dom
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| local function randomByWeight(t) `` ``local totalWeight = ``0 ``for` `i, item in ipairs(t) ``do ``local p = item.weight ``totalWeight = totalWeight + p ``end `` ``local r = math.random() * totalWeight ``totalWeight = ``0 ``for` `i, item in ipairs(t) ``do ``local p = item.weight ``totalWeight = totalWeight + p ``if` `totalWeight >= r then ``return` `item[``1``] ``end ``end end local testtable = { { weight = ``50``, { dom = ``"A"` `} }, ``{ weight = ``50``, { dom = ``"B"` `} } } print(randomByWeight(testtable).dom)
|