一次flask+redis的微服务实战

一次flask+redis的微服务实战_第1张图片
flask

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的部署就基本完成了,中间的环节比较琐碎,但互联网上的资料也很多,基本都可以解决,祝大家玩的开心!

你可能感兴趣的:(一次flask+redis的微服务实战)