使用标头而不是 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_onebackend_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 应用实例的主要内容,如果未能解决你的问题,请参考以下文章

如何从标头中的cookie中获取特定元素

通过 cookie 标头发送令牌身份验证信息是不是安全?

在 HTTPS 期间浏览器 cookie 和其他标头是不是可见?

Wininet 是不是处理 HTTP 标头值“Set-Cookie”?

如何设置授权标头(JWT)

ORBEON:是不是可以添加自定义标头或向 API 授权方发送会话 cookie