2. 服務端項目搭建
進入服務器,安裝各種包
sudo apt-get update # 更新相關源 sudo apt-get install git # 按照git # mysql的安裝 sudo apt-get install mysql-server sudo apt-get install libmysqlclient-dev
進入數據庫, 剛安裝完成的數據庫,root是空密碼,所以要修改root的密碼
mysql -uroot -p # 修改密碼 use mysql; update user set authentication_string=password('新密碼') where user='root' and Host ='localhost'; update user set plugin="mysql_native_password"; # 刷新權限 flush privileges;
創建數據庫命令如下:
create database mogu charset=utf8mb4;
redis安裝
sudo apt-get install redis-server
注意,redis安裝完成以后,要觀察redis是否啟動了,如果沒有啟動,則參考之前redis筆記,啟動redis。
# 查看是否啟動redis-server,一般是沒啟動 # 原因是現在的雲服務器基本都默認給redis配置一個IPV6的綁定地址。而我們大部分人的服務器是沒使用IPV6的 ps -aux | grep redis # 如果沒有啟動,則運行以下命令,再查看是否啟動成功,再不行,則查看下面 注意事項 redis-server /etc/redis/redis.conf
注意事項:給服務器開通redis的6379,你也可以把全部端口打開(騰訊雲可以)
sudo apt install python3-pip
pip3 install virtualenv
pip3 install virtualenvwrapper
安裝完成了以后,接下來需要配置系統環境變量
mkdir $HOME/.virtualenvs
執行命令,打開並編輯 ~/.bashrc
vim ~/.bashrc
文件末尾添加以下幾行代碼(注意最后一句命令,和我們本地的有所不同),:wq 保存退出。
export WORKON_HOME=$HOME/.virtualenvs export VIRTUALENVWRAPPER_PYTHON=/usr/bin/python3 source /usr/local/bin/virtualenvwrapper.sh
可以用一下操作查看到你的虛擬環境實際地址
whereis virtualenvwrapper # 查看地址 /home/ubuntu/.local/bin/virtualenvwrapper.sh
刷新配置文件
source ~/.bashrc
mkvirtualenv mogu -p python3
安裝依賴模塊
pip install flask==1.0.3 pip install pymysql==0.9.3 pip install redis==3.2.1 pip install flask-sqlalchemy==2.4.0 pip install flask-mysqldb==0.2.0 pip install flask-session==0.3.1 pip install flask-script==2.0.6 pip install flask-migrate==2.5.2
我們把項目搭建在/home/mogu目錄下
cd /home mkdir moguapp cd moguapp # 創建flask項目啟動文件manage.py vim manage.py
manage.py文件代碼:
from flask import Flask app = Flask(__name__) @app.route('/') def index(): return 'hello,moluo~' if __name__ == '__main__': app.run(host="0.0.0.0")
在終端下使用python manage.py運行測試服務器
python manage.py
前面我們已經在雲服務器控制台的網絡安全組中添加5000端口,所以可以直接通過瀏覽器進行訪問。
到碼雲上面,創建一個git倉庫,把服務器代碼上傳到碼雲
git config --global user.name "mooluo" git config --global user.email "649641514@qq.com" git init git add . git commit -m "創建manage.py啟動文件" git remote add origin https://gitee.com/mooluo/moguapp.git git push -u origin master
apt install tree
moguapp/ ├─ logs/ # 日志文件存儲目錄 ├─ apps/ # 項目主要邏輯業務代碼保存目錄 │ ├─ __init__.py # 項目初始化文件 │ ├─ modules/ # 保存項目中所有api模塊的存儲目錄 │ │ ├─ common/ # 公共api接口目錄 │ │ │ ├─ __init__.py # 公共api接口的初始化文件 │ │ │ ├─ models.py # 公共api接口的模型文件 │ │ │ └─ api.py # 公共api接口代碼文件 │ │ └─ __init__.py | ├─ utils/ # 項目自定義封裝工具包目錄 | ├─ libs/ # 項目第三方工具包目錄 | ├─ settings/ # 項目配置存儲目錄 │ │ ├─ dev.py # 開發階段的配置文件 │ │ ├─ prop.py # 生產階段的配置文件 │ │ └─ __init__.py │ └─ statics/ # 保存項目中所有的靜態資源文件[img/css/js] └── manage.py # 項目的終端管理腳本文件
Config項目配置
在
import redis class Config(object): """項目配置信息""" # 設置密鑰,可以通過 base64.b64encode(os.urandom(48)) 來生成一個指定長度的隨機字符串 SECRET_KEY = "T1vEjTCjkGon5vU8C6Xq3ujNSQgHQje" # 配置日志 LOG_LEVEL = "DEBUG" # 調試模式 DEBUG = True # 數據庫的配置信息 SQLALCHEMY_DATABASE_URI = "mysql://root:123456@127.0.0.1:3306/mogu?charset=utf8" SQLALCHEMY_TRACK_MODIFICATIONS = True SQLALCHEMY_ECHO = True # redis配置 REDIS_HOST = "127.0.0.1" REDIS_PORT = 6379 # session 配置 SESSION_TYPE = "redis" # 指定 session 保存到 redis 中 SESSION_USE_SIGNER = True # session_id 進行加密簽名處理 SESSION_REDIS = redis.StrictRedis( host=REDIS_HOST, port=REDIS_PORT,db=1 ) PERMANENT_SESSION_LIFETIME = 24 * 60 * 60 # session 的有效期,單位是秒
from . import Config class DevelopementConfig(Config): """開發模式下的配置""" pass
from . import Config class ProductionConfig(Config): """生產模式下的配置""" DEBUG = False LOG_LEVEL = "INFO" SQLALCHEMY_TRACK_MODIFICATIONS = False SQLALCHEMY_ECHO = False
配置項目日志
把日志設置封裝成一個函數init_log
,保存到utils/log.py
import logging from logging.handlers import RotatingFileHandler # 把日志相關的配置封裝成一個日志初始化函數 def init_log(Config): # 設置日志的記錄等級 logging.basicConfig(level=Config.LOG_LEVEL) # 調試debug級 # 創建日志記錄器,指明日志保存的路徑、每個日志文件的最大大小、保存的日志文件個數上限 file_log_handler = RotatingFileHandler("logs/log", maxBytes=1024 * 1024 * 300, backupCount=10) # 創建日志記錄的格式 日志等級 輸入日志信息的文件名 行數 日志信息 formatter = logging.Formatter('%(levelname)s %(filename)s:%(lineno)d %(message)s') # 為剛創建的日志記錄器設置日志記錄格式 file_log_handler.setFormatter(formatter) # 為全局的日志工具對象(flaskapp使用的)添加日志記錄器 logging.getLogger().addHandler(file_log_handler)
項目初始化代碼抽取
在apps/__init__.py
from flask import Flask from redis import StrictRedis from flask_session import Session from flask_sqlalchemy import SQLAlchemy from apps.settings.dev import DevelopementConfig from apps.settings.prop import ProductionConfig from apps.utils.log import init_log config = { "dev": DevelopementConfig, "prop": ProductionConfig, } # 預設全局變量 redis_store = None db = SQLAlchemy() def init_app(config_name): """項目的初始化功能""" app = Flask(__name__) # 設置配置類 Config = config[config_name] # 加載配置 app.config.from_object(Config) # redis的鏈接初始化 global redis_store redis_store = StrictRedis(host=Config.REDIS_HOST, port=Config.REDIS_PORT,db=0) # 開啟session功能 Session(app) # 配置數據庫鏈接 db.init_app(app) # 啟動日志 init_log(Config) return app
配置項目啟動文件
# coding=utf-8 from flask_script import Manager from flask_migrate import Migrate, MigrateCommand from apps import init_app,db app = init_app("dev") # 使用終端腳本工具啟動和管理flask manager = Manager(app) # 啟用數據遷移工具 Migrate(app, db) # 添加數據遷移的命令到終端腳本工具中 manager.add_command('db', MigrateCommand) @app.route('/') def index(): return 'hello,moluo~' if __name__ == '__main__': manager.run()
在虛擬環境重新使用manage.py啟動項目
sudo pip install flask_script
sudo pip install flask_migrate
sudo easy_install redis
python manage.py runserver --host=0.0.0.0 --port=5000
4.
所謂的RPC,Re
mote Procedure Call
的簡寫,中文譯作遠程過程調用或者遠程服務調用。
直觀的理解就是,通過網絡來請求服務,獲取接口數據,而不用知曉底層網絡協議的細節。
RPC
支持的格式很多,比如XML
格式,JSON
格式等等。最常用的肯定是json-rpc。
JSON-RPC協議中的客戶端一般是為了向遠程服務器請求執行某個方法/函數。客戶端向實現了JSON-RPC協議的服務端發送請求,多個輸入參數能夠通過數組或者對象傳遞到遠程方法,這個遠程方法也能返回多個輸出數據,具體是什么,當然要看具體的方法實現。
jsonrpc: 用來聲明JSON-RPC協議的版本,現在基本固定為“2.0”
method,方法,是等待調用的遠程方法名,字符串類型
params,參數,對象類型或者是數組,向遠程方法傳遞的多個參數值
id,任意類型值,用於和最后的響應進行匹配,也就是這里設定多少,后面響應里這個值也設定為相同的
響應的接收者必須能夠給出所有請求以正確的響應。這個值一般不能為Null,且為數字時不能有小數。
響應也有三個屬性:
result,結果,是方法的返回值,調用方法出現錯誤時,必須不包含該成員。
error,錯誤,當出現錯誤時,返回一個特定的錯誤編碼,如果沒有錯誤產生,必須不包含該成員。
id,就是請求帶的那個id值,必須與請求對象中的id成員的值相同。請求對象中的id時發生錯誤(如:轉換錯誤或無效的請求),它必須為Null
當然,有一些場景下,是不用返回值的,比如只對客戶端進行通知,由於不用對請求的id進行匹配,所以這個id就是不必要的,置空或者直接不要了。
git地址:https://github.com/cenobites/flask-jsonrpc
文檔:
pip install Flask-JSONRPC==0.3.1
快速實現一個測試的RPC接口。
例如,我們直接在manage.py啟動文件中直接實現。
from apps import init_app,db from flask_script import Manager from flask_migrate import Migrate, MigrateCommand from flask_jsonrpc import JSONRPC app = init_app("dev") # 使用終端腳本工具啟動和管理flask manager = Manager(app) # 啟用數據遷移工具 Migrate(app, db) # 添加數據遷移的命令到終端腳本工具中 manager.add_command('db', MigrateCommand) @app.route('/') def index(): return 'hello,moluo~' # 初始化jsonrpc模塊 jsonrpc = JSONRPC(app, '/api') # 實現rpc接口 @jsonrpc.method('Common.index') def index(): return u'Welcome to Flask JSON-RPC' if __name__ == '__main__': manager.run()
客戶端需要發起post請求,訪問地址為:http://服務器地址:端口/api
默認情況下,/api
接口只能通過post請求訪問。如果要使用jsonrpc提供的界面調試工具,則訪問地址為:
http://服務器地址端口/api/browse/
訪問數據格式應是:
{ "jsonrpc": "2.0", "method": "Common.index", "params": {}, "id": "1" }
通過postman訪問效果:
對RPC接口代碼進行模塊化分離
apps/__init__py
,代碼:
from flask import Flask from redis import StrictRedis from flask_session import Session from flask_sqlalchemy import SQLAlchemy from flask_jsonrpc import JSONRPC from apps.utils.log import init_log from apps.settings.dev import DevelopementConfig from apps.settings.prop import ProductionConfig config = { "dev": DevelopementConfig, "prop": ProductionConfig, } # 預設全局變量 redis_store = None db = SQLAlchemy() # 創建jsonrpc實例對象 jsonrpc = JSONRPC(app=None, service_url='/api', enable_web_browsable_api=True) def init_app(config_name): """項目的初始化功能""" app = Flask(__name__) # 設置配置類 Config = config[config_name] # 加載配置 app.config.from_object(Config) # redis的鏈接初始化 global redis_store redis_store = StrictRedis(host=Config.REDIS_HOST, port=Config.REDIS_PORT,db=0) # 開啟session功能 Session(app) # 配置數據庫鏈接 db.init_app(app) # 啟動日志 init_log(Config) # jsonrpc注冊到app應用對象中 jsonrpc.init_app(app) return app
modules/common/api.py,代碼:
from apps import jsonrpc # 實現rpc接口 @jsonrpc.method('Common.index') def index(): return u'Welcome to Flask JSON-RPC'
manage.py啟動文件中加載api接口
from apps import init_app,db from flask_script import Manager from flask_migrate import Migrate, MigrateCommand app = init_app("dev") # 使用終端腳本工具啟動和管理flask manager = Manager(app) # 啟用數據遷移工具 Migrate(app, db) # 添加數據遷移的命令到終端腳本工具中 manager.add_command('db', MigrateCommand) # api接口列表 from apps.modules.common import api @app.route('/') def index(): return 'hello,moluo~' if __name__ == '__main__': manager.run()
重新啟動項目,使用postman進行還是原來的結果,則表示調整成功,后面的開發中,我們只需要不斷增加對應的接口即可。
from apps import jsonrpc @jsonrpc.method("模塊名.方法名(username=String, password=String)") def 方法名(username,password): return u"賬號:%s,密碼:%s" % (username,password)
客戶端發送請求:
{ "jsonrpc": "2.0", "id": 188, "method": "Common.add", "params": { "username":"xiaohui", "age":33, "sex":false, "lve":["吃飯","睡覺",3,4,{"title":"aaaa"}], "son":{ "username":"xiaohuihui", "age":12 } } }
實現jsonrpc接口的版本迭代
apps/__init__
代碼:
from flask import Flask from redis import StrictRedis from flask_session import Session from flask_sqlalchemy import SQLAlchemy from flask_jsonrpc import JSONRPC from flask_jsonrpc.site import JSONRPCSite from apps.settings.dev import DevelopementConfig from apps.settings.prop import ProductionConfig from apps.utils.log import init_log config = { "dev": DevelopementConfig, "prop": ProductionConfig, } # 預設全局變量 redis_store = None db = SQLAlchemy() # jsonrpc實例化 jsonrpc = JSONRPC(service_url="/api/v1", site=JSONRPCSite(), enable_web_browsable_api=True) jsonrpc_v2 = JSONRPC(service_url="/api/v2", site=JSONRPCSite(), enable_web_browsable_api=True) def init_app(config_name): 。。。。 # 啟動日志 init_log(Config) # 把jsonrpc注入到app實例對象中 jsonrpc.init_app(app) jsonrpc2.init_app(app) return app
模塊目錄modules/common/api.py,代碼:
from apps import jsonrpc,jsonrpc2 @jsonrpc.method("Common.add(username=String,age=Number,sex=Boolean,lve=Array,son=Object)") def add_v1(username,age,sex,lve,son): return "username=%s,age=%s,sex=%s,lve=%s,son=%s" % (username,age,sex,lve,son) @jsonrpc2.method("Common.add(username=String,age=Number,sex=Boolean,lve=Array,son=Object)") def add_v2(username,age,sex,lve,son): return u"賬號=%s,年齡=%s,性別=%s,愛好=%s,后代=%s" % (username,age,sex,lve,son)
. |-- config.xml # app核心配置文件 |-- css/ # 公共css存儲目錄 | |-- api.css | `-- style.css |-- feature # 啟動畫面圖片 |-- html/ # 頁面/窗口的文件存儲目錄 |-- icon # 手機應用圖標 |-- image/ # 靜態圖片存儲目錄 |-- index.html |-- launch # 啟動畫面圖片 |-- res # 除了圖片以外的其他文件 |-- script/ # javascript文件存儲目錄 | `-- api.js `-- wgt # app模塊目錄
歡迎頁面
window APP的窗口
Frame 窗口里面的框架頁面
FrameGroup 框架頁面的組合
api.openWin({ name: 'page1', # window名字 url: './page1.html', # 頁面地址,可以為本地文件路徑,支持相對路徑和絕對路徑 pageParam: { # 頁面參數,新頁面中可以通過 api.pageParam 獲取 name: 'test' } });