我在Amazon EC2机器上有以下pull-publisher ZMQ架构:
我正在使用我的EC2亚马逊机器的公共IP地址。
我正在尝试通过ZMQ PUSH
套接字从客户端向ZMQ PULL
套接字服务器端发送数据,这是:
import zmq
from zmq.log.handlers import PUBHandler
import logging
# from zmq.asyncio import Context
def main():
ctx = zmq.Context()
publisher = ctx.socket(zmq.PUB)
# publisher.bind("tcp://*:5557")
publisher.bind("tcp://54.89.25.43:5557")
handler = PUBHandler(publisher)
logger = logging.getLogger()
logger.addHandler(handler)
print("Network Manager CNVSS Broker listening")
collector = ctx.socket(zmq.PULL)
# collector.bind("tcp://*:5558")
collector.bind("tcp://54.89.25.43:5558")
while True:
message = collector.recv()
print("Publishing update %s" % message)
publisher.send(message)
if __name__ == '__main__':
main()
但是,当我执行此脚本时,我收到此错误:
(cnvss_nm) ubuntu@ip-172-31-55-72:~/cnvss_nm$ python pull_pub-nm.py
Traceback (most recent call last):
File "pull_pub-nm.py", line 28, in <module>
main()
File "pull_pub-nm.py", line 10, in main
publisher.bind("tcp://54.89.25.43:5557")
File "zmq/backend/cython/socket.pyx", line 547, in zmq.backend.cython.socket.Socket.bind
File "zmq/backend/cython/checkrc.pxd", line 25, in zmq.backend.cython.checkrc._check_rc
zmq.error.ZMQError: Cannot assign requested address
(cnvss_nm) ubuntu@ip-172-31-55-72:~/cnvss_nm$
我在服务器端将IP地址更改为publisher.bind("tcp://*:5557")
和collector.bind("tcp://*:5558")
,我的脚本正在运行:
(cnvss_nm) ubuntu@ip-x-x-x-x:~/cnvss_nm$ python pull_pub-nm.py
Network Manager CNVSS Broker listening
但是从我的client-side code(added recently),任何数据都会被发送。
#include <zmq.hpp>
#include <zmq.h>
#include <iostream>
#include "zhelpers.hpp"
using namespace std;
int main(int argc, char *argv[])
{
zmq::context_t context(1);
/*
std::cout << "Sending message to NM Server…\n" << std::endl; */
zmq::socket_t subscriber(context, ZMQ_SUB);
subscriber.connect("tcp://localhost:5557");
subscriber.setsockopt(ZMQ_SUBSCRIBE, "", 0);
zmq::socket_t sender(context, ZMQ_PUSH);
sender.connect("tcp://localhost:5558");
string firstMessage = "Hola, soy el cliente 1";
while (1)
{
// Wait for next request from client
std::string string = s_recv(subscriber);
std::cout << "Received request: " << string << std::endl;
// Do some 'work'
// sleep(1);
// Send reply back to client
// zmq::message_t message(firstMessage.size() + 1);
// Cualquiera de los dos se puede
// memcpy(message.data(), firstMessage.c_str(), firstMessage.size() + 1);
// s_send(sender, "Hola soy un responder 1");
// sender.send(message);
}
}
我认为我不方便的是我的EC2机器网络配置或设置服务器IP地址的方式。
当我在本地测试客户端和服务器时,它完美地工作。
是否有可能在我的EC2机器上执行某些转发或NAT操作?
我的客户没有到达服务器。
我有安全组规则上面提到的端口5557和5558。
如何解决这个不便?
如何解决这个不便?
1)
如果怀疑EC2地址,首先尝试测试反向的.bind() / .connect()
,以便EC2端本地主机地址分配在游戏中,并且您对已知IP地址的连接证明将不依赖于EC2端设置。
2) 接下来,鉴于没有关于MCVE的客户端部分的详细信息,我可能已经不情愿地得到了场景的想法,所以请耐心等待 - 从那时起只有这些兼容的ZeroMQ可扩展形式通信原型套接字匹配,直到2018 / Q2中的API v4.2.x:
{ PUB: [ SUB,
XSUB,
None
],
PULL: [ PUSH,
None
],
...
}
3)
有一个很好的工程实践,不要让未处理的异常发生,如果Context()
实例可能仍然拥有IP:PORT#(b)锁定资源(有时甚至超出python进程终止(许多事件与我自己的天真)这种方式在我过去的黑暗历史中陷入僵局:o))
基础设施设置中的每一步都应该包含在错误处理语法子句中,最好包括finally:
部分,到目前为止,在异常出现的情况下,有时会以优雅的方式拆除所创建的资源。通过这种方式,您的代码将阻止永久挂起的孤儿,它只能重新启动平台,以便摆脱这些,否则无法挽救人质。
如前所述,最初指出的问题(在.bind() / .connect()
阶段诊断出)与Amazon EC2实例IP地址映射相关,作为任何传输类端点设置所需的术语,localhost:port#
camdebu on Nov 1, 2012 5:07 PM解释了所需的所有步骤: 为您的EC2意图设置弹性IP。然后,您将拥有一个静态IP地址。只要您指向EC2实例,弹性IP就没有成本。
只要您的安全组设置正确,您就可以毫无问题地连接到新的IP地址和端口。 -Cam-
- 检查您的安全组规则。确保允许端口从实例外部进行通信。 (启用所有TCP和检查)。 [添加了Yesu Jeya Bensh.P]
最近发布的客户端代码显示了另一个问题,一个由非合作的zmq::socket_t
sender( context, ZMQ_PUSH )
生成的相互阻塞,它实际上从不发送单个消息。
鉴于客户端如上所述进入while(1)
-loop,相关的对等体将无意中进入python制作的main()
内的不可避免的阻塞状态,因为:
def main():
...
collector = ctx.socket( zmq.PULL )
#ollector.bind( "tcp://*:5558" )
collector.bind( "tcp://54.89.25.43:5558" )
while True:
message = collector.recv() # THIS SLOC WILL BLOCK FOREVER HERE,
... # GIVEN <sender> NEVER SENDS...
所以要特别小心,以使事件的流动足够强大,不要陷入这种或类似的不可救药的相互阻滞。
我有类似的情况,我在EC2上使用ZMQ并获得“无法分配请求的地址”。我也在答案中建议使用弹性IP,但它对我不起作用。事实证明,在EC2上,发送端(ZMQ.PUSH)需要绑定到私有IP而不是公共IP,而接收端需要绑定到公共IP,因此尝试将服务器绑定到弹性IP导致错误。在我将其更改为将服务器ZMQ.PUSH端绑定到专用IP并将客户端ZMQ.PULL绑定到弹性IP(在同一端口上)之后,它工作正常。