Smart-SSO分布式部署踩坑实录:从POM依赖改写到Nginx配置的那些‘坑’
Smart-SSO分布式部署实战从POM依赖到Nginx配置的深度避坑指南去年我们团队在推进Smart-SSO分布式改造时原以为按照官方文档两小时就能搞定结果整整折腾了三天。这篇文章不是标准教程而是我们踩过的坑和填坑经验。如果你正在实施类似项目这些实战细节或许能帮你省下不少时间。1. 环境准备阶段的隐藏陷阱很多人以为环境搭建就是装个Redis和Nginx但实际部署时我们发现版本兼容性是个大坑。官方文档写着Redis 6.2.1和Nginx 1.23.2但我们的测试环境跑的是Redis 6.0.10结果出现了诡异的连接超时问题。关键组件版本对照表组件官方推荐版本实测兼容版本范围不兼容表现Redis6.2.16.0.16 / 7.0.0以下连接池频繁超时Nginx1.23.21.21.0X-Forwarded-For头丢失Spring Boot-2.7.x自动配置冲突提示生产环境强烈建议使用Docker固定版本避免在我的机器上能跑的问题。我们最终采用的组合是Redis 6.2.6 Nginx 1.23.3。本地Hosts配置也是个暗坑。文档里用的server.smart-sso.com和demo.smart-sso.com但实际开发时# 错误配置缺少IPv6条目 127.0.0.1 server.smart-sso.com # 正确配置需包含IPv6 127.0.0.1 server.smart-sso.com ::1 server.smart-sso.com少了IPv6条目会导致某些浏览器随机性解析失败特别是MacOS下的Chrome。2. POM依赖的血泪教训依赖替换看起来简单但实际远比smart-sso-starter-client改成smart-sso-starter-client-redis复杂。我们遇到了三个典型问题依赖顺序问题必须确保redis-starter在spring-boot-starter-data-redis之前版本锁定缺失多模块项目需要统一管理版本号测试依赖污染spring-boot-starter-test会引入内存Redis这是我们的最终配置方案!-- 正确依赖顺序示例 -- dependency groupIdcom.smart-sso/groupId artifactIdsmart-sso-starter-client-redis/artifactId version${smart-sso.version}/version exclusions exclusion groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-data-redis/artifactId /exclusion /exclusions /dependency dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-data-redis/artifactId /dependency最坑的是smart-sso-starter-client-redis的自动配置会在特定条件下失效。当你的应用同时有EnableCaching注解时必须在application.yaml显式声明smart: sso: redis: enable: true # 必须显式开启3. Redis配置的魔鬼细节官方示例的Redis配置过于简单实际生产环境需要关注更多参数。我们经历过连接泄漏导致的生产事故最终总结出这些关键配置项高可用Redis连接配置模板spring: redis: host: redis-cluster.example.com port: 6379 timeout: 3000ms # 重要默认无限等待 lettuce: pool: max-active: 20 max-wait: 1000ms max-idle: 8 min-idle: 2 shutdown-timeout: 100ms cluster: nodes: - 10.0.0.1:6379 - 10.0.0.2:6379 max-redirects: 3注意Smart-SSO的Token存储使用单独的Redis DB不要和其他业务数据混用。我们曾因为DB冲突导致Token莫名失效。连接超时问题排查时这几个命令很有用# 查看Redis连接数 redis-cli info clients # 监控Redis命令 redis-cli monitor # 测试网络延迟 redis-cli --latency -h your-redis-host4. Nginx配置的进阶技巧反向代理配置不当会导致一系列诡异问题特别是获取真实IP和Session保持。这是我们的优化版配置upstream sso_servers { zone sso_servers 64k; server 10.31.88.96:8090 weight3; server 10.31.88.96:8091; keepalive 32; # 长连接提升性能 } server { listen 80; server_name server.smart-sso.com; # 真实IP传递多层代理场景 set_real_ip_from 10.0.0.0/8; real_ip_header X-Forwarded-For; real_ip_recursive on; location / { proxy_pass http://sso_servers; proxy_http_version 1.1; proxy_set_header Connection ; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; # 超时设置 proxy_connect_timeout 3s; proxy_read_timeout 10s; # 健康检查 health_check interval5s fails3 passes2 uri/health; } }特别提醒几个容易忽略的点proxy_http_version 1.1和Connection 必须配合使用才能启用keepalive权重分配(weight)可以配合金丝雀发布健康检查路径需要与后端应用匹配我们在压力测试时发现缺少real_ip_recursive on会导致某些场景下获取的IP是内网代理IP而非真实客户端IP。5. 分布式验证的完整方案验证环节不能只检查是否能登录需要系统性地验证基础功能验证多浏览器同时登录/登出跨子域名的单点登录Token过期自动刷新分布式场景验证// 验证代码示例 Test public void testTokenSync() { // 实例1写入 String token ssoClient1.login(user1, pass); // 实例2读取 UserInfo user ssoClient2.validate(token); assertNotNull(user); // 实例1注销 ssoClient1.logout(token); // 实例2验证失效 assertThrows(SsoException.class, () - ssoClient2.validate(token)); }性能测试要点模拟Redis网络抖动时的降级表现高并发Token续期场景Nginx reload时的请求无损我们自研了一套验证工具集关键指标包括Token同步延迟 ≤ 50ms故障转移时间 ≤ 3s99%登录响应时间 ≤ 300ms6. 监控与排错体系建设上线后我们建立了完整的监控体系这几个指标最为关键Smart-SSO核心监控指标指标名称采集方式报警阈值应对措施Token生成QPSPrometheus突增50%检查是否遭到爬虫Redis连接池等待数Micrometer持续5扩容连接池或Redis集群Nginx upstream响应时间Nginx PlusP99500ms优化后端服务或增加节点跨DC同步延迟自定义探针200ms持续5min检查专线网络排错时这个命令组合能快速定位问题# 查看Nginx路由情况 tail -f /var/log/nginx/access.log | grep 502\|503\|504 # 检查Redis键状态 redis-cli --scan --pattern smart:sso:* | xargs redis-cli ttl # 追踪Java应用请求 arthas trace com.smart.sso.SsoController login7. 生产环境特别注意事项经过三个月的生产运行我们总结出这些经验冷启动问题当Redis集群全部重启后所有Token失效。解决方案是逐步重启应用实例或者实现本地Token缓存降级。地域延迟跨国部署时建议采用区域化Redis集群中心同步的方案。我们在东京和法兰克福节点就曾因为150ms的网络延迟导致登录超时。安全加固禁用Redis的CONFIG命令为Smart-SSO的Redis键设置单独密码Nginx配置WAF规则防护暴力破解灰度发布策略先更新1个服务端实例观察15分钟无异常再全量客户端保持向后兼容文档陷阱官方文档的proxy_set_header配置在某些Nginx版本会导致Host头重复。我们最终采用的方案是proxy_set_header Host $http_host; # 替代原来的$host在阿里云环境还遇到个特别案例他们的SLB会修改X-Forwarded-For需要额外配置set_real_ip_from 100.64.0.0/10; # 阿里云内网段