我正在使用flask应用程序来显示使用零rpc订阅者读取的数据。 虽然我在使用Pycharm启动应用程序时开发工作正常但是一旦部署在Apache服务器中,订阅者就无法获取任何数据。基本上,即使发布者正在发布数据,也不会调用订阅者中的方法。
由于
编辑:(添加更多信息):
在app_start.py
from gevent import monkey
monkey.patch_all()
from flask import Flask
app = Flask(__name__)
import stratgy_subscriber
startegy_state_info_provider = stratgy_subscriber.StartegyStateInfoProvider()
@app.route('/')
def strategy_info():
return startegy_state_info_provider.ip_port_to_subscriber_map[('0.0.0.0', '4249')]
if __name__ == '__main__':
startegy_state_info_provider.start_subscriber('0.0.0.0', '4249')
app.run()
我使用以下代码连接到订阅者。 在stratgy_subscriber.py
中from gevent import monkey
monkey.patch_all()
class StartegyStateInfoProvider(object):
def __init__(self):
self.ip_port_to_subscriber_map = {}
def start_subscriber(machine_ip, port):
strategy_state_subscriber = StrategyStateSubscriber()
ip_port_to_subscriber_map[(machine_ip, port)] = strategy_state_subscriber
end_point = 'tcp://' + machine_ip + ':' + port
strategy_state_subscriber = zerorpc.Subscriber(strategy_state_subscriber)
strategy_state_subscriber.connect(end_point)
gevent.spawn(strategy_state_subscriber.run)
class StrategyStateSubscriber():
def __init__(self):
self.strategy_id_to_info_map = {}
def update_strategy_state(self, strategy_id, updated_strategy_state):
from datetime import datetime
current_time = datetime.strftime(datetime.now(), '%H:%M:%S')
updated_strategy_state.append(current_time)
print updated_strategy_state
strategy_id_to_info_map[strategy_id] = updated_strategy_state
这是发布者`
endpoint = "tcp://0.0.0.0:4249"
publisher = zerorpc.Publisher()
publisher.bind(endpoint)
for a in xrange(0, 1000):
info = [False, a * a, 3 * a, a % 20, a % 50]
publisher.update_strategy_state(a, info)
if a < 50:
gevent.sleep(1)
elif a >= 50:
gevent.sleep(2)
订阅后,即gevent.spawn(strategy_state_subscriber.run),每次发布者发布未发生的数据时,都应调用update_strategy_state。
我遇到以下异常:
[Wed May 28 11:24:03 2014] [error] Traceback (most recent call last):
[Wed May 28 11:24:03 2014] [error] File "/home/sricharan/git_ceres_viewer/src/strategy_state_subscription.py", line 68, in subscribe
[Wed May 28 11:24:03 2014] [error] subscriber = zerorpc.Subscriber(service)
[Wed May 28 11:24:03 2014] [error] File "/usr/local/lib/python2.7/dist-packages/zerorpc/core.py", line 371, in __init__
[Wed May 28 11:24:03 2014] [error] zmq_socket=zmq.SUB)
[Wed May 28 11:24:03 2014] [error] File "/usr/local/lib/python2.7/dist-packages/zerorpc/core.py", line 312, in __init__
[Wed May 28 11:24:03 2014] [error] super(Puller, self).__init__(zmq_socket, context=context)
[Wed May 28 11:24:03 2014] [error] File "/usr/local/lib/python2.7/dist-packages/zerorpc/socket.py", line 34, in __init__
[Wed May 28 11:24:03 2014] [error] self._events = Events(zmq_socket_type, context)
[Wed May 28 11:24:03 2014] [error] File "/usr/local/lib/python2.7/dist-packages/zerorpc/events.py", line 177, in __init__
[Wed May 28 11:24:03 2014] [error] self._socket = zmq.Socket(self._context, zmq_socket_type)
[Wed May 28 11:24:03 2014] [error] File "/usr/local/lib/python2.7/dist-packages/zerorpc/gevent_zmq.py", line 61, in __init__
[Wed May 28 11:24:03 2014] [error] self.__dict__["_state_event"] = gevent.hub.get_hub().loop.io(
[Wed May 28 11:24:03 2014] [error] File "/usr/lib/python2.7/dist-packages/gevent/hub.py", line 135, in get_hub
[Wed May 28 11:24:03 2014] [error] raise NotImplementedError('gevent is only usable from a single thread')
[Wed May 28 11:24:03 2014] [error] NotImplementedError: gevent is only usable from a single thread
经过一番研究后我发现: - gevent与Apache的多线程工作者模型不兼容
答案 0 :(得分:2)
最后我开始工作了。
import zerorpc
import gevent
from subscrclass import StrategyStateSubscriber
strategy_state_subscriber = StrategyStateSubscriber()
machine_ip = "127.0.0.1"
port = "5555"
end_point = "tcp://" + machine_ip + ":" + port
strategy_state_subscriber = zerorpc.Subscriber(strategy_state_subscriber)
strategy_state_subscriber.connect(end_point)
gevent.spawn(strategy_state_subscriber.run)
gevent.sleep(5) # This line was added
带有子驱动程序调用的原始代码以产生它的方式结束,但实际上并没有给代码做任何事情的机会。
如果我添加了gevent.sleep(5)
,则协同程序有机会运行5秒钟并且出现打印件。
请务必使用gevent
次调用,简单time.sleep(5)
无法正常工作,因为它阻止了一个,协同程序没有机会说一句话或运行一行代码。
使用PyCharm IDE我可以想象,你要么有类似的线存在,要么你“慢慢”执行动作,它有机会运行。但这是纯粹的猜测 - 重要的是在代码退出之前为代码提供运行协同程序的机会。
这是完整的可运行样本
subscrclass.py
此课程实际上会接收来自发布商的电话。重要的是:
update_strategy_state
这就是:
from datetime import datetime
class StrategyStateSubscriber():
def update_strategy_state(self, strategy_id, state):
print datetime.strftime(datetime.now(), "%H:%M:%S"), state
pub.py
这是出版商。
它不会导入任何东西来获取StrategyStateSubscriber,它只会创建对某个远程订阅者的调用,该远程订阅者可能实现了一个名为update_strategy_state
的方法,其中包含两个参数。
import gevent
import zerorpc
publisher = zerorpc.Publisher()
publisher.bind("tcp://0.0.0.0:5555")
for a in xrange(0, 1000):
publisher.update_strategy_state(a, [False, a * a, 3 * a, a % 20, a % 50])
gevent.sleep(1 if a < 50 else 2)
client.py
最后,我们来到客户,订阅已发布的调用并将其传递给在类StrategySateSubscriber
上实现的相关方法(由发布者决定)
import zerorpc
import gevent
from subscrclass import StrategyStateSubscriber
strategy_state_subscriber = zerorpc.Subscriber(StrategyStateSubscriber())
strategy_state_subscriber.connect("tcp://127.0.0.1:5555")
gevent.spawn(strategy_state_subscriber.run)
gevent.sleep(5)
允许生成的进程运行很重要,我们在这里调用gevent.sleep(5)
,其他调用或非阻塞I / 0操作也可以提供帮助。
在第一个控制台中启动发布者:
$ python pub.py
在第二个控制台中,启动客户端:
$ python client.py
22:30:06 [False, 16, 12, 4, 4]
22:30:07 [False, 25, 15, 5, 5]
22:30:08 [False, 36, 18, 6, 6]
22:30:09 [False, 49, 21, 7, 7]
22:30:10 [False, 64, 24, 8, 8]