python的rpc服务实现

最近工作中需要实现远程机器的自动化执行,调研了下实现机制,大体如下:

内置库:xmlrpc(使用http协议作为传输协议的rpc机制,使用xml文本的方式传输命令和数据,数据包大,速度慢)

第三方:ZeroRPC(底层使用ZeroMQ和MessagePack,基于TCP协议,轻量级的,速度快,响应时间短,并发高)

1. zerorpc

安装:

pip3 install zerorpc

服务端:

python 复制代码
# remote_rpc_server.py

import sys
from zerorpc import Server

class RemoteMethod:
    @staticmethod
    def print_info(name):
        # flush为了及时写入stdout文件
        print('name is ', name, flush=True)

if __name__ == '__main__':
    # 打开一个txt文件,将标准输出写入,因为远程的代码执行不会在客户端打印
    sys.stdout = open('log.txt', 'w+')
    server = Server(RemoteMethod())
    server.bind('tcp://0.0.0.0:4242')
    server.run()

客户端:

python 复制代码
# local_rpc_client.py

from zerorpc import Client

def rpc_client():
    client = Client(timeout=20)
    # 连接远程ip和端口
    client.connect('tcp://10.x.x.x:4242')
    return client

测试代码:

python 复制代码
import subprocess
from time import sleep
from local_rpc_client import rpc_client
# 拷贝项目文件到远程机器
cmd = ('sshpass -p 1 rsync -av --exclude=".idea" --exclude="__pycache__" /home/test/rpc_project test@10.x.x.x:~/Desktop')
with subprocess.Popen(cmd, shell=True) as proc:
    pass
# 启动远程rpc服务
cmd = 'sshpass -p 1 ssh test@10.x.x.x "cd ~/Desktop/rpc_project; python3 remote_rpc_server.py"'
# with subprocess.Popen(cmd, shell=True) as proc1:
#     pass
# 如果照上面这种写法,启动子进程后,代码执行会阻塞,不接着执行后续的代码。所以只能是不要等待子进程结束。。。
subprocess.Popen(cmd, shell=True)
sleep(2)
print('远程rpc服务已启动')
# 客户端调用远程方法
client = rpc_client()
client.print_info('hope succ')

运行测试代码后,可以在远程机器上查看log.txt文件,确定打印的内容写入,代表远程执行成功。以上代码只是个简单的示例,实际上还需要很多优化,比如要确认下远程rpc服务已启动成功再调用、远程机器的python环境要配置、远程rpc服务的启停设置等。

zerorpc依赖于MessagePack进行数据的序列化和反序列化,而MessagePack可能不支持某些复杂对象的序列化。如果说上面的print_info方法return obj(一个类实例),则可能会报错,这里需要注意,尽量return 基本数据类型。

2. xmlrpc

官方文档戳这里

服务端

python 复制代码
import inspect
from socketserver import ThreadingMixIn
from xmlrpc.server import SimpleXMLRPCServer


class ThreadXMLRPCServer(ThreadingMixIn, SimpleXMLRPCServer):
    pass
# ThreadingMixIn 多线程处理请求

class RemoteMethod:
    @staticmethod
    def print_info(name):
        # flush为了及时写入stdout文件
        print('name is ', name, flush=True)


if __name__ == '__main__':
    server = ThreadXMLRPCServer(("0.0.0.0", 4243), allow_none=True)
    members = inspect.getmembers(RemoteMethod, predicate=inspect.isfunction)
    for func_name, func in members:
        if not func_name.startswith("_"):
            server.register_function(func, func_name)
    server.serve_forever()

客户端和调用方法

python 复制代码
from xmlrpc import client

proxy = client.ServerProxy("http://10.x.x.x:4243/", allow_none=True)
proxy.print_info('succ')

allow_none=True,允许方法返回空,Python 常量 None 将被转写至 XML;默认行为是针对 None 引发 TypeError。

相关推荐
xiaoye-duck39 分钟前
《C++ 项目:手写大模型接入 SDK》DeepSeek接口设计(下):流式响应实现和测试
开发语言·网络·c++·语言模型
其实防守也摸鱼1 小时前
信创安全竞赛知识总结与题库
大数据·网络·人工智能·算法·安全·php
万联WANFLOW2 小时前
异地厂区视频监控远程运维:从组网到安全的实施要点
运维·网络·安全·企业组网·sdwan
衍玊2 小时前
深入剖析 TCP/IP 网络通信原理与内核实现
服务器·网络·tcp/ip
.Bryce.3 小时前
从零到一开发技术名词大全:从需求分析到 AI Agent 工程
java·网络·人工智能·agent·需求分析·agent评测
Black蜡笔小新4 小时前
上云网关/端口穿透/设备上云EasyNTS:无需公网IP、也不改防火墙,设备怎么从内网跑到外网去
网络·网络协议·tcp/ip
Escalating_xu5 小时前
【Linux 网络编程】五种 I/O 模型与非阻塞 I/O:从“等数据”到正确处理 EAGAIN
java·linux·网络
默|笙7 小时前
【Linux网络】传输层协议TCP(3)滑动窗口、流量控制
linux·网络·tcp/ip
xiaoye-duck7 小时前
《C++ 项目:手写大模型接入 SDK》ChatGPT接口设计(中):全量响应实现和测试
网络·c++·语言模型·chatgpt
无言听风雨丶9 小时前
systemd 与信号 / 僵尸进程:Linux 进程管理的底层逻辑与排错
linux·服务器·网络