Flask 基于Flask-JSONRPC提供RPC接口

服务端基于Flask-JSONRPC提供RPC接口

JSON-RPC是一个无状态的、轻量级的远程过程调用(RPC)协议。

所谓的RPC,Remote Procedure Call的简写,中文译作远程过程调用或者远程服务调用

直观的理解就是,通过网络请求远程服务,获取指定接口的数据,而不用知晓底层网络协议的细节。

RPC支持的格式很多,比如XML格式,JSON格式等等。最常用的肯定是json-rpc。

JSON-RPC协议中的客户端一般是为了向远程服务器请求执行某个方法/函数。客户端向实现了JSON-RPC协议的服务端发送请求,多个输入参数能够通过数组或者对象传递到远程方法,这个远程方法也能返回多个输出数据,具体是什么,当然要看具体的方法实现。因为RPC可以通俗理解为:

客户端请求服务端完成某一个服务行为,所以RPC规范要求: 客户端发送的所有请求都是POST请求!!!

所有的传输数据都是单个对象,用JSON格式进行序列化。

请求要求包含三个特定属性:

jsonrpc: 用来声明JSON-RPC协议的版本,现在基本固定为“2.0”

method,方法,是等待调用的远程方法名,字符串类型

params,参数,对象类型或者是数组,向远程方法传递的多个参数值

id,任意类型值,用于和最后的响应进行匹配,也就是这里设定多少,后面响应里这个值也设定为相同的
响应的接收者必须能够给出所有请求以正确的响应。这个值一般不能为Null,且为数字时不能有小数。

响应也有三个属性:

jsonrpc, 用来声明JSON-RPC协议的版本,现在基本固定为“2.0”

result,结果,是方法的返回值,调用方法出现错误时,必须不包含该成员。

error,错误,当出现错误时,返回一个特定的错误编码,如果没有错误产生,必须不包含该成员。

id,就是请求带的那个id值,必须与请求对象中的id成员的值相同。请求对象中的id时发生错误(如:转换错误或无效的请求),它必须为Null

当然,有一些场景下,是不用返回值的,比如只对客户端进行通知,由于不用对请求的id进行匹配,所以这个id就是不必要的,置空或者直接不要了。

在flask中要实现提供json-rpc接口,开发中一般使用Flask JSON-RPC模块来实现。

git地址:https://github.com/cenobites/flask-jsonrpc

文档:http://wiki.geekdream.com/Specification/json-rpc_2.0.html

安装Flask-JSONRPC模块

# pip install Flask-JSONRPC          # 如果出现问题,则降低版本到0.3.1
pip install Flask-JSONRPC==0.3.1

快速实现一个测试的RPC接口。

例如,我们直接在application/__init__.py项目初始化文件中进行初始化jsonrpc并关闭csrf防范机制,代码。

import os,logging

from flask import Flask
from flask_script import Manager
from flask_sqlalchemy import SQLAlchemy
from flask_redis import FlaskRedis
from flask_session import Session
from flask_migrate import Migrate,MigrateCommand
from flask_jsonrpc import JSONRPC

from application.utils import init_blueprint
from application.utils.config import load_config
from application.utils.session import init_session
from application.utils.logger import Log
from application.utils.commands import load_command
# 创建终端脚本管理对象
manager = Manager()

# 创建数据库链接对象
db = SQLAlchemy()

# redis链接对象
redis = FlaskRedis()

# Session存储对象
session_store = Session()

# 数据迁移实例对象
migrate = Migrate()

# 日志对象
log = Log()

# 初始化jsonrpc模块
jsonrpc = JSONRPC(service_url='/api')

def init_app(config_path):
    """全局初始化"""
    # 创建app应用对象
    app = Flask(__name__)
    # 项目根目录
    app.BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

    # 加载配置
    Config = load_config(config_path)
    app.config.from_object(Config)

    # 数据库初始化
    db.init_app(app)
    redis.init_app(app)

    # session存储初始化
    init_session(app)
    session_store.init_app(app)

    # 数据迁移初始化
    migrate.init_app(app,db)
    # 添加数据迁移的命令到终端脚本工具中
    manager.add_command('db', MigrateCommand)

    # 日志初始化
    app.log = log.init_app(app)

    # 蓝图注册
    init_blueprint(app)

    # 初始化json-rpc
    jsonrpc.init_app(app)

    # 初始化终端脚本工具
    manager.app = app

    # 注册自定义命令
    load_command(manager)

    return manager

application/apps/home/views.py,编写接口代码:

# 实现rpc接口
from application import jsonrpc
@jsonrpc.method(name="Home.index")
def index():
    return "hello world!"

客户端需要发起post请求,访问地址为:http://服务器地址:端口/api

注意

默认情况下,/api接口只能通过post请求访问。如果要使用jsonrpc提供的界面调试工具,则访问地址为:

http://服务器地址端口/api/browse/

可以通过postman发送请求接口,访问数据格式应是:

请求地址:http://127.0.0.1:5000/api
请求体:
{
    "jsonrpc": "2.0",
    "method": "Home.index",
    "params": {},
    "id": "1"
}

请求效果:

Flask  基于Flask-JSONRPC提供RPC接口

错误提示:如果访问浏览器页面空白,终端显示如下:

Flask  基于Flask-JSONRPC提供RPC接口

则是因为Flask版本与 Werkzeug 组件版本不兼容的问题导致。

解决方案1,降低Werkzeug版本到0.16以下版本:

pip uninstall Werkzeug
pip install Werkzeug==0.16.1

解决方案2,修改flask/json.py文件中源码的判断条件,把is_xhr改成is_json

if current_app.config['JSONIFY_PRETTYPRINT_REGULAR'] and not request.is_json:

基于api接口接受来自客户端的参数

接口代码:

from application import jsonrpc
@jsonrpc.method(name="Home.index")
def index(id):
    return "hello world!id=%s" % id

postman, 发起请求:

Flask  基于Flask-JSONRPC提供RPC接口

移动端访问测试接口

因为当前我们的服务端项目安装在虚拟机里面,并且我们设置了虚拟机的网络连接模式为NAT,所以一般情况下,我们无法直接通过手机访问虚拟机。因此,我们需要配置一下。

  1. 打开VM的“编辑“菜单,选中虚拟网络编辑器。

Flask  基于Flask-JSONRPC提供RPC接口

  1. 打开编辑器窗口,使用管理员权限,并点击“NAT设置”。

Flask  基于Flask-JSONRPC提供RPC接口

  1. 填写网关IP地址,必须和子网IP在同一网段。末尾一般为1。接着在端口转发下方点击“添加”。

Flask  基于Flask-JSONRPC提供RPC接口

  1. 在映射传入端口中,填写转发的端口和实际虚拟机的IP端口,填写完成以后,全部点击“确定”,关闭所有窗口。将来,手机端访问PC主机的8083端口就自动访问到虚拟机。8083是自定义的,可以是其他端口。

Flask  基于Flask-JSONRPC提供RPC接口

  1. 查看手机wifi连接中,当前手机的IP地址。那么接下来,手机要访问到虚拟机的地址就是当前手机的前面三段+1:8083即可。

Flask  基于Flask-JSONRPC提供RPC接口

  1. 在APP中通过访问192.168.137.1:8083/api/browse
    Flask  基于Flask-JSONRPC提供RPC接口

Flask  基于Flask-JSONRPC提供RPC接口

出现页面则表示访问成功。

上一篇:HTTP上的RPC


下一篇:博文|你还在用python写API,赶紧体验全新curl、jq的API!