调用HTTP接口¶
一般来说,推荐使用 deepfos.elements
中封装好的元素功能。
在以下情况,您可能需要直接调用HTTP接口。
现有元素功能不能满足需要,但是有合适的接口
元素功能引入了额外的接口调用,您希望优化性能
在阅读本节文档前,预设读者有基础的HTTP通信的相关知识,并且有一定的Python开发经验。 如果您认为您将要使用HTTP接口实现的功能有相当的通用性,欢迎您向deepfos提交PR。 流程可以参考这篇文档: 如何贡献。
前言¶
deepfos对HTTP接口的封装是多层级的。 例如一个web服务提供以下接口:
GET controller-1/resource-a
GET controller-1/resource-b
GET controller-2/resource-c
GET controller-2/resource-d
那么deepfos中会对应封装出以下方法:
api.controller_1.get_resource_a
api.controller_1.get_resource_b
api.controller_2.get_resource_c
api.controller_2.get_resource_d
Package deepfos.api
中所有对外的api都以上述形式组织。
HTTP接口分为系统接口和组件接口两大类。仅实例化方法略有不同,使用逻辑是完全一致的。
调用系统接口¶
已封装的接口可以在文档: HTTP接口 中看到。
所有可以实例化的接口都会在此处展示。
简单例子¶
以AppAPI为例,如果需要调用下图中的 get_server_names
方法
则可以使用
from deepfos.api.app import AppAPI
from deepfos.api.models.app import QueryElementInfoByTypeDto
api = AppAPI()
api.element_info.get_server_names([
QueryElementInfoByTypeDto(elementType='PY', elementName='test', path='/'),
QueryElementInfoByTypeDto(elementType='SML', elementName='test', path='/'),
])
所有的接口函数都有完整的类型提示,绝大多数情况下,您只要通过查看函数签名,不需要查看接口的swagger文档就可以完成一个接口的调用。
使用原生python对象¶
有时候为了调用一个简单接口而特意组装一个python对象有些大费周章。您可能更熟悉python的原生数据结构,如 list
, dict
等。
接口函数允许您不按照函数签名,而直接传入一个更接近 json
数据的参数。
同样以 get_server_names
方法为例,您还可以这样调用:
api.element_info.get_server_names([
{'elementName': 'test', 'elementType': 'PY', 'path': '/'},
{'elementName': 'test', 'elementType': 'SML', 'path': '/'},
])
尽管IDE可能会给您一些警告,但实际上这不会有任何问题,甚至比第一种调用方式性能更高!
隐藏的接口参数¶
除了签名所含有的参数外,接口函数还能够接收一些 “隐藏参数”
- resp_model
接口的返回模型
- retries
接口调用失败时的重试次数
resp_model
可以影响接口函数的返回。
按照签名, get_server_names
应该返回 List[ModuleServerNameVO]
对象,但假如希望拿到原始的 json
对象,
可以这样调用:
r = api.element_info.get_server_names([
{'elementName': 'test', 'elementType': 'PY', 'path': '/'},
{'elementName': 'test', 'elementType': 'SML', 'path': '/'},
], resp_model=None)
assert isinstance(r, list)
assert isinstance(r[0], dict)
此时函数将返回 List[Dict]
类型的对象。
您也可以传入其他有效的 Pydantic Model,如果能成功解析,返回的结果将会符合您定义的数据模型。
调用组件接口¶
调用组件接口与 调用系统接口 逻辑一致。但是由于组件可能存在多版本,实例化时必须指定组件版本。
api = MySQLAPI(version=1.0)
r = api.dml.run_sql('select 1')
异步调用接口¶
接口函数不仅能够同步调用,也可以异步调用:
import asyncio
async def run_sql():
api = MySQLAPI(version=1.0, sync=False)
r = await api.dml.run_sql('select 1')
asyncio.run(run_sql())
所有API在实例化时还接受一个可选参数 sync
,其默认值为 True
,即同步调用。
当传入 False
时,所有接口函数将变成异步函数。
异步编程常用于解决 I/O
并发问题,相较于线程,协程开销更小,切换更快,执行顺序明确,
而且只要内存允许,能够达到极高的并发量。
并发调用接口示例:
import asyncio
async def concurrently_run_sqls():
api = MySQLAPI(version=1.0, sync=False)
r = await asyncio.gather(
api.dml.run_sql('select 1'),
api.dml.run_sql('select 2'),
api.dml.run_sql('select 3'),
api.dml.run_sql('select 4'),
)
asyncio.run(concurrently_run_sqls())
配置项¶
有些配置项能够全局影响接口的行为。
- OPTION.api.verify_ssl
是否开启ssl校验
- OPTION.api.timeout
默认超时时间
- OPTION.api.dump_on_failure
是否在调用接口失败时输出curl命令
- OPTION.api.dump_always
是否在所有接口调用时输出curl命令