![Apache 负载均衡器会话创建错误](https://linux22.com/image/746132/Apache%20%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1%E5%99%A8%E4%BC%9A%E8%AF%9D%E5%88%9B%E5%BB%BA%E9%94%99%E8%AF%AF.png)
我一直在尝试在 apache 中设置负载平衡器;而且我对这个东西也还是个新手。
我在本地网络中,有三台 PC,其中一台我想设置为反向代理,另外两台设置为节点。它们都运行 Apache 2.4、Windows 10 和 php 7.3.6,并且两个节点都有我的 PHP 网站的副本和自己的数据库(两个数据库都会立即相互复制,因此数据是共享的 - 两个节点都可以独立使用,并且可以使用其主机名或 IP 地址访问)
至于负载平衡器,它已启动并运行,但无法正常工作:网站已提供服务,并根据负载在节点之间切换,但无法正确创建会话,因此甚至无法登录网站。如果通过负载平衡器访问网站,而不是直接通过键入某个节点的名称(否则它会正常工作),则无法正确创建会话。
似乎负载平衡器无法创建正确的 PHPSESSID 会话 cookie - 并且只有当存在两个或更多节点时,因为如果由于另一个节点不可用而只剩下一个节点,则负载平衡器可以正常工作并且会话可以正确创建。我认为会话 cookie做创建 – 尽管不正确。(我认为,由于新用户页面被编程为在检测到登录用户时重定向到索引页面,并且索引页面被编程为在检测到会话 cookie 中的无效权限时将用户引导回登录页面。我曾尝试弄乱 Apache httpd.conf 文件以修复此问题,但无济于事;至于我尝试的实际方法(我不保证它们被正确应用,因为我是这个领域的新手)。对于所有这些测试,我禁用了所有访问控制(即任何人都可以访问代理):
1)我尝试使用带有 stickysession 属性的 ProxyPass,如下链接所述:Apache2 负载均衡器具有粘性会话,仅适用于 GET,不适用于 POST
2)我尝试使用 ProxyPassReverseCookiePath 和 ProxyPassReverseCookieDomain 指令,如下链接所述:https://stackoverflow.com/questions/8676890/apache-proxypass-and-sessions
相关 .conf 部分如下所示(我已注释掉所有我尝试过但没有起作用的指令):
ProxyRequests Off
#Header add Set-Cookie " PHPSESSID=.%{BALANCER_WORKER_ROUTE}e; path=/" env=BALANCER_ROUTE_CHANGED
<Proxy *>
#here there would be IP filtering, which I removed altogether for ease
</Proxy>
<Proxy balancer://myset>
BalancerMember "http://192.168.3.202:80" route=route1
BalancerMember "http://192.168.3.203:85" route=route2
ProxySet lbmethod=byrequests
#ProxySet stickysession= PHPSESSID
</Proxy>
ProxyPass /balancer-manager !
ProxyPass "/" "balancer://myset/"
ProxyPassReverse "/" "balancer://myset/"
#ProxyPassReverseCookiePath "balancer://myset/" "/"
#ProxyPassReverseCookieDomain "balancer://myset/" localhost
#ProxyPassReverseCookieDomain "balancer://myset/" "/”
有人知道为什么负载均衡器不能正确创建会话吗?
答案1
粘性平衡器会话可以工作,但必须使用自己的 cookie。PHPSESSID 应由 PHP 处理。
对于平衡器,设置一个名称为 balancer-route 之类的 cookie,并在 stickysession 设置中使用它。当然,客户端可以直接使用这些 cookie,但如果您不去管它们,它应该可以正常工作。
另一个考虑因素是,这不包括平衡器节点关闭和启动的情况。平衡器只会发送一条没有存储 PHP 会话的新路由,因此会生成一个新的 PHPSESSID。
在这种情况下,您确实应该将 PHP 会话存储在数据库中,因为您已经复制了它。我不建议尝试复制 PHP 会话文件,因为它们不会不断刷新,因此不会反映内存中的会话。当然,一些 php 数据库驱动的应用程序已经将其会话存储在自己的数据库中。
答案2
我已在 Apache 2.4.29 上简要测试了此设置,仅使用带有 socat 的虚拟反射器后端。我认为您出错的地方是您尝试使用平衡器设置 PHPSESSID。您应该将其留给 PHP 本身。对于平衡器,设置一个名称为 balancer-route 之类的 cookie,并在 stickysession 设置中使用它。当然,客户端可以直接使用这些 cookie,但如果您不理会它们,它应该可以工作。– user188737
这解决了我的问题,感谢评论者(可惜我无法直接将评论标记为答案)!