|
@@ -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
|