Skip to main content

Keep Simple RPC

Project description

ksrpc

Keep Simple RPC。免注册远程过程调用

!!! 注意:已经迭代成第二代。第一代请参考fastapi分支

安全

注意:第二代只有Basic认证导入规则列表,其它功能无任何限制,甚至可以执行rm -rf /。所以强烈建议

  1. 账号只给少量可信之人
  2. 只部署在docker中
  3. 服务不用时最好停止,或定时任务启停
  4. 不要使用默认端口、默认账号、默认URL路径等
  5. 导入规则列表最后一条建议"*": False

第二代 vs 第一代

第一代

  1. 功能比较多:IP黑白名单、函数黑白名单、内网反代、数据缓存、跨语言多数据格式
  2. 实际考察发现,只有内网反代功能才是大家需要的,其他功能都极少有人用
  3. 缺点:由于当初没有在数据包中加入请求编号或会话编号,多人都挤同房间数据会混乱
  4. pip install ksrpc<0.6.0

第二代

  1. 考虑到大家只关注内网反代,所以决定用更专业的反代工具,如:frp
  2. 删减功能,只留API调用+Basic认证+导入规则列表
  3. 某平台中的FastAPI所创建的服务只要访问,uvicorn就崩溃,最后决定将客服端和服务端都替换成aiohttp
  4. asyncsync的互转导致系统非常混乱,清理只留async。客户端可以使用to_sync=True以同步方式调用
  5. pip install ksrpc>=0.6.0

安装

pip install ksrpc -i https://mirrors.aliyun.com/pypi/simple --upgrade
# 或
pip install ksrpc -i https://pypi.org/simple --upgrade

使用

  1. 服务端
# 直接运行
python -m ksrpc.run_app
# 使用配置运行,注意&前一定不要有空格
set CONFIG_SERVER=config_server.py&python -m ksrpc.run_app # windows
CONFIG_SERVER=config_server.py python -m ksrpc.run_app # linux
CONFIG_SERVER=config_server.py gunicorn ksrpc.run_gunicorn:web_app --bind 0.0.0.0:8080 --worker-class aiohttp.GunicornWebWorker # linux gunicorn
  1. 异步客户端(推荐)
import asyncio

from ksrpc.client import RpcClient
from ksrpc.connections import SmartConnection

URL = 'http://127.0.0.1:8080/api/v1'
USERNAME = 'admin'
PASSWORD = 'password123'


async def async_main():
   async with SmartConnection(URL, username=USERNAME, password=PASSWORD) as conn:
      demo = RpcClient('ksrpc.server.demo', conn)
      print(await demo.test())


asyncio.run(async_main())
  1. 同步客户端
import nest_asyncio

from ksrpc.client import RpcClient
from ksrpc.connections.http import HttpConnection  # noqa
from ksrpc.connections.websocket import WebSocketConnection  # noqa

URL = 'http://127.0.0.1:8080/api/v1'
USERNAME = 'admin'
PASSWORD = 'password123'

# 必用,否则同步模式只能调用第一次,第二次会报 RuntimeError: Event loop is closed
nest_asyncio.apply()


def sync_main():
   with HttpConnection(URL, username=USERNAME, password=PASSWORD) as conn:
      demo = RpcClient('ksrpc.server.demo', conn, to_sync=True)
      print(demo.test())


sync_main()

conn = WebSocketConnection(URL, username=USERNAME, password=PASSWORD)
demo = RpcClient('ksrpc.server.demo', conn, to_sync=True)
print(demo.test())
print(demo.test())

远程调用规则

# eager模式
RpcClient(..., lazy=False)
await 一个模块.零到多个模块或方法或属性.一个方法或属性(参数)
# lazy模式
RpcClient(..., lazy=True)
await 一个模块.零到多个模块或方法或属性.一个方法或属性(参数).一个方法或属性(参数).collect()

eager模式

  1. 语句后接()就会触发远程调用
  2. .后的函数用来收集调用链
  3. []本质是.__getitem__(item),内部会调整成.__getattr__("__getitem__").__call__(item),会立即触发远程调用
  4. 大部分情况用户代码只在最后出现()[]eager模式已经够用

lazy模式

  1. 语句后接collect()就会触发远程调用
  2. .后的函数用来收集调用链,()用来收集参数
  3. []本质同eager模式,但触发要等collect()
  4. 只要语句中间出现()[]lazy模式才能处理

lazy模式特别语法

部分语句还是非常难实现

  1. __getattr__('__str__')() # 一般都存在,就算不存在也会退回到__repr__
  2. __getattr__('__int__')() # 自定义对象有可能实现,而str没有__int__

所以专门提供了一种特殊语法.func(Self),它能成功运行依赖于3个条件:

  1. from ksrpc.client import Self,然后传入Self参数
  2. builtins中已经定义了func函数
  3. config_server.pyIMPORT_RULES已经设置了"builtins": True,或没有设置builtins, 但设置了"*": True

前面两句可以简化成

  1. str(Self)
  2. int(Self)

建议先写原始代码测试通过,然后改成魔术方法版测试通过,最后才是远程异步版。例如:

from ksrpc.client import RpcClient, Self
from ksrpc.server import demo

print(len(demo.__file__))  # 1. 在服务端或本地测试是否通过
print(demo.__file__.__len__())  # 2. 翻译成魔术方法版。看是否正常

demo1 = RpcClient('ksrpc.server.demo', conn)
demo2 = RpcClient('ksrpc.server.demo', conn, lazy=True)
print(await demo1.__file__.__len__())  # 3. 改成远程异步版。网络中传输的是`int`
print((await demo1.__file__()).__len__())  # 得到结果一样,但网络中传输的是`str`,然后本地算的`len()`
print(await demo2.__file__.__len__().collect())  # lazy模式,collect()前的代码都会在服务端计算
print(await demo2.__file__.len(Self).collect())  # lazy模式下的Self扩展写法

print(demo1.__doc__)  # 取的其实是RpcClient的__doc__
print(await demo1.__getattr__('__doc__')())  # 取的远程ksrpc.server.demo.__doc__

更多调用方式参考examples

环境变量和配置

  1. 服务端ksrpc/config_server.py

    • CONFIG_SERVER 通过环境变量指定配置文件路径。例如CONFIG_SERVER=config_server.py
  2. 客户端ksrpc/config_client.py

    • CONFIG_CLIENT 通过环境变量指定配置文件路径。例如CONFIG_CLIENT=config_client.py

    • PRINT_PROGRESS=0 通过环境变量屏蔽下载进度条。可覆盖CONFIG_CLIENT中的设置

    • HTTP_ALLOW_REDIRECTS=0 通过环境变量禁用重定向。可覆盖CONFIG_CLIENT中的设置

pyi存根文件

可以查询远程所支持的函数,可以支持IDE自动补全,更多细节参考stubs

工作原理

  1. 创建Web服务,接收请求后,调用服务器中的Python库,将结果二进制封装后返回
  2. 客户端将API调用封装,然后向Web服务器请求,等待返回
  3. 返回结果解包成Python对象
  4. 反代时frp需要有公网服务器(或STUN内网穿透)。当然你也可以使用其他组网工具,如easytierwstunnel

内网反代参考examples_frp

传输方式

  1. 先整体zlib压缩,然后分chunk传输
    • 由于整体压缩,所以可以用第三方软件直接解压
    • 浏览器和其他工具能直接识别'Content-Encoding': 'deflate'并解压
    • 遇到数据大时,压缩就占用很长时间
  2. 先分chunk,每个chunk都分别使用zlib压缩再传输
    • 分块压缩,只能分块解压。第三方工具失效
    • 将大文件压缩耗时分拆了,速度显著提升
  3. 整体zlib压缩,直接传输
    • 请求体大小有限制,无法上传大数据

综合考虑,最终使用的是方案二。

为防止HTTP遇到30x重定向时重复传输大数据,所以HTTP第一次抓取重定向后地址,第二次才是正真的传输数据。可修改HTTP_ALLOW_REDIRECTS定制行为

支持IPv6

支持强制设置IPv4或IPv6

import socket

import aiohttp

from ksrpc.connections import SmartConnection  # noqa
from ksrpc.connections.http import HttpConnection  # noqa
from ksrpc.connections.websocket import WebSocketConnection  # noqa

connector = aiohttp.TCPConnector(family=socket.AF_INET6)  # IPv6
async with SmartConnection(URL, username=USERNAME, password=PASSWORD, connector=connector) as conn:
    pass

connector = aiohttp.TCPConnector(family=socket.AF_INET)  # IPv4
async with WebSocketConnection(URL, username=USERNAME, password=PASSWORD, connector=connector) as conn:
    pass

支持代理

import aiohttp

from ksrpc.connections.http import HttpConnection  # noqa

proxy = "http://127.0.0.1:10808"
proxy_auth = aiohttp.BasicAuth('user', 'pass')
async with HttpConnection(URL, username=USERNAME, password=PASSWORD, proxy=proxy, proxy_auth=None) as conn:
    pass

参考项目

开发到一定阶段后才发现与rpyc这个免注册暴露函数的功能类似,大家也可以去学习一下

https://github.com/tomerfiliba-org/rpyc

声明

此库仅供学习交流,请在数据提供方的授权范围内使用。请勿向第三方转发数据

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

ksrpc-0.8.1.tar.gz (31.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

ksrpc-0.8.1-py3-none-any.whl (41.7 kB view details)

Uploaded Python 3

File details

Details for the file ksrpc-0.8.1.tar.gz.

File metadata

  • Download URL: ksrpc-0.8.1.tar.gz
  • Upload date:
  • Size: 31.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.25

File hashes

Hashes for ksrpc-0.8.1.tar.gz
Algorithm Hash digest
SHA256 ff4bd69d4b99f1a8b2818c1e05edd0d29f14f1b2865efbee99a593f62a5d9d67
MD5 cf3028d7edd98a8e8eac993fc3cc2ecb
BLAKE2b-256 b694129fd0dcf7222e02041aa688dd827d3e49f6c45e93de99182b809c45bfa2

See more details on using hashes here.

File details

Details for the file ksrpc-0.8.1-py3-none-any.whl.

File metadata

  • Download URL: ksrpc-0.8.1-py3-none-any.whl
  • Upload date:
  • Size: 41.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.25

File hashes

Hashes for ksrpc-0.8.1-py3-none-any.whl
Algorithm Hash digest
SHA256 4f3842263911ff9032587c6f7eaee9173dd905da58c0c7a80a43bda28a8434c0
MD5 f053848a031ccd4558b7d27c745ede34
BLAKE2b-256 a32de65b9512a03d6f61781ed9e780d9d2c5078549f63af816adf3d5c2c650df

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page