使用标头而不是 Cookie 定位特定的 Azure Web 应用实例
Posted
技术标签:
【中文标题】使用标头而不是 Cookie 定位特定的 Azure Web 应用实例【英文标题】:Target specific Azure Web App Instance with Header instead of a Cookie 【发布时间】:2021-07-30 01:17:32 【问题描述】:我有一个架构,我有多个实例,但我想最大化缓存命中。
用户是按组定义的,我想确保属于同一组的所有用户尽可能访问同一台服务器。
应用程序是完全无状态的,但让来自同一组的用户访问同一台服务器将显着提高所有实例的性能和内存负载。
在加载主页时,我已经知道我想在 XHR 调用中将此用户发送到哪个服务器。
使用ARRAffinity
cookie 不是很好在这种情况下几乎是不可能的(跨域,必须首先进行服务器调用等),我强烈希望自己通过自定义发送提示标题。
我正在尝试手动执行一些解决方法,删除 cookie 并分配它们,但感觉很麻烦 而且我还没有完全工作。 而且它不适用于XHR 调用。
问题:
是否可以通过 header、url 或域而不是 cookie 定向到特定实例?
备注
在这种情况下,分布式缓存不适用于我。我需要内存缓存的性能,而不需要额外的网络跃点和序列化/反序列化。 这似乎可以通过应用程序网关实现,但它似乎需要大量额外的基础设施和移动部件,而我的所有问题都可以通过发送“正确”来解决 em> 标题。 我可以通过复制整个 Web 应用程序并分配不同的主机名来解决此问题。此外,这感觉就像添加了许多可能会损坏的额外移动部件。此外,维护将变得更加困难和混乱,我失去了自动缩放等。 也许这可以通过 Kubenetes/Docker Swarm 类型的架构轻松解决(没有经验),但由于这是一个大型遗留项目,而且我有一个非常严格的截止日期,所以我非常谨慎地在最后一刻做出如此巨大的转变。【问题讨论】:
请解释从浏览器到应用服务的流程,特别是解决跨域部分。最近,我不得不为服务器到服务器的调用实现类似的东西,其中基于 cookie 的亲和力是唯一的解决方案。无论如何,整个流程是两跳,即浏览器到 appservice1,然后 appservice1 到 appservice2。浏览器到 appservice1 开箱即用,但从 appservice1 到 appservice2 是自定义代码,其中调用将关联 cookie 存储在本地内存缓存中,从而保证来自给定浏览器的请求到达 appservice2 上的同一实例。 【参考方案1】:如果我理解正确,您希望通过客户端应用程序并基于该代理通过与其他后端服务器的连接来设置自定义标头。
我喜欢为此使用 HAProxy,您也可以为此使用 nginx。 您可以从发行版的包管理器在 linux 上安装 HAProxy,也可以使用可用的 HAProxy docker 容器。 在 ArchLinux 上安装的示例:
sudo pacman -S haproxy
sudo systemctl start haproxy
安装后,您可以找到 haproxy.cfg
配置文件的位置,然后复制我在下面发布的 haproxy.cfg 配置 sn-p,而不是现有的默认配置。
在我的例子中,haproxy.cfg 在/etc/haproxy/haproxy.cfg
要在 HAProxy 中实现您想要的,您需要将所有客户端设置为与该主 HAProxy 服务器进行通信,然后该主 HAProxy 服务器将根据您可以设置客户端的自定义标头的值将连接转发到您拥有的不同后端服务器,例如"x-mycustom-header: Server-one"
。作为奖励,如果需要,您还可以在 HAProxy 上启用粘性会话,但这不是必须的。
这是一个简单的 HAProxy 配置文件 (haproxy.cfg) 示例设置,只有 2 个后端服务器,但您可以添加更多。
这里的逻辑是所有客户端都会向监听端口 80 的 HAProxy 服务器发出 http 请求,然后 HAProxy 会检查客户端添加的名为“x-mycustom-header
”的自定义标头的值,并基于该值,它会将客户端转发到backend_server_one
或backend_server_two
。
出于测试目的,HAProxy 和两个后端都在同一个机器上,但侦听不同的端口。 HAProxy 在 80 端口,server1 在 127.0.0.1:3000,server2 在 127.0.0.1:4000。
cat haproxy.cfg
#---------------------------------------------------------------------
# Example configuration. See the full configuration manual online.
#
# http://www.haproxy.org/download/1.7/doc/configuration.txt
#
#---------------------------------------------------------------------
global
maxconn 20000
log 127.0.0.1 local0
user haproxy
chroot /usr/share/haproxy
pidfile /run/haproxy.pid
daemon
frontend main
bind :80
mode http
log global
option httplog
option dontlognull
option http_proxy
option forwardfor except 127.0.0.0/8
maxconn 8000
timeout client 30s
use_backend backend_server_one if req.hdr(x-mycustom-header) server-one
use_backend backend_server_two if req.hdr(x-mycustom-header) server-two
default_backend backend_server_one #when the header is something else default to the first backend
backend backend_server_one
mode http
balance roundrobin
timeout connect 5s
timeout server 5s
server static 127.0.0.1:3000 #change this ip to your 1st backend ip address
backend backend_server_two
mode http
balance roundrobin
timeout connect 5s
timeout server 30s
server static 127.0.0.1:4000 #change this ip to your 2nd backend ip address
要测试它是否有效,您可以打开两个 netcat 侦听器,一个在端口 3000 上,另一个在端口 4000 上,在不同的屏幕或不同的 ssh 会话上运行它们。
nc -l 3000 # in the first screen
nc -l 4000 # in a second screen
然后在您执行sudo systemctl reload haproxy
以确保使用新配置文件重新加载 HAProxy 后,您可以在端口 80 上发出 http GET 请求并提供 "x-mycustom-header: Server-one"
标头。
您将能够在侦听端口 3000 的 netcat 实例的输出中看到该请求。
现在把header改成"x-mycustom-header: Server-two"
,再发出第二个GET请求,你会看到这次请求到达了第二个netcat实例,它正在监听4000端口,说明这个方法有效。
在 ArchLinux 上测试
【讨论】:
嗨@Evyatar,非常感谢您的扩展回答!我有点时间压力,但我会在未来更详细地研究它。我已授予您赏金 - 但目前接受 Microsoft 的反馈作为明确的答案。如果您能帮助我在答案中支持功能请求,我们将不胜感激! :) 感谢@DirkBoer,我在答案中支持了功能请求,如果有的话会很棒。 嗨@Evyater,再次感谢您的回答!我目前正在调查您的答案 - 但您有任何性能方面的经验吗?我处于一个非常小的时间窗口(直到 6 月 11 日),我担心的是我引入了另一个可能成为瓶颈的“齿轮”。我将有大约 40.000 到 80.000 个并发用户同时在网站上疯狂点击 嗨@DirkBoer,不幸的是,我在HAProxy 的大规模性能方面没有太多经验,所以你需要做一些测试/研究并确定HAProxy 是否正确为您的项目。但是,我可以说它始终满足我的需求,而且我相信 HAProxy 的扩展性非常好,是目前最流行的代理之一,但您必须对其进行测试,看看它是否适合您。跨度> 【参考方案2】:Microsoft 团队已回复确认,目前这是不可能的。
【讨论】:
以上是关于使用标头而不是 Cookie 定位特定的 Azure Web 应用实例的主要内容,如果未能解决你的问题,请参考以下文章
在 HTTPS 期间浏览器 cookie 和其他标头是不是可见?