如何使用docker swarm维护粘性会话(会话持久性)?

时间:2017-04-13 09:39:52

标签: docker wildfly load-balancing docker-swarm docker-swarm-mode

我有一个基于Java的Web应用程序,它部署在jboss-10.1.0(wildfly)中。我正在使用docker swarm模式(docker version 1.12.1)扩展我的应用程序一切正常但我面临的唯一问题是会话管理。

现在让我们来看看。

我有两个实例正在运行我的应用程序(即App1App2)。我使用docker swarm模式提供的默认负载均衡器nginx来重定向我的应用程序{ {1}}至chintan.test.com:9080,以便我不需要使用我的网址写下端口,并且我可以直接使用此网址chintan.test.com:80进行访问。

现在,默认负载均衡器正在使用RR(chintan.test.com)来提供我的Web请求。所以我第一次访问Round-Robin algorithm时会转到chintan.test.com实例并显示我登录的登录页面凭借凭据,一切都运行良好,几分钟后,它切换到App1,然后再次登录页面。

有没有办法或工具(应该是开源的)来处理会话?所以至少我登录App2并坚持App1直到我退出。

谢谢!

3 个答案:

答案 0 :(得分:2)

尝试使用Nginx和HA-Proxy,但它们似乎都没有在SWARM模式下正常工作。然后我在Docker Swarm中使用了Traefik,它为我做了诀窍。唯一的限制是Traefik应该在管理器节点上运行,因为它需要知道添加或删除新的工作节点。即使您扩展服务,添加节点等,它也不需要重启。

我已使用 Docker撰写版本3 测试了配置,这是最新版本并使用 Docker堆栈部署进行部署。Step by step instructions are over here

首先,您需要创建一个docker-compose.yml(版本3)并添加负载均衡器Traefik Image。这就是它的样子

public <T> ResponseEntity<T> forward(final RoutingInfo routingInfo, final HttpEntity<?> request, final Class<T> responseType)
{
    final HttpMethod method = routingInfo.getMethod();
    final String url = routingInfo.getURL(HTTPS_URI_SCHEME);
    LOG.info("Routing request: {} {}", method, url);
    try
    {
        return restTemplate.exchange(url, method, request, responseType);
    }
    catch (final HttpClientErrorException exc)
    {
        LOG.error("Failed to forward request: {}", exc.getMessage());
        if (exc.getStatusCode().is4xxClientError())
        {
            throw new BadRequestException(exc.getMessage());
        }

        throw new InternalServerErrorException("Failed to forward request!");
    }
}

然后是您需要会话粘性的图像

   loadbalancer:
image: traefik
command: --docker \
  --docker.swarmmode \
  --docker.watch \
  --web \
  --loglevel=DEBUG
ports:
  - 80:80
  - 9090:8080
volumes:
  - /var/run/docker.sock:/var/run/docker.sock
deploy:
  restart_policy:
    condition: any
  mode: replicated
  replicas: 1
  update_config:
    delay: 2s
  placement:
     constraints: [node.role == manager]

您可以follow this link获取详细说明。

答案 1 :(得分:1)

Docker swarm目前不支持粘性会话,循环法是通过其暴露端口到达服务的唯一方式。

要实现粘性会话,您需要在docker中实现一个支持粘性会话的反向代理,并通过容器ID直接与容器通信(而不是对服务名称进行DNS查找,这将再次转到循环负载平衡器)。实现该负载均衡器还需要您实现自己的服务发现工具,以便它知道哪些容器可用。

答案 2 :(得分:0)

我认为在扩展环境中实现粘性会话的最佳方法是通过数据库会话存储。这会将您的应用程序解绑到特定的节点。

我认为,这比依靠Docker Enterprise Sticky会话(https://docs.docker.com/datacenter/ucp/2.2/guides/user/services/use-domain-names-to-access-services/#sticky-sessions)更为简单,更具成本效益。

当然,这意味着需要进行一些应用程序调整,例如:

  • 出于性能考虑(特别是匿名用户避免DoS)将会话请求最小化
  • 我会将会话数据存储在单独的数据库中(而不是主应用程序数据库中)
  • 会话数据应在一段时间后删除,因此您应该定期进行删除旧会话数据的工作
  • 等等。

此技术还可能带来其他好处:

  • 如果您还匹配用户IP /用户代理,则可以提高安全性
  • 可能会提高性能(因为数据库将能够避免磁盘访问)

希望这会有所帮助。