vnpy源码学习记录(4) ----------RPC网关
RPC启动
examples/client_server/server/run_server.py 为在RPC服务在本项目中的使用方法
1.1 添加RPC应用(实例化)
1.1.1 预处理引擎
- 启动项目时添加RPC应用
- 获取RPC应用实例,并添加RPC引擎:
- 实例化引擎:
1.1.2 实例化服务
首先加载配置信息,然后初始化服务
- 加载配置信息:self.load_setting() 配置文件配置客户端的地址,因为这里是客户端,因此适配所有的ip: rep_address表示可请求地址;pub_address表示可订阅地址
- 初始化服务: 先实例化RPC服务,再初始化(注册)方法 a) 实例化RPC服务 继承了RpcServer类:RpcServer类是RPC服务器运行函数,运行在服务器上,里面初始化了一些变量,并定义了基本函数,如:start()、run()、stop()等 b) 注册方法 注册一些客户端会使用的方法
1.2 启动RPC服务
开启RPC服务: 先获取到rpc引擎的实例,再调用start方法开启服务 start方法调用了RpcServer类的start()方法启动RPC服务: 到此VNPY中的RPC服务启动完成
2. RPC服务应用
rpc服务可以通过广播/订阅的方式向客户端推送数据,也可以通过客户端调用服务端注册的方法返回数据。
2.1 广播/订阅
RPC服务广播,只需要调用服务中def publish(self, topic: str, data: Any):即可。topic为推送的主题,data为推送的数据 然后客户端只需要通过tc.subscribe_topic("")即可订阅服务器推送的数据。参数为订阅的主题,“”表示订阅所有主题。只有配置了的地址(配置文件中的sub_address)可使用订阅功能。**注意:截止当前的测试(2019-08-05),向subscribe_topic传递相应的主题参数获取不到广播的数据,只有使用““””订阅全部主题才可收取到信息。**现已解决。
在vnpy中,CTP接口接收到的数据就可以通过广播的形式推送,然后客户端订阅。CTP接收行情数据的接口为onRtnDepthMarketData
2.2 方法请求
可以通过在服务端注册方法,然后客户端远程调用。 比如客户端查询服务端的数据库中的数据,使用RPC服务的话,在服务端编写好查询代码: 然后在实例化服务类的时候注册该方法 目前vnpy中注册了的方法见vnpy/app/rpc_service/ engine.py中init_server() 客户端使用: 直接调用该方法即可。只有配置了的地址(配置文件中的req_address)可使用请求功能。
3. 客户端使用
3.1 启动客户端
req_address = "tcp://ip:port" #客户端请求地址 sub_address = "tcp://ip:port" #客户端订阅地址 tc = TestClient() # 实例化客户端类 tc.start(req_address, sub_address) # 启动客户端服务
3.2 接收说明
不管是通过订阅方式获取数据还是请求调用方法方式获取数据,如果返回的是一个自定义类的对象,如广播的行情数据TickData或请求查询的合约信息ContractData等,都需要在客户端有响应的类,且路径要与服务端相同。使用到自定义的类也需要同样的操作,如Exchange。
订阅指定主题的解决方法:
def subscribe_topic(self, topic: str): """ Subscribe data 订阅特定主体的广播数据 topic = 订阅所有主题 """ if topic != "": self.topic.append(topic) if topic == "" or topic == : self.topic.append("all") self.__socket_sub.setsockopt_string(zmq.SUBSCRIBE, "")
def callback(self, topic, data): """ Realize callable function """ if "all" in self.topic: print(f"client received topic:{topic}, data:{data}") elif topic in self.topic: print(f"client received topic:{topic}, data:{data}")