赞
踩
分布式更多的一个概念,是为了解决单个物理服务器容量和性能瓶颈问题而采用的优化手段。
该领域需要解决的问题在不同的技术层面上,又包括:分布式文件系统、分布式缓存、分布式数据库、分布式计算等,一些名词Hadoop、zookeeper、MQ等都跟分布式有关。
从理念上讲,分布式的实现有两种形式:
相对于分布式来讲,高并发在解决问题上会集中一些,其反应的是同时有多少量:比如在线直播服务,同时与上万人观看。
高并发可以通过分布式技术去解决,将并发流量分到不同的物理服务器上。
但除此之外,还可以有很多其他优化手段:比如使用缓存系统,将所有的吗,静态内容放到CDNA等;还可以使用多线程技术将一台服务器的服务器能量最大化。
在这个‘云’的时代,提高分布式系统并发能力的方式,方法论上主要有两种:垂直扩展(Scale Up)与水平扩展(Scale Out)。
高并发的三个经典问题:
多线程是指从软件或者硬件上实现多个线程并发执行的技术,它更多的是解决CPU调度多个进程的问题,从而让这些进程看上去是同时执行(实际是交替运行的)。
在这几个概念中,多线程解决的问题是最明确的,手段也是比较单一的,基本上遇到的最大问题就是线程安全。
Flask默认是单进程、单线程阻塞的任务模式,在项目上线的时候可以通过nginx+gunicorn的方式部署flask任务,但是在开发的过程中如果想通过延迟的方式测试高并发,需要在app.run()中通过threaded和processes开启线程支持和进程支持。
但是多进程或多线程只能选择一个,不能同时开启。
app.run(host='0.0.0.0', port=4000, threaded=True, processes=1)
使用flask自带的服务器,可以完成web服务的启动。在生产环境中flask自带的服务器,无法满足性能需求,需要采用Gunicorn做wsgi容器,来部署flask程序。Gunicorn(绿色独角兽)是一个Python WSGI的HTTP服务器。从Ruby的独角兽(Unicorn)项目移植。该Gunicorn服务器与各种Web框架兼容,实现非常简单,轻量级的资源消耗。
WSGI(Web Server Gateway Interface)web服务器网关接口,是一种规范,它是web服务器和web应用程序之间的接口。它的作用就像是桥梁,连接在web服务器和web应用框架之间。
Gunicorn是基于pre-fork模型的,有一个中心管理进程(master process)用来管理worker进程集合。Master从不知道任何关于客户端的信息。所有的请求和响应处理都是由worker进程来处理的。
主程序是一个简单的循环,监听各种信号以及相应的响应进程。master管理着正在运行的worker集合,通过监听各种信号比如TTIN,TTOU和CHLD。TTIN和TTOU响应的增加和减少worker的数目。CHLD信号表明一个子进程已经结束了,在这种情况下master会自动的重启失败的worker。
gunicorn实现了一个Unix的预分发web的服务端。
为了提高使用gunicorn时的性能,需理解3种并发方式。
pip3 install gunicorn --user
gunicorn 入口文件名:app
gunicorn -w 4 -b 0.0.0.0:8000 入口文件名:app
后台执行方式启动服务
nohup 启动服务的命令 &
nohup gunicorn -w 4 -b 0.0.0.0:8000 入口文件名:app &
#gunicorn_config.py
daemon = True
reload =True #修改程序代码,不用每次都通过gunicorn进行重启
查看程序是否运行起来,如果运行起来会有两个进程
fuser -v -n tcp 端口号
结束进程
kill -9 进程号
# coding=utf-8 # /usr/bin/env python """ Author: buty Date: 2019/9/17 下午1:36 Description: gunicorn config """ import gevent.monkey gevent.monkey.patch_all() import multiprocessing #server socket bind = '0.0.0.0:4000' #worker # workers = multiprocessing.cpu_count() * 2 + 1 workers = 4 threads = 1 # worker_class = 'gunicorn.workers.gevent.GeventWorker' # worker_class = 'gthread'#gevent worker_class = 'sync' debug = True # daemon = True worker_connections = 100 #log pidfile = 'log/gunicorn.pid' accesslog = 'log/gunicorn_access.log' # errorlog = 'log/gunicorn_error.log' loglevel = 'debug' access_log_format = '%(h)s %(l)s %(u)s "%(r)s" %(s)s %(b)s "%(f)s" "%(a)s"'
与logging自带log记录合并,减少文件数量。
# !/usr/bin/env python # -*- coding: utf-8 -*- # # @Author: Buty # @Date : 11/17/21 9:09 AM # @File : config.py # config.py import os import gevent.monkey gevent.monkey.patch_all() import multiprocessing debug = True bind = '0.0.0.0:8000' pidfile = 'log/gunicorn.pid' # accesslog = 'log/access.log' # errorlog = 'log/error.log' logconfig_dict = { 'version':1, 'disable_existing_loggers': False, 'loggers':{ "gunicorn.error": { "level": "WARNING",# 打日志的等级可以换的,下面的同理 "handlers": ["error_file"], # 对应下面的键 "propagate": 1, "qualname": "gunicorn.error" }, "gunicorn.access": { "level": "DEBUG", "handlers": ["access_file"], "propagate": 0, "qualname": "gunicorn.access" } }, 'handlers':{ "error_file": { "class": "logging.handlers.RotatingFileHandler", "maxBytes": 1024*1024*1024,# 打日志的大小,我这种写法是1个G "backupCount": 1,# 备份多少份,经过测试,最少也要写1,不然控制不住大小 "formatter": "generic",# 对应下面的键 # 'mode': 'w+', "filename": "./log/gunicorn.error.log"# 打日志的路径 }, "access_file": { "class": "logging.handlers.RotatingFileHandler", "maxBytes": 1024*1024*1024, "backupCount": 1, "formatter": "generic", "filename": "./log/gunicorn.access.log", } }, 'formatters':{ "generic": { "format": "'[%(process)d] [%(asctime)s] %(levelname)s [%(filename)s:%(lineno)s] %(message)s'", # 打日志的格式 "datefmt": "[%Y-%m-%d %H:%M:%S %z]",# 时间显示方法 "class": "logging.Formatter" }, "access": { "format": "'[%(process)d] [%(asctime)s] %(levelname)s [%(filename)s:%(lineno)s] %(message)s'", "class": "logging.Formatter" } } } capture_output = True loglevel = 'warning' daemon = True #后台启动 reload = True #workers = multiprocessing.cpu_count() workers = 1 worker_class = 'gevent' x_forwarded_for_header = 'X-FORWARDED-FOR'
# 添加配置文件后的启动方式
gunicorn -c gun.py 入口文件名:app
pstree -ap|grep gunicorn
最小的一级是worker进程,它们的上一级是gunicorn进程。使用kill -HUP [gunicorn 进程ID]
可以杀掉进程。如果该进程还存在上一级进程,使用kill -9 [进程ID]
将其彻底关闭。
报告总体分为Dashboard和Charts两部分
Chart分为三大模块:时间维度信息(Over Time)、吞吐量(Throughput)、响应时间(Response Times)。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。