搭建一个简单的分布式系统(1)

这个系统的功能非常简单,只是在页面上显示一些文本(Hello,XXX)。搭建这个系统的初衷并不是为了完成这个功能,而是将码农周刊中使用到的一些技术都自己测试一遍。一方面了解下现在互联网公司所使用的一些技术,另一方面为以后工具选型积累一些知识,提供一些参考。
搭建思路也是按照开发思路,先出来一个雏形,然后慢慢丰满羽翼。
其中有些技术和码农周刊中使用的不一样,主要考虑到本人的熟悉程度和工作需要。比如周刊的web开发框架是pyramid,WSGI协议实现使用gunicorn,我这里分别使用的是flask和uWSGI。

网页显示Hello Simon

  • 安装virtualenv隔离环境
$ sudo pip install virtualenv
$ virtualenv --no-site-packages aries # 不使用系统的依赖
hqi@hqi-VirtualBox:~/buildout$ virtualenv --no-site-packages aries
New python executable in /home/hqi/buildout/aries/bin/python
Installing setuptools, pip, wheel...done.
hqi@hqi-VirtualBox:~/buildout/aries$ source ./bin/activate
(aries) hqi@hqi-VirtualBox:~/buildout/aries$

使用virtualenv沙盒创建一个虚拟环境。

  • 安装web开发框架flask
pip install flask
  • 网页显示
(aries) hqi@hqi-VirtualBox:~/buildout/aries$ mkdir app

新建三个文件,app/init.py, app/views.py和run.py
其中init.py创建flask application实例,views.py引入视图,完成URL映射,run.py监听请求

init.py文件内容

from flask import Flask
app = Flask(__name__)
from app import views 

views.py内容

from flask import Flask

app = Flask(__name__)
from app import views 
(aries) hqi@hqi-VirtualBox:~/buildout/aries/app$ cat views.py 
from app import app

# URL映射,分别为/和/index
@app.route('/')
@app.route('/index')
def welcome():
    return "Hello, Wendy & Simon!"

run.py内容:

from app import app
app.debug = True 

执行结果

(aries) hqi@hqi-VirtualBox:~/buildout/aries$ python run.py 
 * Running on http://192.168.1.109:5000/ (Press CTRL+C to quit)
 * Restarting with stat
 * Debugger is active!
 * Debugger pin code: 214-462-276

访问网页


flask.JPG

我们使用的是flask自带的WSGI实现工具,没有用到gunicorn或者uWSGI,后面会介绍Flask如何配合uWSGI使用。

  • 集成celery异步任务调度器
    Celery是Python开发的分布式任务调度模块,接口简单,开发容易,通过第三方消息服务传递任务。stack overflow上有讨论celery和apscheduler的选择,结论是推荐使用celery的多些。有关celery的高级应用,会专门写一篇文章道来。

Flask 与 Celery 整合是十分简单,不需要任何插件。

  • 安装celery
(aries) hqi@hqi-VirtualBox:~/buildout/aries$ pip install celery
  • 在初始化代码中添加celery部分,使用redis作为celery消息通道
from flask import Flask
from celery import Celery

flask_app = Flask(__name__)
celery = Celery(flask_app.name, \
                broker='redis://localhost:6379/0')
celery.conf.update(flask_app.config)

from app import views
  • 添加控制层代码control.py
from app import celery

@celery.task
def get_name(name="Simon"):
    return name
  • 在view.py中添加调用控制层接口
from app import flask_app
import control

@flask_app.route('/')
@flask_app.route('/index')
def welcome(content='Simon'):
    return "Hello, " + content

@flask_app.route('/name') 
def print_name():
    return control.get_name("Wendy & Simon")
get_name.JPG

============ flask 和 Celery整合介绍完毕 =================

  • 安装uWSGI
$ pip install uWSGI
$ uwsgi -h

uwsgi -h出现帮助提示,表明安装成功

  • 配置uWSGI
(aries) hqi@hqi-VirtualBox:~/buildout/aries/uwsgi$ vi aries_uwsgi.ini 

[uwsgi]
# uwsgi启动所使用的地址与端口
socket = 192.168.1.109:8001
#网站目录
chdir = /home/hqi/buildout/aries 
# python 启动程序
wsgi-file = run.py
#flask application实例名称
callable = flask_app
# 处理器个数和线程数
processes = 4
thread = 2
#状态检测地址
stats = 192.168.1.109:9191

$ uwsgi --ini /home/hqi/buildout/aries/uwsgi/aries_uwsgi.ini --http :8002

遇到的问题:

  1. unable to load configuration from uwsgi
    run.py中执行程序要放在main
  2. invalid request block size: 21573 (max 4096)...skip
    uWSGI默认协议是tcp,而浏览器访问协议是http,解决方案是直接提供http服务。
    uwsgi --ini /home/hqi/buildout/aries/uwsgi/aries_uwsgi.ini --http :8002
  3. 如果通过nginx访问uwsgi,uwsgi则可使用以下方式启动

ref: http://www.tuicool.com/articles/2Araye

uwsgi.JPG
  • 安装并运行Nginx
$ sudo apt-get install nginx
$ /etc/init.d/nginx start

访问主机IP地址,会看到Nginx欢迎页面。

由于Nginx不能直接执行托管Python应用程序,所以需要借助uWSGI

  • 配置Nginx和uWSGI
    Nginx和uWSGI通过socket文件相互通信
  • 配置Nginx
    Nginx默认的配置文件位于:
    /etc/nginx/sites-enabled/default
    我们在别的目录下新建一个配置文件
(aries) hqi@hqi-VirtualBox:~/buildout/aries/nginx$ cat aries_nginx.conf 
server {
    listen      316; # 80端口被占,使用别的端口号
    server_name 192.168.1.109;
    charset     utf-8;
    client_max_body_size 75M;

    location / {
        include uwsgi_params;
        # config uwsgi link
        # uwsgi_pass unix:/home/hqi/buildout/aries/nginx/aries_uwsgi.sock;
        uwsgi_pass 192.168.1.109:8001;
        uwsgi_param UWSGI_PYHOME /home/hqi/buildout/aries;
        uwsgi_param UWSGI_CHDIR /home/hqi/buildout;
        uwsgi_param UWSGI_SCRIPT run:flask_app;
    }
}
# Two ways to restart nginx
$ sudo /etc/init.d/nginx restart
$ sudo service nginx restart
$ sudo nginx -c ~/buildout/aries/nginx/aries_nginx.conf
nginx: [emerg] "server" directive is not allowed here in /home/hqi/buildout/aries/nginx/aries_nginx.conf:1

Nginx必须指定配置主文件,再通过主文件加载*.conf配置文件。
检测配置文件是否正确:

$ sudo nginx -t -c /etc/nginx/nginx.conf
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
$ sudo service nginx restart
[sudo] password for hqi: 
 * Restarting nginx nginx                                                                                         [ OK ]
Nginx.JPG
  • 安装supervisor
    supervisor使用python写的进程控制系统。它会监测后台进程的运行状态,帮助你维护,如果它们不小心crash了,还会帮助你重启。
$ sudo apt-get install supervisor
$ echo_supervisord_conf > aries_supervisor.conf

配置supervisor配置文件,其中最重要的配置项为program和group

[program:nginx]
command=nginx -c /home/hqi/buildout/aries/nginx/aries_nginx.conf     ; the program (relative uses PATH, can take args)
process_name=%(program_name)s ; process_name expr (default %(program_name)s)
numprocs=1                    ; number of processes copies to start (def 1)
directory=/home/hqi/buildout/aries/supervisor            ; directory to cwd to before exec (def no cwd)
umask=022                     ; umask for process (default None)
priority=999                  ; the relative start priority (default 999)
autostart=true                ; start at supervisord start (default: true)
autorestart=true        ; whether/when to restart (default: unexpected)
;startsecs=1                   ; number of secs prog must stay running (def. 1)
;startretries=3                ; max # of serial start failures (default 3)
exitcodes=0,2                 ; 'expected' exit codes for process (default 0,2)
stopsignal=INT               ; signal used to kill process (default TERM)
;stopwaitsecs=10               ; max num secs to wait b4 SIGKILL (default 10)
;stopasgroup=false             ; send stop signal to the UNIX process group (default false)
;killasgroup=false             ; SIGKILL the UNIX process group (def false)
;user=chrism                   ; setuid to this UNIX account to run the program
;redirect_stderr=true          ; redirect proc stderr to stdout (default false)
stdout_logfile=/home/hqi/buildout/aries/supervisor/log/stdout.log    ; stdout log path, NONE for none; default AUTO
stdout_logfile_maxbytes=1MB   ; max # logfile bytes b4 rotation (default 50MB)
stdout_logfile_backups=10     ; # of stdout logfile backups (default 10)
stdout_capture_maxbytes=1MB   ; number of bytes in 'capturemode' (default 0)
stdout_events_enabled=false   ; emit events on stdout writes (default false)
stderr_logfile=/home/hqi/buildout/aries/supervisor/log/stderr.log   ; stderr log path, NONE for none; default AUTO
stderr_logfile_maxbytes=1MB   ; max # logfile bytes b4 rotation (default 50MB)
stderr_logfile_backups=10     ; # of stderr logfile backups (default 10)
stderr_capture_maxbytes=1MB   ; number of bytes in 'capturemode' (default 0)
stderr_logfile_backups=10     ; # of stderr logfile backups (default 10)
stderr_capture_maxbytes=1MB   ; number of bytes in 'capturemode' (default 0)
stderr_events_enabled=false   ; emit events on stderr writes (default false)
;environment=A=1,B=2           ; process environment additions (def no adds)
;serverurl=AUTO                ; override serverurl computation (childutils)
##### Start supervisor server ##### 
$ sudo supervisord -c aries_supervisor.conf
##### Shutdown supervisor server ##### 
$ sudo supervisorctl shutdown
##### Reload configuration file ##### 
$ sudo supervisorctl reload

===================================
以上一个基本系统搭建完成,下面我会介绍数据库的存取和SQLAlchemy的使用,数据库选择MySQL数据库

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,015评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,262评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,727评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,986评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,363评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,610评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,871评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,582评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,297评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,551评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,053评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,385评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,035评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,079评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,841评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,648评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,550评论 2 270

推荐阅读更多精彩内容