APISIX 预研

nginx + lua + etcd = apisix

APISIX 预研

https://apisix.apache.org/zh/docs/apisix/getting-started

当前架构

组件

  • openrestry-1.11.2.5 , 基于 nginx 的反向代理

    • ngx_http_dyups_module, dynamic upstreams 动态变更 upsteam, 用来支持 web app 的动态上下线
    • ngx_brotli, 压缩算法
  • flume, 日志收集

入站流量

DNS -> FW ----dnat----> NGINX(4 实例)G

日志收集

flume 配合定时任务将 nginx log 发送到 kafka。

其他细节

  • log_format, 自定义的 log_format.
log_format time_sessionid_json  '{'
                    '"nginx_hostname": "$hostname",'
                    '"remote_addr": "$remote_addr",'
                    '"auth_user_id": "$auth_user_id",'
                    '"username": "$username",'
                    '"sessionid": "$sessionid",'
                    '"time_local": "$time_local",'
                    '"time_iso8601": "$time_iso8601",'
                    '"request_method": "$request_method",'
                    '"uri": "$uri",'
                    '"request_uri": "$request_uri",'
                    '"request_length": $request_length,'
                    '"server_protocol": "$server_protocol",'
                    '"server_name": "$server_name",'
                    '"host_domain": "$host",'
                    '"msec": $msec,'
                    '"status": $status,'
                    '"body_bytes_sent": $body_bytes_sent,'
                    '"http_referer": "$http_referer",'
                    '"http_user_agent": "$http_user_agent",'
                    '"request_time": "$request_time",'
                    '"upstream_addr": "$upstream_addr",'
                    '"upstream_response_time": "$upstream_response_time",'
                    '"scheme": "$scheme",'
                    '"pipe": "$pipe"'
                  '}';

其中 $auth_user_id, $username, $sessionid 是动态从请求的 Cookie 中取得。

set $sessionid "null";
if ( $http_cookie ~* "sessionid=(\S+)(;.*|$)" ){
    set $sessionid  $1;
}
set $username "null";
if ( $http_cookie ~* "username=(\S+)(;.*|$)" ){
    set $username $1;
}
set $auth_user_id "null";
if ( $http_cookie ~* "_auth_user_id=(\S+)(;.*|$)" ){
    set $auth_user_id $1;
}
# nginx.conf
  limit_req_zone $binary_remote_addr zone=web:100m rate=30r/s;
  limit_req_zone $binary_remote_addr zone=home:100m rate=1r/s;
  #limit_req_zone $binary_remote_addr zone=api:100m rate=2r/s;
  limit_req_zone $cookie_sessionid zone=api_w:200m rate=1r/s;
  limit_req_zone $spider_user_agent zone=baidu_spider:100m rate=100r/s;  # 防止百度过去爬取爬虫
  limit_req_zone $binary_remote_addr zone=stop_crawler:100m rate=6r/m;  # 暂缓爬取蜜罐的爬虫

# xxx.conf
  limit_req zone=baidu_spider burst=30;

  • auth_request
    include includes/sso_com.conf;
    auth_request /sso_auth;

APISIX

基于 openresty 与 etcd 组合而成。

openresty (nginx + lua)

运行时细节

nginx 请求处理流程

  • NGX_HTTP_POST_READ_PHASE
  • NGX_HTTP_SERVER_REWRITE_PHASE
  • NGX_HTTP_FIND_CONFIG_PHASE
  • NGX_HTTP_REWRITE_PHASE
  • NGX_HTTP_POST_REWRITE_PHASE
  • NGX_HTTP_PREACCESS_PHASE
  • NGX_HTTP_ACCESS_PHASE
  • NGX_HTTP_TRY_FILES_PHASE
  • NGX_HTTP_CONTENT_PHASE
  • NGX_HTTP_LOG_PHASE

openresty 请求处理流程

  • init_by_lua
  • set_by_lua
  • rewrite_by_lua
  • access_by_lua
  • content_by_lua
  • header_filter_by_lua
  • body_filter_by_lua
  • log_by_lua

flow

apisix 请求处理流程

    server {
        listen 0.0.0.0:9080 default_server reuseport;
        listen [::]:9080 default_server reuseport;
        listen 0.0.0.0:9443 ssl default_server http2 reuseport;
        listen [::]:9443 ssl default_server http2 reuseport;

        server_name _;

        ssl_certificate_by_lua_block {
            apisix.http_ssl_phase()
        }

        proxy_ssl_name $upstream_host;
        proxy_ssl_server_name on;

        location / {
            access_by_lua_block {
                apisix.http_access_phase()
            }

            proxy_pass      $upstream_scheme://apisix_backend$upstream_uri;

            header_filter_by_lua_block {
                apisix.http_header_filter_phase()
            }

            body_filter_by_lua_block {
                apisix.http_body_filter_phase()
            }

            log_by_lua_block {
                apisix.http_log_phase()
            }
        }

---
    upstream apisix_backend {
        server 0.0.0.1;

        balancer_by_lua_block {
            apisix.http_balancer_phase()
        }

        keepalive 320;
        keepalive_requests 1000;
        keepalive_timeout 60s;
    }

nginx.conf 流程相关的关键配置。

关键点在两个地方

  1. apisix.http_access_phase()
  2. apisix.http_balancer_phase()

apisix.http_access_phase

1. 查到 route
2. 执行 plugin (rewrite, access)
3. 通过 route 查找关联的 upstream
4. 尝试获取后端 server

apisix.http_balancer_phase

1. 使用 http_access_phase 得到的 upstream,访问后端节点

基本结论

  1. auth_request 暂不支持

github issues 5210

  1. apisix 默认配置和现配置有些不一样,需要对比测试。

  2. 日志收集可以通过 kafka-logger 来做,不需要打到本地之后通过 flume 处理后发送到 kafka。

  3. dashboard 需要搭配 etcd, 没有 etcd 就相当与原生的 openresty, 没啥优势。

  4. 性能不会比 openresty 更好。

  5. 如何实现应用的平滑上下线,可通过主动+被动的健康探测来实现,而不是通过主动修改 upstream.

  • 缩扩容时需要修改 upstream

备注

  • 现有配置基于 nginx_web(3fe066ca369781b3300ea634ffd2df6e76f52918)
  • apisix lts (2.10.0)

REF