梁辉 f89bbdf95e | 3 jaren geleden | ||
---|---|---|---|
albumy | 删除 | 3 jaren geleden | |
readme_image | 删除 | 3 jaren geleden | |
tests | 删除 | 3 jaren geleden | |
uploads | 删除 | 3 jaren geleden | |
.flaskenv | 3 jaren geleden | ||
.gitignore | 3 jaren geleden | ||
Dockerfile | 3 jaren geleden | ||
LICENSE | 3 jaren geleden | ||
Pipfile | 3 jaren geleden | ||
Pipfile.lock | 3 jaren geleden | ||
README.md | 3 jaren geleden | ||
gconfig.py | 3 jaren geleden | ||
main.py | 3 jaren geleden | ||
nginx_flask.conf | 3 jaren geleden | ||
nohup.out | 3 jaren geleden | ||
requirements.txt | 3 jaren geleden | ||
run.py | 3 jaren geleden |
本次实验源代码来自:https://github.com/greyli/albumy
demo网站:http://59.110.70.81:5000 或者http://106.75.223.107:5000
gitlab项目地址(注意是develop分支下的代码)
http://106.75.225.141/guoteng/albumy/tree/develop
(主机的带宽最好大一点,我的1M小水管打开网站测试极慢)
tomcat需要8080端口,nginx需要5000,80端口。
不必要的端口不要开,提前提示,谨慎reboot,update,upgrade,高并发优化不是必要的,谨慎使用。
系统:Centos 8
先创建一个有root权限的用户(这里用Rivenatte)
切换到Rivenatte:
su Rivenatte
更新:
sudo yum update
sudo yum upgrade
检查有没有gcc:
gcc -v
没有就:
sudo yum install gcc
有时需安装git:
sudo yum install git
拉取项目(这里用原项目的):
git clone https://github.com/greyli/albumy.git
cd albumy
配置虚拟环境:
python -m venv env(or python3 -m venv env)
source env/bin/activate
pip install -r requirements.txt
python -m pip install --upgrade pip
生成测试数据并测试:
flask forge
flask run --host 0.0.0.0 --port 5000
用浏览器打开http://云主机ip:5000
测试的用户账号:
username:admin@helloflask.com
password:helloflask
下面的pip可以换成pip3,如果你在创建虚拟环境时用python3的话
然而flask自带的wsgi容器性能较差,我采用另一个服务器,gunicorn。
先将我git上的python文件放在albumy中,
同时还需在项目目录下:
mkdir log
cd log
touch debug.log
touch gunicorn.pid
cd ..
这里的albumy指项目目录,不是albumy模块。
gunicorn需要在虚拟环境下安装:
(没进虚拟环境的先:
source env/bin/activate)
pip install gunicorn
同时还需安装gevent:
pip install gevent
推荐参考这个格式,指定源:
pip install 包名 -i http://pypi.douban.com/simple/ --trusted-host pypi.douban.com
可以解决大多问题。
然后:
cd albumy
修改__init__.py的create_app中的
app = Flask('albumy')
改为
app = Flask(__name__)
输入
gunicorn -c albumy项目的绝对路径/gconfig.py run:app
像上面一样,打开浏览器测试
继续用nginx来做反向代理。
先安装nginx:
sudo yum install nginx
接下来的配置,不同的linux发行版修改的文件可能不同,但大体类似。
实在不行就用whereis nginx找。
centos就先:
cd /etc/nginx
ls -a
发现conf.d这个文件夹,这个是放配置文件的
先对nginx.conf修改。
一般第二个https的设置是被注释的,不用管。
看http的设置,在http部分的最下面加入:
include conf.d/*.conf;(;不能少了)
这样我们就可以通过在conf.d文件夹里修改文件来进行配置
配置文件必须是.conf格式
比如 albumy.conf
server {
listen 80;
root albumy项目的绝对路径;
server_name 公网ip;
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_pass http://localhost:5000/; # gunicorn绑定的端口号
}
# 配置static的静态文件:
location ~ ^\/static\/.*$ {
root 项目的绝对路径;
}
}
添加后
sudo nginx -c /etc/nginx/nginx.conf
sudo nginx -t
sudo nginx -s reload
用浏览器打开80,5000端口,看下有没有成功。
80端口的仅仅是静态页面,比较简陋。
接着我们需要用nohup守护进程:
进入项目文件夹的虚拟环境:
cd xxx/albumy/
source env/bin/activate
nohup gunicorn -c gconfig.py run:app &
然后看下有没有成功:
ps -e | grep gunicorn
nohub不能让主机重启后自动运行进程,我们需要设置开机启动:
sudo vim /etc/rc.local
在最下面添加命令行,这样就可以在重启后自动执行命令行了。
最后别忘了加:
chmod +x /etc/rc.d/rc.local
然后可以重启检查下。
接下来进行高并发优化
我们需要安装ab压测工具
这个在任何服务器上部署都可以,只要在最后把ip改下就行。
这里申请一台centos8主机,部署ab。
同样不使用root用户。
先提醒下,deb系的安装与以下有点区别。
先更新:
sudo yum update
sudo yum upgrade
安装依赖:
sudo yum install apr-util
sudo yum install yum-utils
sudo mkdir -p /appdata/apache/ab && cd /appdata/apache/ab
安装ab:
sudo yum install yum-utils.noarch
sudo yumdownloader httpd-tools*
下一步需要root用户:
su root
rpm2cpio httpd-tools*.rpm | cpio -idmv
su Rivenatte
sudo cp /appdata/apache/ab/usr/bin/ab /usr/bin
执行ab:
ab -n 1000 -c 200 http://ip:5000/
如果不与项目在同一主机,写公网ip
在就localhost
1000指共访问了1000次,200指同时200并发
进行了5次
出现apr_pollset_poll: The timeout specified has expired (70007)
就改为ab -n 1000 -c 200 -k http://ip:5000/
看主机配置,量力而行。
先测试下,与优化后比较。
回到部署nginx的主机。
先获取cpu核心数:
grep processor /proc/cpuinfo | wc -l
一般在申请时就知道了
修改配置文件中的http模块:
sudo vim /etc/nginx/nginx.conf
具体参数参考以下文章:
https://www.jianshu.com/p/0fa77899913a
单核2g的主机可以参考以下配置:
worker_rlimit_nofile 10000;
events {
worker_connections 10000;
}
keepalive_timeout 0;(高并发的网站需要设置的参数)
su root
(不用root用户无法进行下列命令)
对系统配置:
ulimit -n 一个较大的数字
echo 50000 > /proc/sys/net/core/somaxconn
more /proc/sys/net/core/somaxconn
有50000则正常
下列同理:
echo 1 > /proc/sys/net/ipv4/tcp_tw_recycle(注意,现在的centos取消了这个参数,没有可以不管)
cat /proc/sys/net/ipv4/tcp_tw_recycle
echo 1 > /proc/sys/net/ipv4/tcp_tw_reuse
cat /proc/sys/net/ipv4/tcp_tw_reuse
echo 0 > /proc/sys/net/ipv4/tcp_syncookies
cat /proc/sys/net/ipv4/tcp_syncookies
dmesg|tail
(可能需vim /etc/sysctl.conf
设置:
net.ipv4.tcp_syncookies = 0)
对测试主机也需:
echo 50000 > /proc/sys/net/core/somaxconn
ulimit -n 一个较大的数字
(可能需设置net.ipv4.tcp_syncookies = 0,同上)
不重启主机,对测试主机配置后开始测试: sudo vim /etc/sysctl.conf 加入: net.nf_conntrack_max = 655360 net.netfilter.nf_conntrack_tcp_timeout_established = 1200)
ab -c 100000 -n 100000 -r http://主机ip:5000/
(可以适当改下,但还是要看主机配置,我这台是2gRam 1核)
之后可以将以上系统设置加入自启动项(服务器重启可能会回到修改前设置)
下面添加邮箱:
先去注册个邮箱,并以stmp服务器发送。(这个需要网上查下如何开放邮箱stmp,不同邮箱的可能不同)
像之前一样,修改启动项:
source env/bin/activate
export MAIL_SERVER='smtp.163.com' //示例
export MAIL_USERNAME='XXXXXX@163.com' //填邮箱XXXXXX
export MAIL_PASSWORD='XXXXXX' //密码,注意是邮箱开启第三方smtp的认证码
别忘了chmod +x /etc/rc.d/rc.local
最后reboot。
(注:这里需要邮箱发送验证邮件,才可以输入验证码注册)
配置docker容器并push到远端,重新在别的服务器上部署时只需将镜像pull下来即可。 写好Dockerfile,在本地build好镜像后,将容器push到远端。
在服务器上部署时只需将远端的容器pull到服务器上,再run即可
我们首先要将上面的run.py中的
app.run()改为app.run(host='0.0.0.0',port=3389)
部署时先下载docker
curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun
若报错则先执行
yum install -y https://download.docker.com/linux/centos/7/x86_64/stable/Packages/containerd.io-1.2.6-3.3.el7.x86_64.rpm
接着启动docker服务
service docker start
写入我们的Dockerfile
vim Dockerfile
FROM python:3.6
RUN apt-get update
RUN apt install -y nginx
WORKDIR /Project/demo
COPY requirements.txt ./
RUN pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
COPY . .
RUN rm /etc/nginx/sites-enabled/default
COPY nginx_flask.conf /etc/nginx/sites-available/
RUN ln -s /etc/nginx/sites-available/nginx_flask.conf /etc/nginx/sites-enabled/nginx_flask.conf
RUN echo "daemon off;" >> /etc/nginx/nginx.conf
CMD ["nginx","-c","/etc/nginx/nginx.conf"]
CMD ["nginx","-t"]
CMD ["nginx","-s","reload"]
CMD ["gunicorn", "run:app", "-c", "./gconfig.py"]
其中需要我们之前部署时写的gconfig.py文件和我们的nginx配置文件
除此以外我们需要在根目录创建一个新文件nginx_flask.conf
server {
listen 80;
location / {
proxy_pass http://localhost:5000/;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location ^~ /static/ {
root /Project/demo;
}
}
之后在本地建立镜像
docker build -t image1 .
建立成功后可以尝试启动docker容器
docker run -d -p 3389:3389 --name test1 image1
打开http://云主机ip:3389查看是否显示界面
之后将我们的镜像push到远端
没有注册docker账号的话先注册一个docker账号
https://registry.hub.docker.com/
接着登录docker账号
docker login
输入账号
输入密码
显示login successful就成功了,之后push到远端
首先对镜像打标签
docker tag image1 lh123/albumy_nginx_mysql_image:v2
之后将镜像推送到仓库
docker push lh123/albumy_nginx_mysql_image:v2
以后需要创建应用时只需要从docker中拉取镜像运行即可。
新建云主机,安装docker之后将上述镜像pull到本地,之后执行
docker run -d -p 3389:3389 --name test1 lh123/albumy_nginx_mysql_image:v2
打开http:云主机ip:3389即可访问网页。
之后在ucloud中使用负载均衡ULB,创建负载均衡ULB。
接着在建立三台云主机,使用原来申请的有外网的云主机,分别通过内网连接三台新建的云主机。
在云主机上pull下来刚才上传的docker镜像
docker pull lh123/albumy_nginx_mysql_image:v2
在云主机上启动镜像
docker run -d -p 3389:3389 --name test1 albumy_nginx_mysql_image:v2
将我们启动好的三台云主机啊加到我们的负载均衡当中
使用负载均衡之后的压测效果更好
为了保证负载均衡的服务器的数据一致性,我们将数据库挂在到云数据库mysql上
我们将项目的.flask.env文件中的设置改为
FLASK_APP=albumy
FLASK_ENV=development
再将setting.py中的设置改为
class ProductionConfig(BaseConfig):
SQLALCHEMY_DATABASE_URI = 'mysql://root:lianghui123@10.23.56.255:3306/flask_test'
再打包到docker并运行我们的项目
发现报错No module named MYSQLdb发现是因为
按照 Flask-SQLAlchemy 文档的说明,配置好 SQLALCHEMY_DATABASE_URI = 'mysql://username:password@server/db' 后操作 MySQL 报错 ImportError: No module named 'MySQLdb'。既然缺少 MySQLdb 这个模块,按照常规方法缺啥补啥吧,执行 pip install MySQL-python 却报错 ImportError: No module named 'ConfigParser'。查了一下,这是由于 MySQL-python 不支持 Python 3(MySQL-3.23 through 5.5 and Python-2.4 through 2.7 are currently supported)。
将MySQLdb换为pymsql,安装pymsql(记得先启动虚拟环境)
pip install pymsql
并在__init__.py中加入
import pymysql
pymysql.install_as_MySQLdb()
再将setting.py中的设置改为
class ProductionConfig(BaseConfig):
SQLALCHEMY_DATABASE_URI = 'mysql+pymysql://root:lianghui123@10.23.56.255:3306/flask_test'
即可访问我们的云主机数据库。
最后将完成的项目打包好镜像push到远端仓库。
建立好docker容器之后就可以使用k8s集群部署网页,采用k8s部署可以实现容器集群的自动化部署、自动扩缩容、维护等功能。
首先在ucloud中创建一个UK8S,之后申请一个云主机,
登录云主机安装docker拉取镜像
docker pull lh123/albumy_nginx_mysql_image:v2
安装k8s
wget https://storage.googleapis.com/kubernetes-release/release/v1.19.0/bin/linux/amd64/kubectl
chmod +x kubectl
sudo mv kubectl /usr/local/bin/ (root用户:mv kubectl /usr/bin/)
kubectl version -o json
将K8S的集群凭证添加到kubectl配置文件中,从而能够操控集群。
打开K8S的外网集凭证复制,在云主机中创建~/.kube文件夹,并在其中创建config文件,将外网集凭证复制到config文件中。
为了能在k8s上部署我们的docker镜像,我们还需要在项目文件中添加两个文件Deployment.yaml 和 service.yaml,
deployment.yaml中:
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: albumy-node-deployment
spec:
replicas: 1
selector:
matchLabels:
app: albumynode
template:
metadata:
labels:
app: albumynode
spec:
containers:
- name: albumynode
image: lh123/albumy_nginx_mysql_image:v2
imagePullPolicy: Always
ports:
- containerPort: 3389
service.yaml中:
apiVersion: v1
kind: Service
metadata:
name: albumy-node-deployment
spec:
ports:
- port: 3389
targetPort: 3389
selector:
app: albumynode
之后运行一下命令部署项目
kubectl create -f deployment.yaml
kubectl create -f service.yaml
查看pod是否处于ready状态,若pod不处于ready状态且一直是containercreating状态则
查看创建日志,发现是容器创建失败,谷歌不能访问,uhub-edu.service.ucloud.cn/google_containers/pause-amd64:3.0"镜像无法获取,这应该是ucloud端的问题。(我们采用平时实验作业第八次的部署方法部署实验2里的静态网页也还是报这个错误,真的是很无语)。
(即使用
kubectl create deployment webapp --image=lh123/albumy_nginx_mysql_image:v2
我们发现这样子pod的状态还是一直处于containercreating的状态,而且也是报下图的错误,我觉得者应该是ucloud端的问题,被墙了。我怀疑是ucloud的教育云出问题了之前第八次实验的时候还可以用,现在就不可以用了。
)
解决方法如下,从docker.io把pause-amd64镜像取下来,然后做个标签。这样就可以解决问题。
docker pull googlecontainer/pause-amd64:3.0
docker tag googlecontainer/pause-amd64:3.0 uhub-edu.service.ucloud.cn/google_containers/pause-amd64:3.0
之后新建连接,登录云主机执行
echo -e "\n\e[92mStarting Proxy. After starting it will not output a response. Please click the first Terminal Tab\n"; kubectl proxy
之后访问我们的应用
kubectl get pods#获取我们pod的名称
export POD_NAME=$刚才得到的pod名称
curl http://localhost:8001/api/v1/namespaces/default/pods/$POD_NAME/proxy/
查看我们创建的POD的详细信息
kubectl get pods -o wide
之后将副本scale到10个
kubectl scale deployments/albumy-node-deployment --replicas=10
将我们的网页暴露给公网,并加上负载均衡
创建一个负载均衡
kubectl expose deployment albumy-node-deployment --type=LoadBalancer --port=80
查看service,可以看到负载均衡服务的外网ip地址
kubectl get services
之后访问http:localhost:负载均衡ip就可以看到网页
本次作业镜像:
账号:1491337293@qq.com
密码:18830095812zxc
docker账户
账号:lh123
密码:18830095812zxc
docker镜像:lh123/albumy_nginx_mysql_image:v2
ucloud上docker部署镜像名:docker_nginx_mysql
集群部署有点问题被墙了。
通过本次大作业,我们学习网站前后端的知识,学习了云计算的一些基本知识,亲自部署了云上的应用,学习了docker、k8s等云计算工具的使用,更好的理解了的docker和k8s的用途,和它们在真实云计算环境下对项目部署的帮助。但我们的部署和开发并不完善,一些应用的细节问题没有解决,关于docker、k8s和其他云计算工具的许多知识还需要学习