前后端项目部署-4, flask+Gunicorn+gevent+supervisor+nginx+redis,docker-compose部署
####
部署方案flask+Gunicorn+gevent+supervisor+nginx
每个组件的作用:
1,. gunicorn:高性能WSGI服务器;
Gunicorn是一个unix上被广泛使用的高性能的Python WSGI UNIX HTTP Server。
和大多数的web框架兼容,并具有实现简单,轻量级,高性能等特点。
目前Gunicorn只能运行在Linux环境中,不支持windows平台
部署 Flask 应用时,为什么会需要 gunicorn 或 uWSGI?
简单说就是 Flask自带的wsgi性能低下
只适合你开发调试的时候用,
线上你必须用Gunicorn+Nginx才能获得更强的性能,和更高的安全性
下面我说一些废话:
django、flask 都有自带的http server,
仅仅是方便我们开发的时候调试代码而已
这些开源框架的维护者不可能投入大量精力来优化自带的wsgi服务器,
他们需要把更多的精力投入到框架自身的优化中,
因为服务器方面已经有Gunicorn/uWSGI、nginx等优秀的开源解决方案
假设我们用自带的来部署到线上,会有什么问题呢?
性能很差,差到不好意思出门见人(如果你的网站就几十个人访问,那性能应该问题不大)
最后我个人建议的方案是 flask+Gunicorn+gevent+supervisor+nginx
所以说为什么使用Gunicorn,简单点就是为了并发。利用异步,提高性能。
2. gevent:把Python同步代码变成异步协程的库;
gevent:gunicorn 默认使用同步阻塞的网络模型(-k sync),对于大并发的访问可能表现不够好,我们很方便地顺手套一个gevent来增加并发量
3,nginx:高性能Web服务器+负责反向代理;
Nginx 是高效的 Web 服务器和反向代理服务器,可以用作负载均衡(当有 n 个用户访问服务器时,可以实现分流,分担服务器的压力),与 Apache 相比,Nginx 支持高并发,可以支持百万级的 TCP 连接,十万级别的并发连接,部署简单,内存消耗少,成本低,但 Nginx 的模块没有 Apache 丰富。Nginx 支持 uWSGI 的 uwsgi 协议,因此我们可以将 Nginx 与 uWSGI 结合起来,Nginx 通过 uwsgi_pass 将动态内容交给 uWSGI 处理。
nginx是一个功能强大的反向代理服务器,我们使用nginx来转发gunicorn服务。为什么要在gunicorn之上再加层nginx呢?一方面nginx可以补充gunicorn在某些方面的不足,如SSL支持、高并发处理、负载均衡处理等,另一方面如果是做一个web网站,除了服务之外,肯定会有一些静态文件需要托管,这方面也是nginx的强项.
有了gunicorn和gevent后,gunicorn可以实现多进程http服务,不过其性能还是相对nginx这种专业的web服务要差一些,主要体现在对高并发的处理、安全问题、静态资源文件的处理等。因此一般情况会在gunicorn之上再配置一层nginx服务。其基本架构示意如下(图来源于百度):
uWSGI+Flask就可以实现一个完整的web服务,似乎不需要Nginx服务器。
当一个服务访问量过大时,我们可能会考虑多部署几台web服务器,这几台web服务器都可以处理客户端请求,但问题是如何将客户端请求分发到各个web服务器上?这就是Nginx的作用->反向代理服务器。它们的关系如下图所示:
4,. supervisor:监控服务进程的工具;
web服务跑起来之后,为了保证服务的稳定性,需要加一个收获进程。supervisor非常好用,配置也简单方便,它是一个用 Python 写的进程管理工具,可以很方便的用来启动、重启、关闭进程(不仅仅是 Python 进程)。除了对单个进程的控制,还可以同时启动、关闭多个进程,比如很不幸的服务器出问题导致所有应用程序都被杀死,此时可以用 supervisor 同时启动所有应用程序而不是一个一个地敲命令启动。
nginx一般不会莫名其妙被关闭,但gunicorn是一个进程,完成有有可能因为一些原因被关闭或者阻塞,为了保证gunicorn进程,需要使用看护进程插件。这里使用supervisor来解决这个问题。
supervisor专门用户linux端进程管理,
###
启动主程序的命令传递:supervisor->gunicorn->flask
###
看着步骤很多,其实除了Gunicorn都不是必须的,Supervisor和Nginx你要是不想使用其实也可以不使用,我说得比较啰嗦,不过其实很容易。
####
使用docker-compose部署,
docker-Compose 简介
docker-Compose 是用于定义和运行多容器 Docker 应用程序的工具。通过 Compose,您可以使用 YML 文件来配置应用程序需要的所有服务。然后,使用一个命令,就可以从 YML 文件配置中创建并启动所有服务。
这个很重要,
要使用docker-compose,首先要把每个部分的Dockerfile写好,然后在docker-compose.yml文件中统一构建和启动
docker-compose会先从每个服务的build目录下找到Dockerfile,然后依次镜像。所有镜像创建完毕后,再根据yml文件中其他配置依次启动镜像的容器。
当docker-compose启动一次后,只要不更改它自动生成的容器和镜像,再次启动,它就不会再创建镜像,而是启动之前生成的容器。
如果想要更改单个服务的内容,修改Dockerfile的内容、或者删除docker-compose自动生成的容器和镜像,再次启动docker-compose的时候,它会重新构建修改后服务的容器,而其他没有做过修改的服务不变
####
第一步,准备一个简单的flask项目,
很简单只需要一个文件,
###
第二步,gunicorn 安装,Gevent安装,supervisor安装,redis安装,
Flask==1.1.2 redis==3.5.3 gevent==21.8.0 gunicorn==20.1.0 supervisor==4.2.2
###
第三步,准备web这个文件夹,
app.py
import os import socket from flask import Flask from redis import Redis app = Flask(__name__) redis = Redis(host=os.environ.get('REDIS_HOST', 'redis'), port=6379) @app.route('/') def hello(): redis.incr('hits') return 'Hello Container World! I have been seen %s times and my hostname is %s.\n' % (redis.get('hits'),socket.gethostname())
###
config.py,作为gunicorn的配置文件,
import multiprocessing import os from distutils.util import strtobool bind = os.getenv('WEB_BIND', '0.0.0.0:8000') accesslog = '-' access_log_format = "%(h)s %(l)s %(u)s %(t)s '%(r)s' %(s)s %(b)s '%(f)s' '%(a)s' in %(D)sµs" # noqa: E501 workers = int(os.getenv('WEB_CONCURRENCY', multiprocessing.cpu_count() * 2)) threads = int(os.getenv('PYTHON_MAX_THREADS', 1)) reload = bool(strtobool(os.getenv('WEB_RELOAD', 'false')))
####
dockfile
FROM python:3.8.5-slim-buster LABEL maintainer="XXX>" COPY . / RUN pip install -r requirements.txt && pip install gunicorn ENTRYPOINT ["/runserver.sh"]
###
runserver
#!/bin/bash #gunicorn --log-level info --log-file=/gunicorn.log --workers 4 --name app -b 0.0.0.0:8000 --reload app.app:app #gunicorn -c app/config.py app.app:app supervisord -n -c supervisord.conf
###
supervisord.conf,这个是supervisor的配置文件,
[supervisord] nodaemon=true [program:flask_gunicorn_nginx_docker] command=gunicorn -c app/config.py app.app:app ; supervisor启动命令
#####
第四步,准备nginx文件夹
app,这个作为Nginx的配置文件,
server { listen 80; server_name 0.0.0.0; charset utf-8; location / { proxy_pass http://web:8000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } }
##
dockefile,注意你看这里,使用了Nginx的基础镜像,
FROM nginx:alpine RUN rm /etc/nginx/conf.d/default.conf ADD sites-enabled/app /etc/nginx/conf.d/default.conf
###
###
第五步,docker-compose.yml,注意这个地方又使用了redis的镜像,
version: "2.0" services: redis: image: redis:buster web: build: context: ./web/ ports: - "8000:8000" links: - redis nginx: restart: always build: ./nginx/ ports: - "80:80" links: - web
#####
运行,
build and up
$ cd docker-compose-flask
$ docker-compose build
$ docker-compose up -d
Starting dockercomposeflask_redis_1 ... done
Starting dockercomposeflask_web_1 ... done
Starting dockercomposeflask_nginx_1 ... done
Check the service running information
$ docker-compose ps
Name Command State Ports
--------------------------------------------------------------------------------------------
dockercomposeflask_nginx_1 /usr/sbin/nginx Up 0.0.0.0:80->80/tcp
dockercomposeflask_redis_1 docker-entrypoint.sh redis ... Up 6379/tcp
dockercomposeflask_web_1 /runserver.sh Up 0.0.0.0:8000->8000/tcp
Check the web service
$ curl 127.0.0.1
Hello Container World! I have been seen 1 times and my hostname is 09ad15ad1b51.
$ curl 127.0.0.1
Hello Container World! I have been seen 2 times and my hostname is 09ad15ad1b51.
$ curl 127.0.0.1
Hello Container World! I have been seen 3 times and my hostname is 09ad15ad1b51.
stop the service
$ docker-compose stop
Stopping dockercomposeflask_nginx_1 ... done
Stopping dockercomposeflask_web_1 ... done
Stopping dockercomposeflask_redis_1 ... done
#####
整个的过程,已经可以作为生产环境部署了,
下一步,要把MongoDB,mysql加入docker里面,看看是怎么应用的,
#####
相关文章
- Redis实战:从入门到精通(redis项目实战)
- Redis:推动企业发展的助力伙伴(redis项目应用)
- Redis的端口号:使用说明(redis的端口号)
- Redis日志文件的存储位置探索(redis日志文件位置)
- 利用Redis缓存 加速网页渲染(redis缓存的好处)
- 解决使用Redis缓存解决难题(缓存redis 问题)
- 基于Redis的创新项目实现(结合redis的项目)
- 本地Redis启动开启本地熔断的新空间(本地redis启动服务)
- 为项目增添更快速之缓存系统Redis实现(为项目添加redis缓存)
- 的应用Web开发中Redis的助力极大提升项目效率(web项目中redis)
- TP50与Redis的联手,为完善Web应用打造极致体验(tp5.0redis)
- 利用Redis管理你的博客项目(博客项目redis)
- 抉择存储数据的最佳选择 ES 还是 Redis(存es还是redis)
- 使用Redis提升项目性能(什么项目要用redis)
- 共享Redis,多个项目英雄无敌(多个项目公用redis)
- 项目中无缝连接Redis实现高性能结果(在项目里直连redis)
- 快速提升项目效率如何利用Redis优化项目性能(在项目中使用redis)
- 华硕台式机上Redis出现的闪退问题(华硕redis打开闪退)
- 红色的发展认识Redis项目的现状与运用(redis 项目运用)
- 红色升空Redis项目融入新时代(redis项目融合)
- 基于Redis的项目搭建新思路(redis项目搭建)
- 红色之火Redis项目开发实践(redis项目开发)
- Redis释放Redis的强大威力构建高性能项目(redis 项目中应用)
- 建立Redis集群,使用Pipe实现分布式计算(redis集群 pipe)
- 阿里云上尽享高效Redis服务(redis阿里云服务)
- 利用Redis实现高效的链表结构(redis 链表结构体)
- 统计Redis输出缓存优化大小分析(redis输出缓存大小)
- Redis读写性能分析 – 测量平均耗时(redis读写的平均时长)
- 简单集成Redis集群与JWT认证实现安全的分布式系统(redis集群jwt)
- Redis如何配置主从复制(redis要几主几从)
- Redis过期极速多线程为您服务(redis过期 多线程)