ソースを参照

tenant_router

peterguo 2 ヶ月 前
コミット
eeb492fa37
3 ファイル変更102 行追加0 行削除
  1. 1 0
      docker-compose.yml
  2. 96 0
      openresty/lua/tenant_router.lua
  3. 5 0
      openresty/nginx.conf

+ 1 - 0
docker-compose.yml

@@ -499,6 +499,7 @@ services:
         - ${OPENRESTY_HOST_LOG_PATH}:/var/log/nginx
         - ${OPENRESTY_SITES_PATH}:/etc/nginx/sites-available
         - ${OPENRESTY_SSL_PATH}:/etc/nginx/ssl
+        - ${OPENRESTY_LUA_PATH}:/usr/local/openresty/lualib/resty
       ports:
         - "${OPENRESTY_HOST_HTTP_PORT}:80"
         - "${OPENRESTY_HOST_HTTPS_PORT}:443"

+ 96 - 0
openresty/lua/tenant_router.lua

@@ -0,0 +1,96 @@
+local redis = require "resty.redis"
+
+-- 定义Redis连接参数
+local REDIS_HOST = "redis-host"
+local REDIS_PORT = 6379
+local REDIS_TIMEOUT = 1000  -- 1秒超时
+
+local ngx_shared = ngx.shared
+local env_cache = ngx_shared.env_cache  -- 需在nginx.conf定义共享内存lua_shared_dict env_cache 10m;
+
+local _M = {}
+
+-- 设置后端upstream
+function set_upstream(tenant, env)
+    if env == "prod" then
+        ngx.var.upstream = "backend_prod"
+    elseif env == "dev" then
+        ngx.var.upstream = "backend_dev"
+    else
+        ngx.log(ngx.ERR, "Upstream not found for env: " .. tostring(env))
+        return ngx.exit(ngx.HTTP_BAD_REQUEST)  -- 使用标准HTTP状态码
+    end
+    ngx.log(ngx.INFO, "Backend routing: ", "tenant=", tenant, "env=", env, ", upstream=", ngx.var.upstream)
+end
+
+-- 设置前端upstream
+function set_frontend_upstream(tenant, env)
+    if env == "prod" then
+        ngx.var.frontend_upstream = "frontend_prod"
+    elseif env == "dev" then
+        ngx.var.frontend_upstream = "frontend_dev"
+    else
+        ngx.log(ngx.ERR, "Frontend upstream not found for env: " .. tostring(env))
+        return ngx.exit(ngx.HTTP_BAD_REQUEST)  -- 使用标准HTTP状态码
+    end
+    ngx.log(ngx.INFO, "Frontend routing: ", "tenant=", tenant, "env=", env, ", frontend_upstream=", ngx.var.frontend_upstream)
+end
+
+-- 根据租户信息获取环境变量
+function get_env(tenant)
+    local cache_key = "tenant_identification_location_" .. tenant
+    local cache_res = env_cache:get(cache_key)
+    if cache_res then
+        ngx.log(ngx.DEBUG, "Cache hit: ", cache_key)
+        return cache_res
+    end
+
+    local red = redis:new()
+    red:set_timeouts(REDIS_TIMEOUT, REDIS_TIMEOUT, REDIS_TIMEOUT)
+
+    local ok, connect_err = red:connect(REDIS_HOST, REDIS_PORT)
+    if not ok then
+        ngx.log(ngx.ERR, "Redis connect failed: ", connect_err)
+        return ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)  -- 使用标准HTTP状态码
+    end
+
+    local env = red:get(cache_key)
+    if not env then
+        ngx.log(ngx.ERR, "No environment found for tenant:", tenant)
+        red:set_keepalive(10000, 100)  -- 归还连接到连接池
+        return ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)  -- 使用标准HTTP状态码
+    end
+
+    red:set_keepalive(10000, 100)
+    env_cache:set(cache_key, env, 60)  -- 缓存60秒
+
+    return env
+end
+
+-- 处理API请求的路由逻辑
+function _M.route_by_tenant_for_api()
+    local tenant = ngx.req.get_headers()["X-Tenant"] or ngx.req.get_uri_args()["tenant"]
+
+    if not tenant or tenant == "" then
+        ngx.log(ngx.ERR, "Missing tenant identifier")
+        return ngx.exit(ngx.HTTP_BAD_REQUEST)  -- 使用标准HTTP状态码
+    end
+
+    local env = get_env(tenant)
+    set_upstream(tenant, env)
+end
+
+-- 处理前端请求的路由逻辑
+function _M.route_by_tenant_for_frontend()
+    local tenant = ngx.req.get_headers()["X-Tenant"] or ngx.req.get_uri_args()["tenant"]
+
+    if not tenant or tenant == "" then
+        ngx.log(ngx.ERR, "Missing tenant identifier")
+        return ngx.exit(ngx.HTTP_BAD_REQUEST)  -- 使用标准HTTP状态码
+    end
+
+    local env = get_env(tenant)
+    set_frontend_upstream(env)
+end
+
+return _M

+ 5 - 0
openresty/nginx.conf

@@ -91,6 +91,11 @@ http {
     ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
     ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS';
 
+    # 定义共享内存区域
+    lua_shared_dict env_cache 10m;
+    # 添加Lua脚本路径
+    lua_package_cpath "/usr/local/openresty/lualib/resty/?.so;;";
+
     include /etc/nginx/conf.d/*.conf;
     include /etc/nginx/sites-available/*.conf;