python 服务端框架_GitHub - edisonlz/fastor: Python服务端开发框架-极易上手,超出你的想象!...
歡迎使用Python 服務端開發框架 Fastor
Fastor是一款專為Python 打造的API與后端管理系統,通過精心的設計與技術實現,集成了大部分穩定開發組件,memcache , redis,tornado,django,mysql 等。特點概述:
功能豐富 : 支持大部分服務器組件,支持API Doc。
得心應手 : 簡單的實例,非常容易上手。
代碼自動生成 : 根據定義的model模型,自動生成增刪改查代碼。
性能優先 : API使用Tornado開發,性能極高。
穩定服務 : django和tornado經過深度優化,例如:數據庫連接自動重連,緩存過期防止雪崩策略等等。
支付功能 : 支持微信,支付寶支付功能。
API安全 : 在nginx層使用lua插件,對api簽名并校驗。
Fastor = faster + 人 , 意為(人效更高)
開始使用
Fastor 分為后端管理系統和API系統
1)后端管理系統
2)API系統
3)系統架構圖
環境配置
部署
下載或者clone fastor 代碼
支持python2.7,目前不支持python3.0。
框架結構
APP 目錄結構
api: API 接口代碼
app: ORM Model與后端Views代碼
background: 分布式異步處理Async代碼 & 定時任務
base: 基類和一些幫助函數
base/site-packages: 這里優先使用的是代碼中的 site-packages 的python第三方庫
一 后端管理系統
1)配置 base/settings.py
創建數據庫fastor_db
配置數據庫連接參數
配置redis連接參數
配置memached連接參數
其他配置等
示例
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'fastor_db', # Or path to database file if using sqlite3.
'USER': 'root', # Not used with sqlite3.
'PASSWORD': '123456', # Not used with sqlite3.
'HOST': '127.0.0.1', # Set to sempty string for localhost. Not used with sqlite3.
'PORT': '3306', # Set to empty string for default. Not used with sqlite3.
'CHARSET': 'utf8',
'OPTIONS': {
'init_command': 'SET storage_engine=INNODB; SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;set autocommit=1;',
},
},
配置 app/settings.py
配置應用(app) 如第一次使用默認配置即可
2)配置成功后,同步數據庫并運行演示程序
cd app/
python manager.py syncdb #同步數據庫并創建管理員
python runserver #啟動服務
open http://127.0.0.1:8000/ , 并使用剛創建的管理員賬號密碼登錄
3)創建自己的 models
1. 在目錄 iclass/models/中創建model文件,例如 user.py
2. 在 iclass/models/__init__中導入 user 中的model對象
3. 示例
class BaseUser(models.Model):
"""
用戶
"""
user_id = models.CharField(max_length=32, verbose_name=u'用戶ID', default='',primary_key=True)
username = models.CharField( max_length=11, verbose_name=u'用戶名', default='')
nickname = models.CharField(max_length=20, verbose_name=u'昵稱', default='')
password = models.CharField(max_length=100, verbose_name=u'密碼', default='')
image_url = models.CharField( max_length=255, verbose_name=u'用戶頭像', default='')
sex = models.IntegerField( verbose_name=u'性別', default='1')
email = models.CharField( max_length=50, verbose_name=u'郵箱', default='' )
status = models.IntegerField( verbose_name=u'狀態', default='0' ) # 0-關閉,1-開啟
register_from = models.IntegerField(verbose_name=u'注冊設備', default='0', choices=RegisterFromChoices)
last_login_time = models.DateTimeField(auto_now_add=True, verbose_name=u'最后登錄時間')
create_time = models.DateTimeField(auto_now_add=True, verbose_name=u'創建時間')
class Meta:
app_label = "iclass"
db_table = "user"
verbose_name = u"客戶"
4).執行自動生成view/templates代碼 python manage.py gencode iclass.models.base_user BaseUser
- 這里將會在views和templates自動生成增刪改查的代碼
- 在iclass/urls.py 編寫url規則
- view 導入views/__init__.py
- 設置入口導航 iclass/templates/cms_index/left_side_menu.html
"""
自動生成view.templates 說明:
圖像上傳: field_name 中包括 image 字符串的會自動檢測為圖像控件
時間: field_type 等于 DatetimeField 會自動生成時間控件
poistion 字段:如果包含position 字段,1,數據不分頁 2.可以生成拖動保存位置
choices: 如果 module 里面包括choices,自動生成select控件
"""
5) 后臺系統服務部署
- 部署nginx ,nginx配置文件路徑, app/conf/nginx.conf
- 執行 bash app/app.sh 執行進程的數量,端口號均在這里配置。
6) 為了區分開發環境和線上環境支持本地my_settings.py,如果配置了my_settings.py,將覆蓋原有配置,默認加到了.gitignore
- 配置 app/my_settings.py
#示例配置
def load_settings(settings):
settings.update({
'DEBUG': True,
'CACHES': {
'default': {
'BACKEND': 'django.core.cache.backends.dummy.DummyCache',
}
},
'DATABASES': {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'fastor_db', # Or path to database file if using sqlite3.
'USER': 'api', # Not used with sqlite3.
'PASSWORD': 'Win123456', # Not used with sqlite3.
'HOST': '58ec9db06f05c.sh.cdb.myqcloud.com',
'PORT': '3612',
'CHARSET': 'utf8',
'OPTIONS': {
'init_command': 'SET storage_engine=INNODB; SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;set autocommit=1;',
},
},
},
'AUTHENTICATION_BACKENDS': (
"django.contrib.auth.backends.ModelBackend",
"app.user.backends.LDAPBackend",
),
"memcache_settings": {
"func_cache": ["127.0.0.1:11211"],
},
'redis_settings': {
"REDIS_BACKEND": {"servers": '127.0.0.1', "port": 6379, "db": 11},
"MQUEUE_BACKEND": {"servers": '127.0.0.1', "port": 6379, "db": 12},
"MASTER_REDIS": {"servers": '127.0.0.1', "port": 6379, "db": 9},
"SLAVE_REDIS": {"servers": '127.0.0.1', "port": 6379, "db": 9},
},
"memcache_proxy_settings": {
},
})
7) 關于上傳圖片地址的配置
base/settings.py
#上傳到本地地址
'SAVE_IMAGE_PATH':"/tmp",
#這個本地地址chrome訪問無權限,如果存儲在本地,可以啟動nginx作為代理服務器訪問本地圖片
"IMAGE_URL_HOST":"file:///private/tmp",
#參考配置
server {
listen 80;
server_name image.fastor.com;
charset utf-8;
location / {
alias /data/images/;
expires 15m;
}
}
"IMAGE_URL_HOST":"http://image.fastor.com",
備注:建議上傳到騰訊云或者阿里云的對象存儲中。
8) DBrouter配置
base/settings.py
#默認配置
'DATABASE_ROUTERS': ['app.db_router.MainRouter'],
#語法: { 'app_label': '數據庫連接' }
'DATABASE_MAPPING': {},
'DATABASE_READ_MAPPING': {},
#讀寫分離配置
'DATABASE_MAPPING': {"iclass":"default"},
DATABASE_READ_MAPPING': {"iclass":"slave"},
9) UMeditor配置
配置地址:app/statics/umeditor/umeditor.conf
#默認配置,如有需要可自行配置
,imageUrl:"/editor/upload_img" //圖片上傳地址
,imageFieldName: "files[]" //圖片數據的key,若此處修改,需要在后臺對應文件修改對應參數
10) 右側菜單選中規則
右側菜單:app/iclass/templates/cms_index/left_side_menu.html
data-menu-id="100"
#view 對應的增刪改查 template 中的 menu-sel 須和 data-menu-id值相等
二 API管理系統
1)運行api管理系統
cd api/
python main.py --doc --debug --logging=debug
API系統默認用戶名:admin, 密碼:123456
密碼可以在api/settings.py 中配置 ["api"]["password"] = "123456"
2)創建api文件,在api/handler/user_api.py
示例代碼user_api.py
@handler_define
class GetUserInfo(CachedPlusHandler):
def get_cache_expire(self):
return 60 * 1
def get_cache_key(self):
return {
'user_id': self.arg('user_id', ''),
}
@api_define("GetUserInfo", r'/user/info/detail',
[
Param('user_id', True, str, "", "201702071511512892383865", u'用戶id'),
],
description="""讀取用戶基本信息""",
return_desc=""""""
)
def get(self):
user_id = self.arg('user_id')
user = BaseUser.objects.filter(user_id=user_id).first()
if not user:
response = {
"code": 0,
"status": "fail",
"msg": "用戶不存在",
}
return self.write(result)
response = {
"status": "success",
"code": 200,
"user":user.to_json()
}
return self.write(response)
2)注冊api,在api/document/doc_insall_handlers.py 注冊新增api
示例代碼
INSTALL_HANDLERS = [
"api.handler.common",
"api.handler.user_api",
]
INSTALL_HANDLERS_NAME = {
"api.handler.common": "通用接口",
"api.handler.user_api":"用戶接口",
}
3)重新運行API
python main.py --doc --debug --logging=debug
4)API 緩存配置
from api.view.base import BaseHandler , CachedPlusHandler
#1.接口緩存
@handler_define
class GetUserInfo(CachedPlusHandler):
#這個方法返回接口緩存時間帶娃秒
def get_cache_expire(self):
return 60 * 1
#這個方法返回緩存key值,一般返回請求參數即可
def get_cache_key(self):
return {
'user_id': self.arg('user_id', ''),
}
#2.方法緩存
from wi_cache import function_cache
#cache_keys.方法參數,如多個參數用逗號分隔。例如:"user_id,course_id"
#prefix:緩存key前綴#expire_time:緩存時間單位秒
@classmethod
@function_cache(cache_keys="user_id", prefix="func#get_user", expire_time=60*5)
def get_user(cls, user_id):
user = cls.objects.filter(user_id=user_id).first()
return user
#https://pypi.org/project/hash_ring/
#默認memcached分布式算法使用求余數,
#如果是大型應用,可以將memcached 修改為一致性hash算法
#一致性hash算法,主要解決key分布不均勻問題。
#備注:不建議使用memcached代理服務,對性能有損耗,出問題不好查找,max_open_files連接符開到2萬沒問題的,內存要夠。
#修改算法路徑 /fastor/base/site-packages/wi_cache/__init__.py #148行
# 將 func_cache = memcache.Client(memcache_settings["func_cache"])
# 替換為 func_cache = MemcacheRing(memcache_settings["func_cache"])
#示例代碼
from hash_ring import MemcacheRing
mc = MemcacheRing(['127.0.0.1:11222','127.0.0.1:11111'])
mc.set('hello', 'world')
print mc.get('hello')
5)API 異步處理
#示例客戶端代碼
@handler_define
class AsyncDemo(BaseHandler):
@api_define("AsyncDemo", r'/api/async/demo', [
Param('user_id', True, str, "" , "123456" , u'用戶ID'),
Param('course_name', True, str, "","Ed老師的python課程" , u'課程名稱'),
], description="[示例]處理異步事件", return_desc="""""")
def get(self):
user_id = self.arg("user_id")
course_name = self.arg("course_name")
data = {
"user_id":user_id,
"course_name":course_name,
}
dispatch_client = Client()
dispatch_client.dispatch("demo.async.send", data)
response = {
"code": 200,
"status": "success",
}
return self.write(response)
#示例服務端代碼 background/demo.py
def do_sync_worker(data):
print "**Recieve data: ", data
logging.error(data)
if __name__ == "__main__":
worker = Worker("demo.async.send",support_brpop=False)
try:
worker.register(do_sync_worker)
worker.start()
except KeyboardInterrupt:
worker.stop()
print "exited cleanly"
sys.exit(1)
except Exception as e:
logging.error(e)
#示例服務端代碼啟動配置 background/supervisord.conf
#啟動:supervisord -c background/supervisord.conf
#重啟:supervisorctl -c background/supervisord.conf restart all
#重啟demo服務:supervisorctl -c background/supervisord.conf restart demo:*
[program:demo]
process_name = demo-%(process_num)s
command=/data/python2.7/bin/python /data/python/fastor/background/demo.py
process_name=%(program_name)s_%(process_num)02d
stdout_logfile = /data/logs/demo.log
numprocs=2 #這里需要配置你并發處理任務的進程數量
autostart=true
6)API 增加了微信支付寶支付接口
文檔詳見doc/pay文檔
需要根據當前業務,實現業務邏輯
代碼依賴第三發庫,PIL,OpenSSL,qrcode 需要部署安裝
#代碼示例
@handler_define
class WeixinAppPayHandler(BaseHandler):
@api_define("WeixinAppPayHandler", r'/api/wx/app/pay',
[
Param('order_id', True, str, "", "201907261548295499512023", u'訂單id'),
Param('good_name', True, str, "", "xxx", u'good_name'),
],
description="微信APP支付")
def get(self):
application_id = self.arg_int('application_id', 1)
order_id = self.arg('order_id')
good_name = self.arg('good_name','')
order = OrderInfo.objects.filter(order_id=order_id).first() #訂單邏輯需要根據當前業務實現
pay = WePayDoPay(
out_trade_no=order.order_id,
subject=good_name,
total_fee= int(order.amount * 100),
body=good_name,
ip = self.user_ip,
payment_type = "NATIVE",
application_id=application_id
)
params = pay.get_pay_params()
results = {
"params": params,
"code":200,
'status': "success",
"msg":"成功",
}
return self.write(results)
8) API系統高級方法
#獲取參數,必傳
order_id = self.arg('order_id')
#獲取參數,帶默認值,非必傳
order_id = self.arg('order_id','')
#獲取int型參數
user_type = self.arg_int('user_type')
#獲取bool型參數
is_admin = self.arg_bool('is_admin')
#(用戶)客戶端ip地址
user_ip = self.user_ip
9) API系統服務部署
- 部署nginx ,nginx配置文件路徑, api/conf/nginx/nginx.conf
- 執行 bash api/tornado.sh 執行進程的數量,端口號均在這里配置。
日志切割
#Delete old more than 7 days log files
0 0 * * * /data/python/fastor/api/bin/logrotate-nginx.sh > /dev/null 2>&1
5 0 * * * /data/python/fastor/api/bin/logrotate.sh > /dev/null 2>&1
22 2 * * * find /data/logs/ -mtime +7 -type f -name "*log*" -exec rm -rf {} \;
10) API安全數字簽名,此功能適合高手
1)API接口安全規則
Method : GET | POST
增加參數:
_s_: signature 簽名
_t_: 當前時間戳,校隊系統時間在初始化接口返回,接口參數有效期30分鐘
_t_ = timestamp = timestamp + (客戶端當前時間 - 客戶端從初始化獲得timestamp的時間)
這樣做到原因是需要客戶端校對服務器時間,因為客戶端時間有可能不準確。
簽名方式:
token_string = req_method + ":" + path + ":" + sorted(query) + ":" + timestamp + ":" + secret
其中:sorted(query) 是按照key的自然順序排列,然后以key=value的形式累加
例如: GET /test?b=2&a=1
token_string = GET + ":" + /test + ":" + a=1b=2 + ":" + 1457665234 + ":" + secret_xxxxxx
signature = ngx.md5(token_string)
*method為post的情況下,需要將請求發到body中,不支持url參數post*
接口返回狀態碼為 410 請重新更新服務器時間。
接口返回 403 為簽名錯誤,訪問被禁止。
2)Nginx 部署,詳見 deploy.secure.api.sh
- 這里建議使用 nginx-1.0.4 版本,穩定/性能高。
- deploy.secure.api.sh部署起來過于繁瑣,需要花費一定的時間和經歷。
- 部署完畢后建議制作鏡像。
- 如果下載不到歷史版本,可以從百度云盤下載,鏈接: https://pan.baidu.com/s/19-5fSBn5wM-xwGLZL-K34Q 提取碼: jhbt
3)nginx配置示例
#lua配置地址:api/conf/nginx/lua
#簽名密鑰配置:api/conf/nginx/lua/check_pid_signature.lua
local secret = "82406d2ff6c40894a26a3ad34eafff2f" #32位字符串
location / {
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Headers X-Requested-With;
add_header Access-Control-Allow-Methsods GET,POST,OPTIONS;
#引入效驗文件,如上傳圖片,初始化接口可不加載該配置
access_by_lua_file conf/lua/check_pid_signature.lua;
proxy_pass http://make_app_api;
proxy_connect_timeout 3;
proxy_send_timeout 3;
proxy_read_timeout 3;
proxy_redirect default;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $http_host;
proxy_set_header Range $http_range;
}
未來版本支持
tensorflow 基礎版本基于大數據的用戶分類
圖像識別 opencv 拍照識別答題卡
作者: 向Ed老師曾經的戰友們致敬!
總結
以上是生活随笔為你收集整理的python 服务端框架_GitHub - edisonlz/fastor: Python服务端开发框架-极易上手,超出你的想象!...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: sqlsession.selectlis
- 下一篇: 吃亚麻籽油可以减肥吗