Flask+nginx负载均衡综合使用
2台机子模仿负载均衡的实验.
本机IP:115.213.73.254
云主机IP:xxx.xxx.xxx.xxx(保密起见,下同) 公网IP
本机运行连接云主机:
ssh ubuntu@某大佬 -p 10070
---------------------------------------云主机上运行netstat -pan结果如下------------------------------------------------
tcp 0 464 192.168.1.109:22 115.213.73.254:16328 ESTABLISHED -
tcp 0 0 192.168.1.109:22 115.213.73.254:16890 ESTABLISHED -
tcp 0 0 192.168.1.109:22 115.213.73.254:16253 ESTABLISHED -
可以看到:
192.168.1.109是云主机的局域网IP
115.213.73.254:16328是台式机所属路由器的端口
----------------------------------自己台式机上运行netstat -pan结果如下-----------------------------------------------------
(python3.6) appleyuchi@ubuntu:~$ netstat -pan|grep 10070
(Not all processes could be identified, non-owned process info
will not be shown, you would have to be root to see it all.)
tcp 0 0 192.168.0.101:47450 xxx.xxx.xxx.xxx:10070 ESTABLISHED 8775/SecureCRT
tcp 0 0 192.168.0.101:47534 xxx.xxx.xxx.xxx:10070 ESTABLISHED 8775/SecureCRT
192.168.0.101:47450是自己台式机的局域网IP和端口
啦啦啦:10070是云主机的IP和防火墙端口
-------------------------------------------------概念总结--------------------------------------------------------------------------------------------
端口监听就是端口占用
上面涉及了四种端口
本机局域网端口->路由器端口->云主机防火墙端口->云主机内部局域网端口
因为本机是没有公网端口的,所以本地netstat查到的端口与云主机netstat查到的端口是不对应的
主要流程:
云主机内部局域网端口->云主机内部防火墙端口->云主机管理平台防火墙端口->客户路由器端口->客户本地端口->访问内容。
-------------------------------------------能不能用命令查询云主机管理平台防火墙?------------------------------------------------------------------
管理员大大说,refused还是drop都是云主机管理平台设定的,所以不能根据信息来判断端口到底咋了。
问了其他几位网友也是:不能用命令查。
命令查询防火墙端口是否没开:
云主机内部:
1.用web app监听一个port的情况下,
2.自己的台式机telnet 云主机IP 端口,返回connection refused
满足上述两个条件,就表示云主机管理平台防火墙端口没开。
-----------------------------------------------------------实验架构--------------------------------------------------------------------------
我们用两台机子,调度分发的时候,一台是发给自己,一台是发给云主机。
------------------------------------------------------web app部署、nginx配置、测试-------------------------------------------------------------------
1.《Flask Web开发:基于Python的Web应用开发实战》第四章的代码,具体操作如下:
①git clone https://github.com/miguelgrinberg/flasky
②gitcheck out 4c
③把上述步骤得到的文件夹分别拷贝到本机和云主机任意位置。
④分别修改本机和云主机和hello.py,具体修改在文末附录。
⑤分别在本机和云主机执行
python3 hello.py
2.
①文末附录的两个nginx.conf分别放到本机和云主机的/etc/nginx/路径下,
②nginx -s reload
3.测试:
chromium浏览器(不要使用Chrome浏览器,因为它会自动补充斜杠"/"导致访问失败,很讨厌,当然可以自己额外去hello.py中修改)
打开http://127.0.0.1:9020/flask_learn2
多打开几次会发现效果如下:
负载均衡成功。
-----------------------------------------------实验分析与调试---------------------------------------------------------------------
如果运行失败,检查以下环节:
不要在nginx.conf中使用ngrok穿透出来的网址,容易失败。
理清楚端口之间的关系,不要把端口设置重复了。
查清楚上面的“概念总结”中每一层端口是否被封
整体端口占用示意图:
/本机127.0.0.1:9002->本机127.0.0.1:9000
本机:9020
\云主机xx.xx.xx.xx:10072->云主机127.0.0.1:10071
上述9020,9002,10072端口都被nginx占用,其余都被Flask web app占用
另外,检查端口是否被占用,可以使用:
lsof -i:port
-------------------------------------------------附录-代码-------------------------------------------------------------------------
云主机的hello.py
from flask import Flask, render_template, session, redirect, url_for, flash
from flask_bootstrap import Bootstrap
from flask_moment import Moment
from flask_wtf import FlaskForm
from wtforms import StringField, SubmitField
from wtforms.validators import DataRequiredapp = Flask(__name__)
app.config['SECRET_KEY'] = 'hard to guess string'bootstrap = Bootstrap(app)
moment = Moment(app)class NameForm(FlaskForm):name = StringField('What is your name?', validators=[DataRequired()])submit = SubmitField('Submit')@app.errorhandler(404)
def page_not_found(e):return render_template('404.html'), 404@app.errorhandler(500)
def internal_server_error(e):return render_template('500.html'), 500@app.route('/flask_learn2', methods=['GET', 'POST'])
def index():form = NameForm()if form.validate_on_submit():#用戶第2次以上訪問程序,這個地方的有效性(validate)驗證就是看你輸入了東西沒,沒輸入東西的話就會提醒你輸入print(dir(session))old_name = session.get('name')#直接從回話中讀取name參數的值# old_name = session['name']#session用来跨请求保存数据!# old_name没有跨请求的能力print("old_name=",old_name)if old_name is not None and old_name != form.name.data:#form.name.data是html页面传过来的新数据flash('Looks like you have changed your name!')session['name'] = form.name.datareturn redirect(url_for('index'))if session.get("name") is None:print("进入if")return render_template('index.html', form=form, name=session.get('name'))#用戶第一次訪問程序else:print("进入else")return render_template('index.html', form=form, name=session.get('name')+"当前是(云主机)")#form.name.data最新提交的數據,但是這個請求一旦結束,數據就丟失了#session.get('name')老數據#session['name']老數據#從上面的代碼來看,session['name']完全等效於session.get('name')#----------------------------关闭被占用的端口-----------------------------------------
def killport(port):command='''kill -9 $(netstat -nlp | grep :'''+str(port)+''' | awk '{print $7}' | awk -F"/" '{ print $1 }')'''os.system(command) if __name__ == '__main__':port=10071app.run(host="127.0.0.1", port=port)
本机(就是自己的电脑)中的hello.py如下:
from flask import Flask, render_template, session, redirect, url_for, flash
from flask_bootstrap import Bootstrap
from flask_moment import Moment
from flask_wtf import FlaskForm
from wtforms import StringField, SubmitField
from wtforms.validators import DataRequiredapp = Flask(__name__)
app.config['SECRET_KEY'] = 'hard to guess string'bootstrap = Bootstrap(app)
moment = Moment(app)class NameForm(FlaskForm):name = StringField('What is your name?', validators=[DataRequired()])submit = SubmitField('Submit')@app.errorhandler(404)
def page_not_found(e):return render_template('404.html'), 404@app.errorhandler(500)
def internal_server_error(e):return render_template('500.html'), 500@app.route('/flask_learn2', methods=['GET', 'POST'])
def index():form = NameForm()if form.validate_on_submit():#用戶第2次以上訪問程序,這個地方的有效性(validate)驗證就是看你輸入了東西沒,沒輸入東西的話就會提醒你輸入print(dir(session))old_name = session.get('name')#直接從回話中讀取name參數的值# old_name = session['name']#session用来跨请求保存数据!# old_name没有跨请求的能力print("old_name=",old_name)if old_name is not None and old_name != form.name.data:#form.name.data是html页面传过来的新数据flash('Looks like you have changed your name!')session['name'] = form.name.datareturn redirect(url_for('index'))if session.get("name") is None:print("进入if")return render_template('index.html', form=form, name=session.get('name'))#用戶第一次訪問程序else:print("进入else")return render_template('index.html', form=form, name=session.get('name')+"当前是(本地)")#form.name.data最新提交的數據,但是這個請求一旦結束,數據就丟失了#session.get('name')老數據#session['name']老數據#從上面的代碼來看,session['name']完全等效於session.get('name')#----------------------------关闭被占用的端口-----------------------------------------
def killport(port):command='''kill -9 $(netstat -nlp | grep :'''+str(port)+''' | awk '{print $7}' | awk -F"/" '{ print $1 }')'''os.system(command) if __name__ == '__main__':port=9000app.run(host="127.0.0.1", port=port)
-------------------------------------------------附录-nginx-----------------------------------------------------------------------
云主机完整nginx.conf
user www-data;
worker_processes auto;
pid /run/nginx.pid;events {worker_connections 768;# multi_accept on;
}http {### Basic Settings##sendfile on;tcp_nopush on;tcp_nodelay on;keepalive_timeout 65;types_hash_max_size 2048;# server_tokens off;# server_names_hash_bucket_size 64;# server_name_in_redirect off;include /etc/nginx/mime.types;default_type application/octet-stream;### SSL Settings##ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLEssl_prefer_server_ciphers on;### Logging Settings##access_log /var/log/nginx/access.log;error_log /var/log/nginx/error.log;### Gzip Settings##gzip on;gzip_disable "msie6";# gzip_vary on;# gzip_proxied any;# gzip_comp_level 6;# gzip_buffers 16 8k;# gzip_http_version 1.1;# gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;### Virtual Host Configs##include /etc/nginx/conf.d/*.conf;include /etc/nginx/sites-enabled/*;server {listen 10072;#server_name mycard.moe;#charset koi8-r;#access_log /var/log/nginx/log/host.access.log main;location / {proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_set_header Host $http_host;proxy_set_header X-NginX-Proxy true;proxy_pass http://127.0.0.1:10071/; fastcgi_intercept_errors on;
proxy_redirect off;}}}
本地完整nginx.conf(下面公网IP:xx.xx.xx.xx需要改成自己的)
user www-data;
worker_processes auto;
pid /run/nginx.pid;events {worker_connections 768;# multi_accept on;
}http {### Basic Settings##sendfile on;tcp_nopush on;tcp_nodelay on;keepalive_timeout 65;types_hash_max_size 2048;# server_tokens off;# server_names_hash_bucket_size 64;# server_name_in_redirect off;include /etc/nginx/mime.types;default_type application/octet-stream;### SSL Settings##ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLEssl_prefer_server_ciphers on;### Logging Settings##access_log /var/log/nginx/access.log;error_log /var/log/nginx/error.log;### Gzip Settings##gzip on;gzip_disable "msie6";# gzip_vary on;# gzip_proxied any;# gzip_comp_level 6;# gzip_buffers 16 8k;# gzip_http_version 1.1;# gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;### Virtual Host Configs##include /etc/nginx/conf.d/*.conf;include /etc/nginx/sites-enabled/*;upstream myapp{server 127.0.0.1:9002 weight=5;server xx.xx.xx.xx:10072 weight=5;#server srv3.example.com;}server{listen 9020;#server_namelocation / {proxy_pass http://myapp;}}server {listen 9002;#server_name xxx.cn#charset koi8-r;#access_log /var/log/nginx/log/host.access.log main;location /{proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_set_header Host $http_host;proxy_set_header X-NginX-Proxy true;proxy_pass http://127.0.0.1:9000/;proxy_redirect off;}}}
-------------------------------------------------------相关资料阅读和小记------------------------------------------------------------
[1]提到了各种负载均衡的类型(看完了)
[2]提到了flask+uwsgi
根据[3],uwsgi和gunicorn是两个相似的东西
[4]提到了nginx负载均衡, 并且有localhost测试的极好案例。
[5]提到了动静分离(动态网络资源和静态网络资源)
[6]nginx+Django+uwsgi
[7]提到了nginx对四层和七层的负载均衡的实现.
[8]提到了多个nginx的配置文件...不知道怎么一起操作.
[9]中server和upstream一起使用
[10]中一个conf文件里面有多个upstream,不知道含义是什么
[11]中提到,upstream是用来跨越单机(意思应该是转发给别的单机)
三台服务器,需要3个nginx.conf,但是每台机子上的nginx.conf内容都是不同的.
Reference:
[1]http://www.ttlsa.com/nginx/using-nginx-as-http-loadbalancer/
[2]https://my.oschina.net/RabbitXiao/blog/1583662
[3]https://segmentfault.com/q/1010000008927097/a-1020000008927326
[4]https://www.jianshu.com/p/4c250c1cd6cd
[5]https://blog.51cto.com/13178102/2063271
[6]https://segmentfault.com/a/1190000016108576
[7]https://www.jb51.net/article/153710.htm
[8]https://www.cnblogs.com/crazymagic/p/11029415.html
[9]https://www.cnblogs.com/winniejohn/p/9855351.html
[10]https://www.cnblogs.com/diantong/p/11208508.html
[11]https://blog.csdn.net/gu_wen_jie/article/details/82149003
Flask+nginx负载均衡综合使用相关推荐
- Linux中 Nginx+uwsgi部署flask项目 Nginx负载均衡 反向代理
Nginx是一款自由的.开源的.高性能HTTP服务器和反向代理服务器. 轻量级,同样起web服务,比 apache占用更少的内存及资源 抗并发, nginx处理请求是异步非阻塞的,而 apache则是 ...
- MHA+LAMP+Keepalived实现高可负载均衡综合实验
MHA+LAMP+Keepalived实现高可负载均衡综合实验 文章目录 MHA+LAMP+Keepalived实现高可负载均衡综合实验 MHA实验过程 安装MySQL数据库 配置MySQL一主两从 ...
- Nginx负载均衡的详细配置及使用案例
Nginx负载均衡的详细配置及使用案例详解 感谢看过这一些列博文和评论的小伙伴, 我把自己所看到的学到的拿到这里来分享是想和大家一起学习进步, 想听听园友给出的意见, 也是对自己学习过程的一个总结. ...
- Nginx负载均衡集群介绍
第1章 集群介绍 1.1 集群简介 1.1.1 什么是集群 简单说,集群就是一组(若干个)相互独立的计算机,利用高速通信网络组成的一个较大的计算机服务系统,每个集群节点(即集群中的每台计算机)都是运行 ...
- [ 总结 ] nginx 负载均衡 及 缓存
操作系统:centos6.4 x64 前端使用nginx做反向代理,后端服务器为:apache + php + mysql 1. nginx负载均衡. nginx编译安装(编译安装前面的文章已经写过) ...
- docker初体验:docker部署nginx负载均衡集群
Docker 是一个用于开发,交付和运行应用程序的开放平台.Docker 使您能够将应用程序与基础架构分开,从而可以快速交付软件.今天来为大家演示一下docker部署nginx负载均衡集群 环境 ce ...
- 【CentOS 7LNMP架构33】,nginx负载均衡#180109
2019独角兽企业重金招聘Python工程师标准>>> hellopasswd nginx负载均衡 多台代理服务器 vi /usr/local/nginx/conf/vhost/lo ...
- Keepalived+LVS+Nginx负载均衡之高可用
2019独角兽企业重金招聘Python工程师标准>>> 上一篇写了nginx负载均衡,此篇实现高可用(HA).系统整体设计是采用Nginx做负载均衡,若出现Nginx单机故障,则导致 ...
- Nginx负载均衡+tomcat+session共享
为什么80%的码农都做不了架构师?>>> 本文,是笔者工作之余写的,第一是把之前打系统框架的步骤记录下来.第二是将这个过程,谈不上经验,奉献给正在撘这种框架遇到各种bug,各种 ...
最新文章
- html怎么移动文字的位置,css怎么移动文字
- 第二百五十天 how can I 坚持
- Jquery getJSON方法分析(一)
- 【SPOJ-QTREE】树链剖分
- 微信小程序 Unexpected end of JSON input
- Flink window 用法介绍
- 随想录(用python预测未来中国的GDP)
- Attribute	 in C#
- mysql adodb_指南从MySQL转向ADODB的方法_MySQL
- WoShop分销积分拼团裂变APP小程序商城全开源无加密商城源码
- navicat 简体中文破解版
- ThinkPHP 3.2.3 验证码 (解决图片不显示的问题)
- 计算机桌面的任务栏,屏幕任务栏消失怎么办_电脑屏幕上任务栏不见了的解决方法...
- windows 8.1 关机
- SparkSQL——各区域热门商品TOP3
- 遥感影像反差增强、直方图均衡化
- 通过Nginx反向代理实现IP访问分流
- 两片8-3优先编码器转化为16-4线优先编码器真值表--python实现
- 在Jupyter Notebook,沉浸式体验ChatGPT
- android蓝牙开发搜素,Android蓝牙开发(一)之打开蓝牙和设备搜索