您可以捐助,支持我们的公益事业。

1元 10元 50元





认证码:  验证码,看不清楚?请点击刷新验证码 必填



  求知 文章 文库 Lib 视频 iPerson 课程 认证 咨询 工具 讲座 Model Center   Code  
会员   
   
 
     
   
 订阅
  捐助
一次flask+redis的微服务实战
 
   次浏览      
 2019-7-26
 
编辑推荐:
本文来自于jianshu,主要简单介绍了一个flask的app部署的环境搭建,以及各种配置的坑等相关知识。

0x00 背景

先说一下需求的场景,策划部门想做一个垂直领域的社区产品,类似与知乎那种,但受益人群是金融行业的从业人员。产品中有一个搜索问题的需求,搜索的问题去题库中进行模糊匹配,终端支持H5/APP/小程序,甚至是微信的自动回复,用过ItChat的人都知道这个强大的工具包,不过最近好像有封号的动作了。做搜索,肯定就会用到分词,当前开源的分词库jieba是做的比较好的了,分析了一下技术栈,就决定用flask来实现一个微服务,供其他的服务模块使用。

本人会着重讲一下环境的搭建,各种配置的坑。

0x01 升级操作系统

操作系统:CentOS 6.x

CentOS 7的玩家手动跳过该环节。首先6.x的版本,默认装的python的版本是2.6的版本,这个版本后面用到的一些软件支持的不是很好,所以我们首先要把python升级到2.7的版本。先创建一个update.sh脚本,然后把下面内容复制进去。

#!/usr/bin/env bash
#安装依赖
yum install openssl openssl-devel zlib-devel gcc -y
# apt-get install libssl-dev
# apt-get install openssl openssl-devel
# 下载源码
wget http://www.python.org/ftp/python/2.7.12/Python-2.7.12.tgz
tar -zxvf Python-2.7.12.tgz
cd Python-2.7.12
mkdir /usr/local/python2.7.12
# 开启zlib编译选项
# sed -i '467c zlib zlibmodule.c -I$(prefix)/include -L$(exec_prefix)/lib -lz' Module/Setup
sed '467s/^#//g' Module/Setup
./configure --prefix=/usr/local/python2.7.12
make
make install
if [ $? -eq 0 ];then
echo "Python2.7.12升级完成"
else
echo "Python2.7.12升级失败,查看报错信息手动安装"
fi
cd
mv /usr/bin/python /usr/bin/python2.6.6
ln -s /usr/local/python2.7.12/bin/python2.7 /usr/bin/python
sed -i '1s/python/python2.6/g' /usr/bin/yum
wget --no-check-certificate https://bootstrap.pypa.io/get-pip.py
python get-pip.py
if [ $? -eq 0 ];then
echo "pip升级完成"
else
echo "pip安装失败,查看报错信息手动安装"
fi
rm -rf /usr/bin/pip
ln -s /usr/local/python2.7.12/bin/pip2.7 /usr/bin/pip

然后把这个脚本加上可执行的权限,并且运行。

chmod u+x update.sh
./update.sh

0x02 创建python虚拟空间

这一步完成之后,我们就开始隔离一个虚拟的空间来运行这个微服务,以后我们所有的程序都在隔离的虚拟空间中来运行,有点docker的概念,这样不管是用python2.x还是3.x都可以同时兼容了。

pip install virtualenv
cd /home/test/web
virtualenv ENV
cd bin
source active

至此就启动了这个docker,接下来就是在这个docker中安装我们requirement.txt中所需要的包了。

我们用的包有如下:

pip install flask
pip install jieba
pip install pymysql
pip install redis
pip install virtualenv
pip install uwsgi
pip install xlrd

到此为止就可以在ENV的环境中,测试app的功能了,现在python myapp.py试一下各接口功能。

0x03 安装nginx

尽管测试成功了,但是线上是不能这么运行的,因为flask只是一个web框架,并不是一个web server的容器,flask自带的werkzeug只能用于开发环境,不能用于生产环境,对于web服务器,我们选择更专业的uWSGI,并且配合nginx作为反向代理。

首先,我们安装nginx

yum -y install nginx

默认的nginx的监听端口是80,如果部署在云服务器上,80端口极大的可能被占用了,我们要去修改这个配置文件。

cd /etc/nginx
vim conf.d

查看一下配置端口的配置文件在哪里,我们看到是default.conf这个文件中有端口号的配置,我们把所有端口号都改成我们想要的端口比如8100。

在 /etc/nginx/ngixn.conf 文件的 http 部分添加一条 include 内容,即最后一行

http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
include /etc/nginx/sites-enabled/*;
}

创建配置文件 vim /etc/nginx/sites-enabled/hello.conf

server {
# Running port
listen 8100;
# 服务器ip 或者域名
server_name 0.0.0.0;

# Proxying connections to application servers
location / {
include uwsgi_params;
uwsgi_pass 127.0.0.1:5000;//和 uWSGI 配置文件中的 ip端口一致
}
}

然后看系统中是否有nginx的service脚本

vim /etc/init.d/nginx

如果没有该脚本,在该脚本中写如下内容:

#!/bin/bash
# chkconfig: - 85 15
nginx=/usr/sbin/nginx
conf=/etc/nginx/nginx.conf
case $1 in
start)
echo -n "Starting Nginx"
$nginx -c $conf
echo " done"
;;
stop)
echo -n "Stopping Nginx"
$nginx -s stop
echo " done"
;;
test)
$nginx -t -c $conf
;;
reload)
echo -n "Reloading Nginx"
$nginx -s reload
echo " done"
;;
restart)
$0 stop
$0 start
;;
show)
ps -aux|grep nginx
;;
*)
echo -n "Usage: $0 {start|restart|reload|stop|test|show}"
;;
esac

给该文件加上可执行权限

chmod u+x nginx
service nginx start

Nginx 在 /var/log/nginx 目录下有 access.log 和 error.log 两个日志文件,如果有问题可以查看这2个日志文件。

0x04 配置uWSGI

接下来配置uWSGI的启动文件,创建 uwsgi 配置文件

vim /etc/uwsgi/apps-enabled/hello.ini

[uwsgi]
// 开启主线程
master = true
// 项目目录
base = /home/test/web
// 移动到项目目录 cd
chdir = %(base)
// 本地的ip和端口
socket = 127.0.0.1:5000
// Python 虚拟环境目录
home = %(base)/ENV
// 程序启动文件
wsgi-file = hello.py
// 项目中引用 flask 实例的变量名
callable = app
// 处理器数
processes = 2
// 线程数
threads = 4
// 获取uwsgi统计信息的服务地址
stats = 127.0.0.1:9191

保存配置文件,通过 uwsgi -i /etc/uwsgi/apps-enabled/hello.ini,来启动 uwsgi。

注意在env的环境下,uwsgi安装的目录不会在/usr/bin中,而是在ENV的bin中,所以

在后面的/etc/init.d/uwsgi中的路径要注意。

创建uWSGI的日志文件

vim /var/log/uwsgi/hello.log

创建uWSGI的service文件

vim /etc/init.d/uwsgi

#!/bin/bash
# chkconfig: - 85 15
uwsgi=/home/test/web/ENV/bin/uwsgi
hello_conf=/etc/uwsgi/apps-enabled/hello.ini
case $1 in
start)
echo -n "Starting uWsgi"
nohup $uwsgi -i $hello_conf >/var/log/uwsgi/hello.log 2>&1 &
echo " done"
;;
stop)
echo -n "Stopping uWsgi"
killall -9 uwsgi
echo " done"
;;
restart)
$0 stop
$0 start
;;
show)
ps -ef|grep uwsgi
;;
*)
echo -n "Usage: $0 {start|restart|stop|show}"
;;
esac

添加可执行属性

sudo chmod +x /etc/init.d/uwsgi
service uwsgi start

uWSGI 在 /var/log/uwsgi 目录下有项目对应日志,有问题可以查看。

0x05 redis的安装

首先安装redis的编译工具gcc和gcc-c++

yum install gcc gcc-c++

然后从redis的官网上下载redis并且安装

wget http://download.redis.io/releases/redis-3.2.5.tar.gz
tar -zxvf /soft/redis-3.2.5.tar.gz
cd redis-3.2.5
make & make install

然后配置redis.conf

bind 0.0.0.0
# 3.x版本,将此属性关闭
protected-mode no

添加redis的service服务

vim /etc/init.d/redis

#!/bin/sh
#
# Simple Redis init.d script conceived to work on Linux systems
# as it does use of the /proc filesystem.
REDISPORT=6379
EXEC=/usr/local/bin/redis-server
CLIEXEC=/usr/local/bin/redis-cli
PIDFILE=/var/run/redis_${REDISPORT}.pid
CONF="/etc/redis/${REDISPORT}.conf"
case "$1" in
start)
if [ -f $PIDFILE ]
then
echo "$PIDFILE exists, process is already running or crashed"
else
echo "Starting Redis server..."
$EXEC $CONF
fi
;;
stop)
if [ ! -f $PIDFILE ]
then
echo "$PIDFILE does not exist, process is not running"
else
PID=$(cat $PIDFILE)
echo "Stopping ..."
$CLIEXEC -p $REDISPORT shutdown
while [ -x /proc/${PID} ]
do
echo "Waiting for Redis to shutdown ..."
sleep 1
done
echo "Redis stopped"
fi
;;
*)
echo "Please use start or stop as first argument"
;;
esac

然后启动服务

chmod u+x redis
service redis start

0x06 python中引入redis作为缓存

我们知道redis是k-v的数据缓存机制,当缓存数据为string, 或是hash类型的时候,都有原生的函数支持,具体可以参考redis的API文档。

但是当我们缓存我们自定义的实体类的时候,有点力不从心,这时候可以用pickle库来做序列化,先把实体类转换成string类型存储在redis中,取出的时候,再做反序列化的操作,具体代码如下:

#coding=utf-8

import redis
import pickle

class Redis:
@staticmethod
def connect(host='localhost', port=6379, db=0):
r = redis.StrictRedis(host, port, db)
return r

# 将内存数据二进制通过序列号转为文本流,再存入redis
@staticmethod
def set_data(r, key, data, ex=None):
r.set(pickle.dumps(key), pickle.dumps(data), ex)

# 将文本流从redis中读取并反序列化,返回
@staticmethod
def get_data(r, key):
data = r.get(pickle.dumps(key))
if data is None:
return None

return pickle.loads(data)

0x07 总结

到此为止,一个flask的app的部署就基本完成了,中间的环节比较琐碎,但互联网上的资料也很多,基本都可以解决,祝大家玩的开心!

 
   
次浏览       
相关文章

手机软件测试用例设计实践
手机客户端UI测试分析
iPhone消息推送机制实现与探讨
Android手机开发(一)
相关文档

Android_UI官方设计教程
手机开发平台介绍
android拍照及上传功能
Android讲义智能手机开发
相关课程

Android高级移动应用程序
Android系统开发
Android应用开发
手机软件测试