四位一体水溶交融,Docker一拖三Tornado6.2 + Nginx + Supervisord非阻塞负载均衡容器式部署实践

本文主要是介绍四位一体水溶交融,Docker一拖三Tornado6.2 + Nginx + Supervisord非阻塞负载均衡容器式部署实践,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

原文转载自「刘悦的技术博客」https://v3u.cn/a_id_203

容器,又见容器。Docker容器的最主要优点就在于它们是可移植的。一套服务,其所有的依赖关系可以捆绑到一个独立于Linux内核、平台分布或部署模型的主机版本的单个容器中。此容器可以传输到另一台运行Docker的主机上,并且在没有兼容性问题的情况下执行。而传统的微服务架构会将各个服务单独封装为容器,虽然微服务容器化环境能够在给定数量的基础架构内实现更高的工作负载密度,但是,在整个生产环境中创建、监视和销毁的容器需求总量呈指数级增长,从而显著增加了基于容器管理环境的复杂性。

藉此,本次我们将服务化零为整,将Tornado服务和Nginx服务器以及配套的监控管理程序Supervisor集成到一个单独的容器中,将其高度可移植性最大化地发挥。

Docker具体安装流程请移玉步到:一寸宕机一寸血,十万容器十万兵|Win10/Mac系统下基于Kubernetes(k8s)搭建Gunicorn+Flask高可用Web集群

整体容器内的系统架构如图所示:

首先,创建项目目录 mytornado:

mkdir mytornado

这里web服务框架我们使用业内著名的非阻塞异步框架Tornado6.2,创建一个服务的入口文件main.py

import json  
import tornado.ioloop  
import tornado.web  
import tornado.httpserver  
from tornado.options import define, options  define('port', default=8000, help='default port', type=int)  class IndexHandler(tornado.web.RequestHandler):  def get(self):  self.write("Hello, Tornado")  def make_app():  return tornado.web.Application([  (r"/", IndexHandler),  ])  if __name__ == "__main__":  tornado.options.parse_command_line()  app = make_app()  http_server = tornado.httpserver.HTTPServer(app)  http_server.listen(options.port)  tornado.ioloop.IOLoop.instance().start()

这里运行端口我们通过命令行传参的方式进行监听,方便多进程服务的启动。

之后,创建 requirements.txt 项目依赖文件:

tornado==6.2

接下来,创建Nginx的配置文件 tornado.conf

upstream mytornado {  server 127.0.0.1:8000;  server 127.0.0.1:8001;  
}  
server {  listen      80;  location / {  proxy_pass http://mytornado;  proxy_set_header Host $host;  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;  }  
}

这里Nginx监听80端口,反向代理到本地系统的8000和8001端口,这里我们使用默认的负载均衡方案:轮询,如果有其他需求,可以按照其他的方案进行修改:

1、轮询(默认)  
每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器down掉,能自动剔除。  upstream backserver {  server 192.168.0.14;  server 192.168.0.15;  
}  2、权重 weight  
指定轮询几率,weight和访问比率成正比,用于后端服务器性能不均的情况。  upstream backserver {  server 192.168.0.14 weight=3;  server 192.168.0.15 weight=7;  
}  3、ip_hash( IP绑定)  
上述方式存在一个问题就是说,在负载均衡系统中,假如用户在某台服务器上登录了,那么该用户第二次请求的时候,因为我们是负载均衡系统,每次请求都会重新定位到服务器集群中的某一个,那么已经登录某一个服务器的用户再重新定位到另一个服务器,其登录信息将会丢失,这样显然是不妥的。  我们可以采用ip_hash指令解决这个问题,如果客户已经访问了某个服务器,当用户再次访问时,会将该请求通过哈希算法,自动定位到该服务器。  每个请求按访问ip的hash结果分配,这样每个访客固定访问一个后端服务器,可以解决session的问题。  upstream backserver {  ip_hash;  server 192.168.0.14:88;  server 192.168.0.15:80;  
}  4、fair(第三方插件)  
按后端服务器的响应时间来分配请求,响应时间短的优先分配。  upstream backserver {  server server1;  server server2;  fair;  
}  5、url_hash(第三方插件)  
按访问url的hash结果来分配请求,使每个url定向到同一个后端服务器,后端服务器为缓存时比较有效。  upstream backserver {  server squid1:3128;  server squid2:3128;  hash $request_uri;  hash_method crc32;  
}

下面我们编写Supervisor的配置文件supervisord.conf:

[supervisord]  
nodaemon=true  [program:nginx]  
command=/usr/sbin/nginx  [group:tornadoes]  
programs=tornado-8000,tornado-8001  [program:tornado-8000]  
command=python3.8 /root/mytornado/main.py --port=8000  
# 执行目录  
directory=/root/mytornado  
# 自动重启  
autorestart=true  
# 启动supervisor时,程序自启动  
autostart=true  
# 日志  
stdout=/var/log/tornado-8000.log  
redirect_stderr=true  
loglevel=info  [program:tornado-8001]  
command=python3.8 /root/mytornado/main.py --port=8001  
# 执行目录  
directory=/root/mytornado  
# 自动重启  
autorestart=true  
# 启动supervisor时,程序自启动  
autostart=true  
# 日志  
stdout=/var/log/tornado-8001.log  
redirect_stderr=true  
loglevel=info

Supervisor 是专门用来在类 Unix 系统上监控管理进程的工具,发布于 2004 年,它对应的角色分别为 Supervisorctl 和 Supervisord。后者的主要作用是启动配置好的程序、响应 Supervisorctl 发过来的指令以及重启退出的子进程,而前者是 Supervisor 的客户端,它以命令行的形式提供了一系列参数,来方便用户向 Supervisord 发送指令,常用的有启动、暂停、移除、更新等命令。

这里我们主要使用Supervisor针对Tornado服务进行监控和管理,这里默认的项目目录为/root/mytornado/

进程配置两个,分别对应nginx的监听端口:8000和8001

最后,编写容器配置文件Dockerfile:

FROM yankovg/python3.8.2-ubuntu18.04  RUN sed -i "s@/archive.ubuntu.com/@/mirrors.163.com/@g" /etc/apt/sources.list \  && rm -rf /var/lib/apt/lists/* \  && apt-get update --fix-missing -o Acquire::http::No-Cache=True  
RUN apt install -y nginx supervisor pngquant  # application  
RUN mkdir /root/mytornado  
WORKDIR /root/mytornado  
COPY  main.py /root/mytornado/  
COPY  requirements.txt /root/mytornado/  
RUN pip install -r requirements.txt -i https://mirrors.aliyun.com/pypi/simple/  # nginx  
RUN rm /etc/nginx/sites-enabled/default  
COPY tornado.conf /etc/nginx/sites-available/  
RUN ln -s /etc/nginx/sites-available/tornado.conf /etc/nginx/sites-enabled/tornado.conf  
RUN echo "daemon off;" >> /etc/nginx/nginx.conf  # supervisord  
RUN mkdir -p /var/log/supervisor  
COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf  # run  
CMD ["/usr/bin/supervisord"]

这里基础镜像选择预装了Python3.8的Ubuntu18,兼具了小体积和可扩展的特性,添加apt-get的安装源之后,分别安装Nginx以及Supervisor。

随后,依照Supervisor配置文件内所书,在容器内部创建项目目录/root/mytornado/

并且将上面编写好的main.py以及requirements.txt复制到容器内部,运行pip install -r requirements.txt -i https://mirrors.aliyun.com/pypi/simple/ 安装项目的所有依赖。

最后,将tornado.conf和supervisord.conf也拷贝到对应的配置路径中,分别启动Nginx和Supervisor服务。

编写好之后,在项目根目录的终端内运行命令打包镜像:

docker build -t 'mytornado' .

首次编译会等待一小会儿,因为需要下载基础镜像服务:

liuyue:docker_tornado liuyue$ docker build -t mytornado .  
[+] Building 16.2s (19/19) FINISHED                                                                                                            => [internal] load build definition from Dockerfile                                                                                    0.1s  => => transferring dockerfile: 37B                                                                                                     0.0s  => [internal] load .dockerignore                                                                                                       0.0s  => => transferring context: 2B                                                                                                         0.0s  => [internal] load metadata for docker.io/yankovg/python3.8.2-ubuntu18.04:latest                                                      15.9s  => [internal] load build context                                                                                                       0.0s  => => transferring context: 132B                                                                                                       0.0s  => [ 1/14] FROM docker.io/yankovg/python3.8.2-ubuntu18.04@sha256:811ad1ba536c1bd2854a42b5d6655fa9609dce1370a6b6d48087b3073c8f5fce      0.0s  => CACHED [ 2/14] RUN sed -i "s@/archive.ubuntu.com/@/mirrors.163.com/@g" /etc/apt/sources.list     && rm -rf /var/lib/apt/lists/*     0.0s  => CACHED [ 3/14] RUN apt install -y nginx supervisor pngquant                                                                         0.0s  => CACHED [ 4/14] RUN mkdir /root/mytornado                                                                                            0.0s  => CACHED [ 5/14] WORKDIR /root/mytornado                                                                                              0.0s  => CACHED [ 6/14] COPY  main.py /root/mytornado/                                                                                       0.0s  => CACHED [ 7/14] COPY  requirements.txt /root/mytornado/                                                                              0.0s  => CACHED [ 8/14] RUN pip install -r requirements.txt -i https://mirrors.aliyun.com/pypi/simple/                                       0.0s  => CACHED [ 9/14] RUN rm /etc/nginx/sites-enabled/default                                                                              0.0s  => CACHED [10/14] COPY tornado.conf /etc/nginx/sites-available/                                                                        0.0s  => CACHED [11/14] RUN ln -s /etc/nginx/sites-available/tornado.conf /etc/nginx/sites-enabled/tornado.conf                              0.0s  => CACHED [12/14] RUN echo "daemon off;" >> /etc/nginx/nginx.conf                                                                      0.0s  => CACHED [13/14] RUN mkdir -p /var/log/supervisor                                                                                     0.0s  => CACHED [14/14] COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf                                                        0.0s  => exporting to image                                                                                                                  0.0s  => => exporting layers                                                                                                                 0.0s  => => writing image sha256:2dd8f260882873b587225d81f7af98e1995032448ff3d51cd5746244c249f751                                            0.0s  => => naming to docker.io/library/mytornado                                                                                            0.0s

打包成功后,运行命令查看镜像信息:

docker images

可以看到镜像总大小不到1g:

liuyue:docker_tornado liuyue$ docker images  
REPOSITORY                           TAG       IMAGE ID       CREATED         SIZE  
mytornado                            latest    2dd8f2608828   4 hours ago     828MB

接着让我们来启动容器:

docker run -d -p 80:80 mytornado

通过端口映射技术,将容器内的80端口服务映射到宿主机的80端口。

输入命令查看服务进程:

docker ps

显示正在运行:

docker ps  
CONTAINER ID   IMAGE       COMMAND                  CREATED         STATUS         PORTS                               NAMES  
60e071ba2a36   mytornado   "/usr/bin/supervisord"   6 seconds ago   Up 2 seconds   0.0.0.0:80->80/tcp, :::80->80/tcp   frosty_lamport  
liuyue:docker_tornado liuyue$

此时我们打开浏览器访问 http://127.0.0.1

没有任何问题。

同时可以根据运行中的容器id来选择进入对应的容器:

liuyue:docker_tornado liuyue$ docker exec -it 60e071ba2a36 /bin/sh  
#

在容器内部我们可以看到项目的所有文件:

# pwd  
/root/mytornado  
# ls  
main.py  requirements.txt  
#

重要的是,可以使用Supervisor对既有的Tornado进程进行管理操作,

查看所有进程:

supervisorctl status

根据配置文件,我们容器内运行着三个服务:

# supervisorctl status  
nginx                            RUNNING   pid 10, uptime 0:54:28  
tornadoes:tornado-8000           RUNNING   pid 11, uptime 0:54:28  
tornadoes:tornado-8001           RUNNING   pid 12, uptime 0:54:28

依据服务名称,对服务进行停止操作:

# supervisorctl stop tornadoes:tornado-8001  
tornadoes:tornado-8001: stopped  
# supervisorctl status  
nginx                            RUNNING   pid 10, uptime 0:55:52  
tornadoes:tornado-8000           RUNNING   pid 11, uptime 0:55:52  
tornadoes:tornado-8001           STOPPED   Dec 28 08:47 AM  
#

再次启动:

# supervisorctl start tornadoes:tornado-8001                         
tornadoes:tornado-8001: started  
# supervisorctl status  
nginx                            RUNNING   pid 10, uptime 0:57:09  
tornadoes:tornado-8000           RUNNING   pid 11, uptime 0:57:09  
tornadoes:tornado-8001           RUNNING   pid 34, uptime 0:00:08  
#

如果服务进程意外终止,Supervisor可以对其进行拉起操作,满血复活:

# ps -aux | grep python  
root         1  0.0  0.1  55744 20956 ?        Ss   07:58   0:01 /usr/bin/python /usr/bin/supervisord  
root        11  0.0  0.1 102148 22832 ?        S    07:58   0:00 python3.8 /root/mytornado/main.py --port=8000  
root        34  0.0  0.1 102148 22556 ?        S    08:48   0:00 python3.8 /root/mytornado/main.py --port=8001  
root        43  0.0  0.0  11468  1060 pts/0    S+   08:51   0:00 grep python  
# kill -9 34  
# supervisorctl status  
nginx                            RUNNING   pid 10, uptime 1:00:27  
tornadoes:tornado-8000           RUNNING   pid 11, uptime 1:00:27  
tornadoes:tornado-8001           RUNNING   pid 44, uptime 0:00:16

如果愿意,也可以将编译好的镜像提交到Dockerhub上,这样可以做到随时使用随时拉取,不需要每次都进行编译操作,这里我已经将镜像推送到云端,需要的话可以直接拉取使用:

docker pull zcxey2911/mytornado:latest

Dockerhub的具体操作流程请参见:利用DockerHub在Centos7.7环境下部署Nginx反向代理Gunicorn+Flask独立架构

结语:诚然,Docker容器技术消除了线上线下的环境差异,保证了服务生命周期的环境一致性标准化。开发者使用镜像实现标准开发环境的构建,开发完成后通过封装着完整环境和应用的镜像进行迁移,藉此,测试和运维人员可以直接部署软件镜像来进行测试和发布,大大简化了持续集成、测试和发布的过程,但是我们也不得不正视容器技术现有阶段的劣势,那就是性能的损耗,Docker容器对CPU和内存的使用几乎没有任何开销,但它们会影响I/O和OS交互。这种开销是以每个I/O操作的额外周期的形式出现的,所以小I/O比大I/O遭受的损失要大得多。这种开销增加了I/O延迟,减少了用于有用工作的CPU周期,从而限制了吞吐量。也许不久的将来,随着内核技术的提升,该缺陷会被逐步解决,最后奉上项目地址,与君共觞:https://github.com/zcxey2911/Docker_Tornado6_Supervisor_Python3.8

原文转载自「刘悦的技术博客」 https://v3u.cn/a_id_203

这篇关于四位一体水溶交融,Docker一拖三Tornado6.2 + Nginx + Supervisord非阻塞负载均衡容器式部署实践的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/315060

相关文章

Nginx设置连接超时并进行测试的方法步骤

《Nginx设置连接超时并进行测试的方法步骤》在高并发场景下,如果客户端与服务器的连接长时间未响应,会占用大量的系统资源,影响其他正常请求的处理效率,为了解决这个问题,可以通过设置Nginx的连接... 目录设置连接超时目的操作步骤测试连接超时测试方法:总结:设置连接超时目的设置客户端与服务器之间的连接

ElasticSearch+Kibana通过Docker部署到Linux服务器中操作方法

《ElasticSearch+Kibana通过Docker部署到Linux服务器中操作方法》本文介绍了Elasticsearch的基本概念,包括文档和字段、索引和映射,还详细描述了如何通过Docker... 目录1、ElasticSearch概念2、ElasticSearch、Kibana和IK分词器部署

部署Vue项目到服务器后404错误的原因及解决方案

《部署Vue项目到服务器后404错误的原因及解决方案》文章介绍了Vue项目部署步骤以及404错误的解决方案,部署步骤包括构建项目、上传文件、配置Web服务器、重启Nginx和访问域名,404错误通常是... 目录一、vue项目部署步骤二、404错误原因及解决方案错误场景原因分析解决方案一、Vue项目部署步骤

Java调用DeepSeek API的最佳实践及详细代码示例

《Java调用DeepSeekAPI的最佳实践及详细代码示例》:本文主要介绍如何使用Java调用DeepSeekAPI,包括获取API密钥、添加HTTP客户端依赖、创建HTTP请求、处理响应、... 目录1. 获取API密钥2. 添加HTTP客户端依赖3. 创建HTTP请求4. 处理响应5. 错误处理6.

Linux流媒体服务器部署流程

《Linux流媒体服务器部署流程》文章详细介绍了流媒体服务器的部署步骤,包括更新系统、安装依赖组件、编译安装Nginx和RTMP模块、配置Nginx和FFmpeg,以及测试流媒体服务器的搭建... 目录流媒体服务器部署部署安装1.更新系统2.安装依赖组件3.解压4.编译安装(添加RTMP和openssl模块

Spring Cloud LoadBalancer 负载均衡详解

《SpringCloudLoadBalancer负载均衡详解》本文介绍了如何在SpringCloud中使用SpringCloudLoadBalancer实现客户端负载均衡,并详细讲解了轮询策略和... 目录1. 在 idea 上运行多个服务2. 问题引入3. 负载均衡4. Spring Cloud Load

golang内存对齐的项目实践

《golang内存对齐的项目实践》本文主要介绍了golang内存对齐的项目实践,内存对齐不仅有助于提高内存访问效率,还确保了与硬件接口的兼容性,是Go语言编程中不可忽视的重要优化手段,下面就来介绍一下... 目录一、结构体中的字段顺序与内存对齐二、内存对齐的原理与规则三、调整结构体字段顺序优化内存对齐四、内

0基础租个硬件玩deepseek,蓝耘元生代智算云|本地部署DeepSeek R1模型的操作流程

《0基础租个硬件玩deepseek,蓝耘元生代智算云|本地部署DeepSeekR1模型的操作流程》DeepSeekR1模型凭借其强大的自然语言处理能力,在未来具有广阔的应用前景,有望在多个领域发... 目录0基础租个硬件玩deepseek,蓝耘元生代智算云|本地部署DeepSeek R1模型,3步搞定一个应

redis群集简单部署过程

《redis群集简单部署过程》文章介绍了Redis,一个高性能的键值存储系统,其支持多种数据结构和命令,它还讨论了Redis的服务器端架构、数据存储和获取、协议和命令、高可用性方案、缓存机制以及监控和... 目录Redis介绍1. 基本概念2. 服务器端3. 存储和获取数据4. 协议和命令5. 高可用性6.

Deepseek R1模型本地化部署+API接口调用详细教程(释放AI生产力)

《DeepseekR1模型本地化部署+API接口调用详细教程(释放AI生产力)》本文介绍了本地部署DeepSeekR1模型和通过API调用将其集成到VSCode中的过程,作者详细步骤展示了如何下载和... 目录前言一、deepseek R1模型与chatGPT o1系列模型对比二、本地部署步骤1.安装oll