零停机时间 (Zero-Downtime)
对于互联网上需要直接面向用户的应用在更新时一般要求尽可能地减少停机时间,所谓零停机时间意思就是应用更新或回滚时不会导致服务不可用,一般实现有结合软负载均衡器、SO_REUSEPORT等。
结合软负载均衡器
该方案架构上要求由web server对外提供服务,接收到请求后均衡转发给多个app server,部署时利用reload特性每次更新一部分机器,可以实现零停机时间,缺点是整个部署过程较长,比较繁琐。假设存在这样一个工作集:一台nginx服务器和两台tomcat服务器tomcat1和tomcat2,这样的工作集零停机部署过程大致是这个样子的:
- 将app-v1@tomcat1从nginx负载中移除
- 部署app-v2到tomcat1,即为app-v2@tomcat1
- 将app-v2@tomcat1重新加入到负载中(此时负载中app-v1和app-v2共存)
- 将app-v1@tomcat2从nginx负载中移除
- 部署app-v2到tomcat2,即为app-v2@tomcat2
- 将app-v2@tomcat2重新加入到负载中
说明:app-v1表示v1版本的应用,app-v1@tomcat1表示在tomcat1上的v1版本的应用
SO_REUSEPORT
SO_REUSEPORT是linux kernel 3.9之后的一个新特性,它支持多个进程同时listen同一个地址和端口,在此之前我相信大家都遇到过类似Address already in use
的错误,这样一来就给我们一种错觉认为多个进程不能同时listen同一个端口,其实并非如此,下面看一个python应用的例子。
$ vi server.py
import socket
import os
SO_REUSEPORT = 15
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, SO_REUSEPORT, 1)
s.bind(('', 10000))
s.listen(1)
while True:
conn, addr = s.accept()
print('Connected to {}'.format(os.getpid()))
data = conn.recv(1024)
conn.send(data)
conn.close()
<