翼度科技»论坛 编程开发 python 查看内容

01、uwsgi、gunicorn如何实现优雅重启

5

主题

5

帖子

15

积分

新手上路

Rank: 1

积分
15
1、为何需要优雅重启

在实际开发过程中,我们会不断迭代升级产品,每次迭代后,都需要在线上服务器更新代码。一般小公司的迭代升级,是没有做到像金丝雀发布或者使用到kubernetes这些东西的。那如何保证更新的时候,之前接收到的请求能够正常处理完成呢,这个时候就需要实现优雅重启了。
那如何实现优雅重启呢,其实,我们部署python web服务所用到的uwsgi和gunicorn已经实现了优雅重启了,下面就讲讲如何实现优雅重启
2、uwsgi 如何实现优雅重启

以下实验是基于以下版本进行的。
  1. python3.6.8
  2. flask==2.0.3
  3. uwsgi==2.0.21
复制代码
2.1 编写 web 服务

main.py
  1. import time
  2. from flask import Flask
  3. app = Flask(__name__)
  4. @app.route("/")
  5. def index():
  6.     time.sleep(10)
  7.     return "hello eeee"
  8. if __name__ == "__main__":
  9.     app.run()
复制代码
2.2 编写 uwsgi.ini 配置文件
  1. [uwsgi]
  2. #uwsgi启动时,所使用的地址和端口(这个是http协议的)
  3. http=0.0.0.0:8000
  4. #指向网站目录
  5. chdir=./
  6. #python 启动程序文件
  7. wsgi-file=main.py
  8. #python 程序内用以启动的application 变量名
  9. callable=app
  10. #处理器数
  11. processes=4
  12. #线程数
  13. threads=2
  14. #####实现优雅重启添加下面两行配置即刻#####
  15. lazy-apps = true
  16. #监听 test.txt 文件 当 test.txt 发生改变时优雅重启uwsgi。这个名字可以随便起
  17. touch-chain-reload = /Users/xx/work/test/py_test/sample_test/flask_graceful_restart/test.txt
复制代码
2.3 启动uwsgi 服务
  1. uwsgi --ini uwsgi.ini
复制代码
2.4 测试优雅重启

1、请求 http://127.0.0.1:8000/
2、更新 main.py 中返回的内容,改为: return "hello xxxxx"
2、在/Users/xx/work/test/py_test/sample_test/flask_graceful_restart 目录下,执行 touch test.txt。有这个文件时,更改这个文件的内容也可以优雅重启 uwsgi 服务
3、得到第一步的返回结果,返回结果为:"hello eeee"
5、再次请求 http://127.0.0.1:8000/ ,返回结果为:"hello xxxxx"
通过上述测试,可以发现实现了优雅重启。
优雅重启的日志过程:
整个时间还挺久的,差不多4分钟。
开始:12:14:45。
结束:12:18:57。
1、先查看 uwsgi 进程信息
  1. 501  7758  4633   0 12:13PM ttys005    0:00.04 uwsgi --ini uwsgi.ini
  2. 501  7759  7758   0 12:13PM ttys005    0:00.27 uwsgi --ini uwsgi.ini
  3. 501  7760  7758   0 12:13PM ttys005    0:00.27 uwsgi --ini uwsgi.ini
  4. 501  7761  7758   0 12:13PM ttys005    0:00.27 uwsgi --ini uwsgi.ini
  5. 501  7762  7758   0 12:13PM ttys005    0:00.26 uwsgi --ini uwsgi.ini
  6. 501  7763  7758   0 12:13PM ttys005    0:00.00 uwsgi --ini uwsgi.ini
  7. 501  7789  6013   0 12:13PM ttys006    0:00.00 grep --color=auto --exclude-dir=.bzr --exclude-dir=CVS --exclude-dir=.git --exclude-dir=.hg --exclude-dir=.svn --exclude-dir=.idea --exclude-dir=.tox uwsgi
复制代码
2、生成 test.txt 时的现象:当 出现 chain reloading complete 时,代表了优雅完成。
  1. Mon Apr 10 12:14:45 2023 - *** /Users/mashili/work/test/py_test/sample_test/flask_graceful_restart/test.txt has been touched... chain reload !!! ***
  2. Mon Apr 10 12:14:45 2023 - chain next victim is worker 1
  3. Gracefully killing worker 1 (pid: 7759)...
  4. Mon Apr 10 12:15:46 2023 - worker 1 (pid: 7759) is taking too much time to die...NO MERCY !!!
  5. worker 1 killed successfully (pid: 7759)
  6. Respawned uWSGI worker 1 (new pid: 7847)
  7. Mon Apr 10 12:15:47 2023 - chain is still waiting for worker 1...
  8. WSGI app 0 (mountpoint='') ready in 0 seconds on interpreter 0x7fc33e00da00 pid: 7847 (default app)
  9. Mon Apr 10 12:15:48 2023 - chain next victim is worker 2
  10. Gracefully killing worker 2 (pid: 7760)...
  11. Mon Apr 10 12:16:49 2023 - worker 2 (pid: 7760) is taking too much time to die...NO MERCY !!!
  12. worker 2 killed successfully (pid: 7760)
  13. Respawned uWSGI worker 2 (new pid: 7885)
  14. Mon Apr 10 12:16:50 2023 - chain is still waiting for worker 2...
  15. WSGI app 0 (mountpoint='') ready in 0 seconds on interpreter 0x7fc33e00da00 pid: 7885 (default app)
  16. Mon Apr 10 12:16:51 2023 - chain next victim is worker 3
  17. Gracefully killing worker 3 (pid: 7761)...
  18. Mon Apr 10 12:17:52 2023 - worker 3 (pid: 7761) is taking too much time to die...NO MERCY !!!
  19. worker 3 killed successfully (pid: 7761)
  20. Respawned uWSGI worker 3 (new pid: 7905)
  21. Mon Apr 10 12:17:53 2023 - chain is still waiting for worker 3...
  22. WSGI app 0 (mountpoint='') ready in 0 seconds on interpreter 0x7fc33e00da00 pid: 7905 (default app)
  23. Mon Apr 10 12:17:54 2023 - chain next victim is worker 4
  24. Gracefully killing worker 4 (pid: 7762)...
  25. Mon Apr 10 12:18:55 2023 - worker 4 (pid: 7762) is taking too much time to die...NO MERCY !!!
  26. worker 4 killed successfully (pid: 7762)
  27. Respawned uWSGI worker 4 (new pid: 7910)
  28. Mon Apr 10 12:18:56 2023 - chain is still waiting for worker 4...
  29. WSGI app 0 (mountpoint='') ready in 0 seconds on interpreter 0x7fc33e00da00 pid: 7910 (default app)
  30. Mon Apr 10 12:18:57 2023 - chain reloading complete
复制代码
3、优雅重启过程中,查看进程信息。ps -ef|grep uwsgi
发现即存在新的进程,也存在老的进程。测试的时候,发现,优雅重启过程中,并不一定会将重启过程中的请求转发到新的进程中去。
  1.   501  7758  4633   0 12:13PM ttys005    0:00.08 uwsgi --ini uwsgi.ini
  2.   501  7761  7758   0 12:13PM ttys005    0:00.27 uwsgi --ini uwsgi.ini
  3.   501  7762  7758   0 12:13PM ttys005    0:00.26 uwsgi --ini uwsgi.ini
  4.   501  7763  7758   0 12:13PM ttys005    0:00.00 uwsgi --ini uwsgi.ini
  5.   501  7847  7758   0 12:15PM ttys005    0:00.26 uwsgi --ini uwsgi.ini
  6.   501  7885  7758   0 12:16PM ttys005    0:00.26 uwsgi --ini uwsgi.ini
  7.   501  7889  6013   0 12:17PM ttys006    0:00.00 grep --color=auto --exclude-dir=.bzr --exclude-dir=CVS --exclude-dir=.git --exclude-dir=.hg --exclude-dir=.svn --exclude-dir=.idea --exclude-dir=.tox uwsgi
复制代码
2.5 线上如何更新

1、首先将代码更新到服务器。
2、ps -ef|grep uwsgi 查看现在的进程号。
2、查看 test.txt是否存在,存在就更新文件内容,不存在就生成 test.txt。
3、观察uwsgi的日志或者进程,待所有的worker进程都重启生成后,即完成了优雅重启。
3、gunicorn 如何实现优雅重启

3.1 编写 web 服务

main.py
  1. import time
  2. from flask import Flask
  3. app = Flask(__name__)
  4. @app.route("/")
  5. def index():
  6.     # time.sleep(3)
  7.     return "hello fdaf fdafd "
  8. if __name__ == "__main__":
  9.     app.run()
复制代码
3.2 编写 conf.py 配置gunicorn 文件

conf.py
  1. # 是否开启debug模式
  2. debug = True
  3. # 访问地址
  4. bind = "0.0.0.0:8888"
  5. # 工作进程数
  6. workers = 2
  7. # 工作线程数
  8. threads = 2
  9. # 超时时间
  10. timeout = 600
  11. # 输出日志级别
  12. loglevel = 'info'
  13. # 存放日志路径
  14. pidfile = "log/gunicorn.pid"
  15. # 存放日志路径
  16. accesslog = "log/access.log"
  17. # 存放日志路径
  18. errorlog = "log/debug.log"
  19. ######注意,下面这个不能加,加了就不能达到优雅重启的效果,切记切记!!
  20. # gunicorn + apscheduler场景下,解决多worker运行定时任务重复执行的问题
  21. # preload_app = True
复制代码
3.3 启动 gunicorn 服务
  1. gunicorn -c conf.py main:app
复制代码
3.4 测试优雅重启

1、pstree -ap|grep gunicorn  找到主进程
  1. pstree -ap|grep gunicorn
复制代码
2、执行 kill -HUP masterpid
  1. kill -HUP 1540847
复制代码
3、再次 执行 pstree -ap|grep gunicorn,发现worker 进程id不一样后,即更新完成。或者查看日志
  1. [2023-04-10 15:36:51 +0800] [11623] [INFO] Handling signal: hup
  2. [2023-04-10 15:36:51 +0800] [11623] [INFO] Hang up: Master
  3. [2023-04-10 15:36:51 +0800] [11681] [INFO] Booting worker with pid: 11681
  4. [2023-04-10 15:36:51 +0800] [11682] [INFO] Booting worker with pid: 11682
  5. [2023-04-10 15:36:51 +0800] [11644] [INFO] Worker exiting (pid: 11644)
  6. [2023-04-10 15:36:51 +0800] [11645] [INFO] Worker exiting (pid: 11645)
复制代码
3.5 线上如何更新

1、通过 pstree -ap|grep gunicorn 找到主进程ID
2、执行 kill -HUP masterpid 命令
3、等待gunicorn优雅重启完成

来源:https://www.cnblogs.com/huageyiyangdewo/p/17303182.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

举报 回复 使用道具