FarBox & Python

代码,是艺术的一部分。
2014

From FarBox, Nothing of FarBox!

长得好看,是一种生产力

RubyConf China 2014

PyCon China 2014

RubyConf

PyCon

那么问题来了

如果你重回初学者的状态,你会选择哪种语言?
对了,还有Node.js、Go...

人生苦短,我用Python

请稍微关心一下设计,不然就暴殄天物了!

今天讲些什么?

  1. 开发环境
  2. 服务器基础环境
  3. 数据库选择
  4. 基本构架
  5. 开发实践
  6. Tips

开发环境,让自己舒服

一个IDE的基本要求

1,基本语法纠错
2,Debug的支持,包括在某行代码的断点中断后,可以手写代码测试
3,可以快速的查看某函数、命令的源码

自动编译,提高效率

Python包:watchdog + scss + pyjade + subprocess(coffee>js)
浏览器插件:LiveReload
Why: 百行不到的代码,自定义的编译逻辑;提高开发的效率!

选择一个Web框架

无框架

# Base on WSGI
def just_web_app(environ, start_response):
    data = "this is FarBox Realtime API Page, you should request by WebSocket\n"
    start_response("200 OK", [
      ("Content-Type", "text/plain"),
      ("Content-Length", str(len(data)))
    ])
    return iter([data])

Why Flask

1, 源码量不多,容易追源;可控性高,定制的痛苦度低。
2, 文档够用,再不济看下源码即可。
3, from flask import request, g; then anywhere
4, debugger
5, 恰到好处,比如没有冲突的交叉import from website import app(views.py); from views import * (website.py)
6, Pocoo品牌: Flask/Jinja2/Pygments/Shpinx/Werkzeug

Why Jinja2/Jade

模板引擎是什么? 编译(html为py)、缓存(避免重复编译)、执行(渲染)

Jinja2 VS Django: 在模板里处理逻辑,适合吗?

Jade VS Jinja2

if var == 'a'
    div.css_class this is a
elif var == 'b'
    div.css_class_2 this is b
else
    div.css_class.css_class_3 this is not a or b

Why Coffee & SCSS

bind_sign_in = =>
    submit_dom = $('#submit')
    $('li input').keydown (e)->
        if e.keyCode == 13
            submit_to_login()
    submit_dom.click(submit_to_login)

Web服务器的基础环境

Tengine & Nginx (frontend server)

1, 强化了的limit_req_zone (rate=5r/s burst=500)
2, websocket反代(公用80/443端口+访问限制逻辑)

Gunicorn (backend server)

1, 支持Gevent
2, pre-fork worker model (比如:一个master控制10个workers,其中5个会被分派任务;当一个worker处理了1w请求或者其它原因被要求终止,master会分派一个新的worker,无缝交接)

Fail2Ban

Supervisor

Fabric

Bakthat(自动备份到S3)

rotation:
    days: 7 # Number of days to keep
    first_week_day: 5  # First week day, to calculate wich weekly backup keep 
    months: 6 #  Number of months to keep
    weeks: 6 # Number of weeks to keep
import sh, logging
from bakthat.helper import BakHelper
# BakHelper automatically create a temp directory
with BakHelper("mongodb",
               destination="s3",
               password="xxxxx",
               tags=["mongodb"]) as bh:
    logging.info(sh.mongodump(host='localhost:xxxx'))
    bh.backup()
    bh.rotate()

持续迭代与监控

Sentry
NewRelic
用户抱怨...

数据库

Mongodb

1, FarBox的数据对象之间关系很弱,是通过路径名关联起来的
2,NoSQL
3,JSON

现在的结构: 三个节点的副本集,两个节点跟Web服务器一起,另外一个节点主要作为备份

Why need Patches

# for exmaple
db.collection.find_one()
db.collection.find_one(object_id)
db.collection.find_one(None)
# btw, Replica的选择机制

Mongodb is Brainless!

某些场景下,我们在Python中排序以取代数据库本身的sort

Wrapped Memecache

Why Memecache? Because it's simple!

我们的处理:
1, 连接池
2, Memecache服务崩溃、重启时自动绕过&重连
3, 缓存数据压缩

ElasticSearch(全文搜索)

1, 单机版、无状态式
2, 仅存储分词索引&doc_id
3, 与Mongodb的数据自动同步, Gevent控制timeout

Why not 结巴 (python写的)?

统一的数据库模板API(get_data)

基本构架

  1. 心跳系统与系统信息收集
  2. 中国各省ISP的线路检测
  3. DNS负载 (why CNAME to blog.farbox.com.park.farbox.net?)
  4. 分布式数据库
  5. So,可以随时增加服务器,自动分担负载...

开发实践

Response Handler

Gevent without block and force limited timeout, do some jobs in middlewares like statistics.

Desktop APP

FarBox Editor、PySide、QT、QML、Javascript

do amazing cache!

5ms...

do amazing design by Python!

like this...

Some Tips

UnicodeWithAttrs

­­­__call__

get_value_from_data

def get_value_from_data(data, attr, default=None):
    try:
        attrs = attr.split('.')[:25]
        for attr in attrs:
            if type(data) == dict:
                data = data.get(attr, None)
            else:
                data = getattr(data, attr, None)
            if data is None or isinstance(data, LazyDict):  
                if default is not None:
                    return default
                else:
                    return None
    except RuntimeError:
        return None
    return data

Thinking means, not solutions!

Life means, not technology!

@2013-10-25 01:04