AWS负载均衡器路由错误致CodeIgniter应用登录失败无法启动会话
这种负载均衡环境下的会话丢失问题我之前在项目里碰到过,结合你的AWS EC2+ELB+CodeIgniter架构,给你几个针对性的排查和解决步骤:
1. 开启ELB的会话粘性(会话亲和性)
默认情况下AWS ELB会随机把请求分发到后端服务器,这就会导致登录请求在服务器A创建会话后,后续请求被转发到服务器B,而B上没有对应的会话数据,自然无法验证登录状态。你可以在ELB的配置里开启基于Cookie的会话粘性,把同一用户的请求固定到同一台服务器上,直到会话过期或者粘性Cookie失效。注意要确保CodeIgniter的会话Cookie名称和ELB的粘性Cookie名称不冲突(比如ELB默认是AWSELB,CodeIgniter默认是ci_session,一般不会冲突,但最好确认下)。
2. 切换CodeIgniter的会话存储到共享后端
如果不想依赖ELB的粘性会话(比如高可用场景下服务器可能会被替换),更可靠的方式是让两台服务器共享会话数据:
- Redis/Memcached存储:在CodeIgniter的
config.php里配置会话驱动为redis或memcached,让两台服务器连接同一个AWS ElastiCache实例(或者自建的缓存服务),这样所有服务器都能读取到相同的会话数据,不管请求路由到哪台都能正常识别登录状态。 - 数据库存储:CodeIgniter原生支持数据库存储会话,你可以创建一个会话表(框架自带SQL脚本),然后让两台服务器连接同一个RDS数据库,会话数据存在数据库里,自然就能跨服务器共享。
- 避免使用默认的文件存储:文件存储的话,会话数据只存在单台服务器的本地,另一台服务器完全访问不到,这是导致你问题的核心原因之一。
3. 调整CodeIgniter的Cookie配置
检查application/config/config.php里的Cookie相关配置,确保跨服务器有效:
- 设置
$config['cookie_domain']为你的应用域名(比如.yourdomain.com,注意前面的点,这样子域名也能共享Cookie),不要留空或者设置为单台服务器的IP。 - 如果你的应用用HTTPS,把
$config['cookie_secure']设为TRUE,确保Cookie只通过HTTPS传输。 - 建议开启
$config['cookie_httponly'] = TRUE,提升Cookie的安全性,避免前端脚本篡改。
4. 验证请求路由情况
可以在两台服务器上添加日志,追踪请求到底被分发到了哪台服务器:
在CodeIgniter的入口文件index.php里添加一行日志代码:
error_log("Request received by server: " . $_SERVER['SERVER_ADDR'] . " | URI: " . $_SERVER['REQUEST_URI']);
然后查看服务器的Web日志(比如Apache的error.log或者Nginx的error.log),或者通过AWS CloudWatch收集日志,确认登录请求后的跳转请求是不是被路由到了另一台服务器,这样就能明确是不是会话不一致导致的问题。
5. 检查ELB健康检查配置
有时候ELB的健康检查配置不正确,会导致服务器被频繁踢出或重新加入,也可能引发请求路由异常。确保健康检查的路径是一个能稳定返回200状态码的页面,比如你可以在CodeIgniter里创建一个简单的健康检查控制器:
class Health extends CI_Controller { public function index() { http_response_code(200); echo "OK"; } }
然后把ELB的健康检查路径设为/health,避免因为健康检查误判导致请求分发异常。
内容的提问来源于stack exchange,提问作者Zabeen

