请考虑以下事项:
S1
,S2
和S3
S1P1
,S1P2
,S2P1
,S2P2
,S3P1
,{{ 1}} S3P2
代理在单个进程中运行,并且可由所有服务进程访问逻辑服务,让我们说ZeroMQ
,发布逻辑服务S1
和M1
感兴趣的消息S2
。每个逻辑服务只有一个进程必须收到S3
,因此请说M1
和S2P1
。
我尝试了以下内容,但没有成功:
S3P2
代理XSUB/XPUB
代理,ROUTER/DEALER
连接到ROUTER
套接字并订阅了所有内容(逻辑XPUB
)S1
代理,ROUTER/DEALER
连接到ROUTER
套接字并订阅了所有内容(对于逻辑XPUB
)S2
代理,ROUTER/DEALER
连接到XPUB套接字并订阅了所有内容(对于逻辑ROUTER
)S3
套接字的REP
套接字线程我认为DEALER
代理会给我发布/订阅语义,并且XSUB/XPUB
代理会在ROUTER/DEALER
套接字之间引入REP
发送的消息之间的竞争代理。
如何合并XSUB/XPUB
套接字来完成此操作?
UPDATE1
我知道"没有成功"我没有帮助,我尝试了不同的配置并得到了不同的错误。我尝试的最新配置如下:
ZeroMQ
copyLoop是这样的:
(XSUB proxy=> XPUB) => (SUB copyLoop=> REQ) => (ROUTER proxy=> DEALER) => REP
我得到的例外情况如下:
public void start() {
context = ZMQ.context(1);
subSocket = context.socket(ZMQ.SUB);
subSocket.connect(subSocketUrl);
subSocket.subscribe("".getBytes());
reqSocket = context.socket(ZMQ.REQ);
reqSocket.connect(reqSocketUrl);
while (!Thread.currentThread().isInterrupted()) {
final Message msg = receiveNextMessage();
resendMessage(msg);
}
}
private Message receiveNextMessage() {
final String header = subSocket.recvStr();
final String entity = subSocket.recvStr();
return new Message(header, entity);
}
private void resendMessage(Message msg) {
reqSocket.sendMore(msg.getKey());
reqSocket.send(msg.getData(), 0);
}
我正在运行JeroMQ 0.3.4,Oracle Java 8 JVM和Windows 7.
答案 0 :(得分:3)
您似乎通过ROUTER
连接添加了一些复杂性 - 您应该能够直接与发布商建立联系。
您当前遇到的错误是REQ
套接字具有严格的消息排序模式 - 您不能连续两次send()
,您必须发送/接收/发送/接收/ etc(同样,REP
套接字必须接收/发送/接收/发送/等)。从它的外观来看,你只是在REQ
套接字上进行发送/发送/发送/等,而没有收到响应。如果您不关心同行的回复,则必须接收并弃置回复,或使用DEALER
(或ROUTER
,但DEALER
在您当前的图表中更有意义。
我已经创建了一个如何使用基本流程结构完成此体系结构的图表。
Broker T1 Broker T2 Broker T3 Broker T4
(PUB*)------>(*SUB)[--](DEALER*) -->(*SUB)[--](DEALER*) -->(*SUB)[--](DEALER*)
|_____________________||____| || | ||
|_____________________||_______________________||____| ||
|| || ||
========================|| ==================|| ===========||=
|| || || || || ||
|| || || || || ||
|| || || || || ||
(REP*) (REP*) (REP*) (REP*) (REP*) (REP*)
S1P1 S1P2 S2P1 S2P2 S3P1 S3P2
所以,主要区别在于我放弃了你的(SUB copyLoop=> REQ)
步骤。您选择XPUB/XSUB
vs PUB/SUB
取决于您,但除非您目前想要使用XPUB/XSUB
的额外功能,否则我会更容易开始。
显然,这个图表没有涉及信息如何进入您的经纪人,当前您显示的是XSUB
套接字 - 这超出了您迄今为止提供的信息的范围,可能是您能够收到的信息已成功发送到您的经纪商,所以我不会处理。
我认为专用于每项服务的代理线程是否可以明智地选择是否将消息发送到他们的服务?如果是这样,那么您选择让他们订阅一切应该可以正常工作,否则可能需要更智能的订阅设置。
如果您在服务进程上使用REP
套接字,那么服务进程必须接收该消息并异步处理它,从不将有关该消息的任何详细信息传达给经纪人。然后它必须通过确认(如“RECEIVED”)响应每条消息,以便它遵循REP
套接字的严格接收/发送/接收/发送模式。
如果您想要关于服务如何处理发送回代理的消息的任何其他类型的通信,REP
不再是服务进程的适当套接字类型,DEALER
可能不再是您的经纪人的正确套接字类型。如果您需要某种形式的负载平衡以便发送到下一个打开的服务进程,则需要使用ROUTER/REQ
并让每个服务指示其可用性并让代理保持该消息直到下一个服务进程说通过发回结果可以获得它。如果你想要一些其他类型的消息处理,你必须指出它是什么,这样才能提出合适的架构。
答案 1 :(得分:1)
显然,我混淆了一些元素:
.front_back{
transform: rotateY( 180deg );
backface-visibility: hidden;
background-color:red;
}
)还是服务器端套接字(Socket.connect
)Socket.bind
套接字不应调用Socket.subscribe
)PUSH
)REQ/REP
vs PUSH/PULL
)非常感谢Jason的非常详细的答案(以及令人敬畏的图表!),它指出了我正确的方向。
我最终得到了以下设计:
ROUTER/DEALER
和XSUB/XPUB
bind(localhost:6000)
代理
bind(localhost:6001)
和SUB/PUSH
上运行排队connect(localhost:6001)
代理;代理线程3和4使用具有不同绑定端口号的类似设计bind(localhost:6002)
PUB
套接字连接到代理
connect(localhost:6000)
上的PULL
套接字连接到代理排队代理除了这种特定于服务的排队机制之外,我还能够简单地添加一个类似于服务的扇出机制:
connect(localhost:6002)
和SUB/PUB
connect(localhost:6001)
代理
bind(localhost:6003)
PUB
套接字连接到代理
connect(localhost:6000)
上的SUB
套接字连接到代理扇出代理这是一次有趣的旅程。