大家好!
今天,我们想谈谈
Ostrovok.ru酒店预订服务团队如何解决微服务增长的问题,其任务是与我们的供应商交换信息。 关于他的经历告诉了Ostrovok.ru DevOps团队负责人。
最初,微服务很小,并且执行以下功能:
- 接受本地服务的请求;
- 向合作伙伴提出要求;
- 规范响应;
- 将结果返回给查询服务。
但是,随着时间的流逝,服务随着合作伙伴的数量和对他们的请求而增长。
随着服务的增长,各种问题开始出现。 不同的提供程序提出了自己的规则:有人限制最大连接数,有人将客户端限制在白名单中。
结果,我们必须解决以下问题:
- 最好有几个固定的外部IP地址,以便您可以将它们提供给合作伙伴,以将其添加到白名单中,
- 与所有供应商只有一个连接池,以便在扩展我们的微服务时,连接数量保持最小,
- 终止SSL并将
keepalive
放在一个位置,从而减轻合作伙伴本身的负担。
他们想了很久,立即想知道该选择什么:Nginx或Haproxy。
最初,钟摆转向Nginx,因为与HTTP / HTTPS相关的大多数问题我都借助它来解决,并且始终对结果感到满意。
该方案很简单:在Nginx上向我们的新代理服务器发出了一个请求,请求的域名格式为
<partner_tag>.domain.local
,在Nginx中有一个
map
,其中
<partner_tag>
对应于合作伙伴的地址。 从
map
中获取了一个地址,并对该地址进行了
proxy_pass
。
这是一个示例
map
,我们使用它来解析域并从列表中选择上游:
这是“
snippet.d/upstreams_map
”的样子:
“one” “http://one.domain.net”; “two” “https://two.domain.org”;
这里我们有
server{}
:
server { listen 80; location / { proxy_http_version 1.1; proxy_pass $upstream_address$request_uri; proxy_set_header Host $upstream_host; proxy_set_header X-Forwarded-For ""; proxy_set_header X-Forwarded-Port ""; proxy_set_header X-Forwarded-Proto ""; } }
一切都很酷,一切正常。 如果没有任何细微差别,可以结束本文。
使用proxy_pass时,通常,使用不带有
keepalive
的HTTP / 1.0协议,请求直接转到所需地址,并在响应完成后立即关闭。 即使我们
proxy_http_version 1.1
,没有上游(
proxy_http_version )也不会改变。
怎么办 首先想到的是让所有供应商进入上游,服务器将成为我们所需供应商的地址,并在
map
保留
"tag" "upstream_name"
。
添加另一个
map
以解析该方案:
并使用标签名称创建
upstreams
:
upstream one { keepalive 64; server one.domain.com; } upstream two { keepalive 64; server two.domain.net; }
对服务器本身进行了少许修改,以考虑到方案,并使用上游名称代替地址:
server { listen 80; location / { proxy_http_version 1.1; proxy_pass $upstream_scheme$upstream_prefix$request_uri; proxy_set_header Host $upstream_host; proxy_set_header X-Forwarded-For ""; proxy_set_header X-Forwarded-Port ""; proxy_set_header X-Forwarded-Proto ""; } }
太好了 该解决方案有效,在每个上游添加
keepalive
指令,设置
proxy_http_version 1.1
,-现在我们有了一个连接池,一切正常。
这次,您绝对可以完成文章,然后去喝茶。 还是不行
确实,当我们喝茶时,其中一个供应商可能会更改同一域(例如,亚马逊)下的IP地址或地址组,因此其中一个供应商可能会在我们茶会的高峰期倒下。
好吧,该怎么办? Nginx有一个有趣的细微差别:在重新加载期间,它可以将
upstream
内部的服务器清醒到新地址并向其发送流量。 一般来说,也是一种解决方案。 每5分钟投入
cron reload nginx
并继续喝茶。
但是在我看来,这似乎仍然是一个一般的决定,所以我开始对Haproxy产生疑问。
Haproxy可以指定
dns resolvers
和配置
dns cache
。 因此,如果Haproxy中的条目已过期,则Haproxy将更新
dns cache
如果更改,则替换上游的地址。
太好了! 现在由设置决定。
这是Haproxy的简短配置示例:
frontend http bind *:80 http-request del-header X-Forwarded-For http-request del-header X-Forwarded-Port http-request del-header X-Forwarded-Proto capture request header Host len 32 capture request header Referer len 128 capture request header User-Agent len 128 acl host_present hdr(host) -m len gt 0 use_backend %[req.hdr(host),lower,field(1,'.')] if host_present default_backend default resolvers dns hold valid 1s timeout retry 100ms nameserver dns1 1.1.1.1:53 backend one http-request set-header Host one.domain.com server one--one.domain.com one.domain.com:80 resolvers dns check backend two http-request set-header Host two.domain.net server two--two.domain.net two.domain.net:443 resolvers dns check ssl verify none check-sni two.domain.net sni str(two.domain.net)
一切似乎都正常了,这一次。 我对Haproxy唯一不满意的是配置描述的复杂性。 您需要构建大量文本才能在上游添加一个文本。 但是懒惰是进步的动力:如果您不想写相同的东西,请编写生成器。
我已经从Nginx获得了一个映射,格式为
"tag" "upstream"
,所以我决定以它为基础,解析并基于这些值生成haproxy后端。
现在,我们所需要做的就是在nginx_map中添加一个新主机,启动生成器并准备好haproxy配置。
今天可能就这些了。 本文更多地涉及介绍性文章,并且致力于选择解决方案并将其集成到当前环境中的问题。
在下一篇文章中,我将向您详细介绍使用Haproxy时遇到的陷阱,哪些指标对监控很有用,以及应该在系统中进行哪些优化以最大程度地发挥服务器性能。
谢谢大家的关注,再见!