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负载均衡综合使用相关推荐

  1. Linux中 Nginx+uwsgi部署flask项目 Nginx负载均衡 反向代理

    Nginx是一款自由的.开源的.高性能HTTP服务器和反向代理服务器. 轻量级,同样起web服务,比 apache占用更少的内存及资源 抗并发, nginx处理请求是异步非阻塞的,而 apache则是 ...

  2. MHA+LAMP+Keepalived实现高可负载均衡综合实验

    MHA+LAMP+Keepalived实现高可负载均衡综合实验 文章目录 MHA+LAMP+Keepalived实现高可负载均衡综合实验 MHA实验过程 安装MySQL数据库 配置MySQL一主两从 ...

  3. Nginx负载均衡的详细配置及使用案例

    Nginx负载均衡的详细配置及使用案例详解 感谢看过这一些列博文和评论的小伙伴, 我把自己所看到的学到的拿到这里来分享是想和大家一起学习进步, 想听听园友给出的意见, 也是对自己学习过程的一个总结.  ...

  4. Nginx负载均衡集群介绍

    第1章 集群介绍 1.1 集群简介 1.1.1 什么是集群 简单说,集群就是一组(若干个)相互独立的计算机,利用高速通信网络组成的一个较大的计算机服务系统,每个集群节点(即集群中的每台计算机)都是运行 ...

  5. [ 总结 ] nginx 负载均衡 及 缓存

    操作系统:centos6.4 x64 前端使用nginx做反向代理,后端服务器为:apache + php + mysql 1. nginx负载均衡. nginx编译安装(编译安装前面的文章已经写过) ...

  6. docker初体验:docker部署nginx负载均衡集群

    Docker 是一个用于开发,交付和运行应用程序的开放平台.Docker 使您能够将应用程序与基础架构分开,从而可以快速交付软件.今天来为大家演示一下docker部署nginx负载均衡集群 环境 ce ...

  7. 【CentOS 7LNMP架构33】,nginx负载均衡#180109

    2019独角兽企业重金招聘Python工程师标准>>> hellopasswd nginx负载均衡 多台代理服务器 vi /usr/local/nginx/conf/vhost/lo ...

  8. Keepalived+LVS+Nginx负载均衡之高可用

    2019独角兽企业重金招聘Python工程师标准>>> 上一篇写了nginx负载均衡,此篇实现高可用(HA).系统整体设计是采用Nginx做负载均衡,若出现Nginx单机故障,则导致 ...

  9. Nginx负载均衡+tomcat+session共享

    为什么80%的码农都做不了架构师?>>>    本文,是笔者工作之余写的,第一是把之前打系统框架的步骤记录下来.第二是将这个过程,谈不上经验,奉献给正在撘这种框架遇到各种bug,各种 ...

最新文章

  1. html怎么移动文字的位置,css怎么移动文字
  2. 第二百五十天 how can I 坚持
  3. Jquery getJSON方法分析(一)
  4. 【SPOJ-QTREE】树链剖分
  5. 微信小程序 Unexpected end of JSON input
  6. Flink window 用法介绍
  7. 随想录(用python预测未来中国的GDP)
  8. Attribute in C#
  9. mysql adodb_指南从MySQL转向ADODB的方法_MySQL
  10. WoShop分销积分拼团裂变APP小程序商城全开源无加密商城源码
  11. navicat 简体中文破解版
  12. ThinkPHP 3.2.3 验证码 (解决图片不显示的问题)
  13. 计算机桌面的任务栏,屏幕任务栏消失怎么办_电脑屏幕上任务栏不见了的解决方法...
  14. windows 8.1 关机
  15. SparkSQL——各区域热门商品TOP3
  16. 遥感影像反差增强、直方图均衡化
  17. 通过Nginx反向代理实现IP访问分流
  18. 两片8-3优先编码器转化为16-4线优先编码器真值表--python实现
  19. 在Jupyter Notebook,沉浸式体验ChatGPT
  20. android蓝牙开发搜素,Android蓝牙开发(一)之打开蓝牙和设备搜索

热门文章

  1. offsetTop,offsetHeight,scrollHeight,scrollTop的区别
  2. Disassembly3:variable
  3. 【练习】翻转句子中单词的顺序
  4. 为现有的表添加自增列id并赋值
  5. 如何限制SELECT-OPTIONS的选择屏幕的OPTION
  6. Vue面试题 70道题目及答案
  7. linux+eth0+流量监控,linux流量监控脚本 | 旺旺知识库
  8. js获取一周从开始到结束日期范围
  9. mysql 全连接查询合并字段
  10. ES6公用跑马灯抽奖组件的封装及使用