Web 技术研究所

我一直坚信着,Web 将会成为未来应用程序的主流

nginx 配置之 upstream 的各种哈希

  如果 upstream 只是简单地做轮询,那么很多业务场景可能都无法满足。比如后端业务可能是基于 Session 的,而且这些 Session 并没有在集群的机器之间共享。也就是说,对于同一个用户,每次都应该被分配到同一台机器上,否则集群将无法处理。这时就该轮到哈希登场了。
  一个最简单的需求是,我希望同一个 IP 始终被分配到同一台机器上。轮询肯定是不行的,那么就要把机器作为桶,对 IP 执行哈希运算后分布到桶中。其实 nginx 提供一个简单的指令 ip_hash 来做这件事。比如我们这么配置 5 个 server,并开启 ip_hash:
upstream myservers { ip_hash; server 127.0.0.1:8001; server 127.0.0.1:8002; server 127.0.0.1:8003; server 127.0.0.1:8004; server 127.0.0.1:8005; }   然后这么玩,对 127.0.0.1 发送 5 次请求,对 192.168.0.102 发送 8 次请求(这两个都是我本机的 IP),然后统计到底哪些 server 被使用了:
( for i in {1..5}; do curl http://127.0.0.1:8080 2>/dev/null; done for i in {1..8}; do curl http://192.168.0.102:8080 2>/dev/null; done ) | sort | uniq -c   可以得到这样的结果:

  5 个请求全部被 8001 处理,8 个请求全部被 8004 处理,确实实现了同 IP 分配到同机器上。但是 ip_hash 有个问题,它使用的并不是一致性哈希,所以如果我们删除掉完全没被用到的 8005 就可能会影响到先前的分配,下面是删掉 8005 后的测试结果:

  于是原本由 8004 处理的 8 个请求被分配到了 8002 上。
  当时 nginx 1.6.1 的时候还没有解决这个问题,tengine 自己造了一个 consistent_hash 指令来解决。后来到了 nginx 1.7.2 之后添加了个 hash 指令来解决。
  同样是将同 IP 分配到同机器上,使用 consistent_hash $remote_addr 就不会遇到 ip_hash 那样的问题。consistent_hash 默认使用 IP 和端口作为服务器的标识符,还可以手动设置 id 作为 server 的标识符,而不是像 ip_hash 那样依赖 server 的数量和位置来计算。
网名:
3.80.32.*
电子邮箱:
仅用于接收通知
提交 悄悄的告诉你,Ctrl+Enter 可以提交哦
神奇海螺
[查看全部主题]
各类Web技术问题讨论区
发起新主题
本模块采用即时聊天邮件通知的模式
让钛合金F5成为历史吧!
次碳酸钴的技术博客,文章原创,转载请保留原文链接 ^_^