ublic void quiescingTransmit(Method m) throws IOException {
synchronized (_channelMutex) {
quiescingTransmit(new AMQCommand(m));
}
}
public void quiescingTransmit(AMQCommand c) throws IOException {
synchronized (_channelMutex) {
if (c.getMethod().hasContent()) {
while (_blockContent) {
try {
_channelMutex.wait();
} catch (InterruptedException e) {}
// This is to catch a situation when the thread wakes up during
// shutdown. Currently, no command that has content is allowed
// to send anything in a closing state.
ensureIsOpen();
}
}
c.transmit(this);
}
}
上面代码只需要看: c.transmit(this);这一句,其余的都是摆设。看到这里,就调用了AMQCommand的transmit方法,这个transmit方法就是讲AMQChannel中封装的内容发给broker,然后等待broker返回,进而通过之前附值的_activeRpc来处理回传的帧。
虽然之前在AMQConnection([[二]RabbitMQ-客户端源码之AMQConnection][RabbitMQ-_AMQConnection])中详细讲述了start()方法,但是这里还是要来拿这个来举例这个AMQChannel中的rpc怎么使用
在AMQConnection中有这么一段代码:
Method method = (challenge == null)
? new AMQP.Connection.StartOk.Builder()
.clientProperties(_clientProperties)
.mechanism(sm.getName())
.response(response)
.build()
: new AMQP.Connection.SecureOk.Builder().response(response).build();
try {
Method serverResponse = _channel0.rpc(method, HANDSHAKE_TIMEOUT/2).getMethod();
if (serverResponse instanceof AMQP.Connection.Tune) {
connTune = (AMQP.Connection.Tune) serverResponse;
} else {
challenge = ((AMQP.Connection.Secure) serverResponse).getChallenge();
response = sm.handleChallenge(challenge, this.username, this.password);
}
客户端将Method封装成Connection.StartOk帧之后等待broker返回Connection.Tune帧。
此时调用了AMQChannel的rpc(Method m, int timeout)方法,其间接调用了AMQChannel的privateRpc(Method, int timeout)方法。代码详情上面已经罗列出来。
注意privateRpc(Method, int timeout)方法的最有一句返回:return k.getReply(timeout);这句代码的意思是SimpleBlockingRpcContinuation对象在等待broker的返回,确切的来说是MainLoop线程处理之后返回,即AMQChannel类中handleCompleteInboundCommand方法的nextOutstandingRpc().handleCommand(command)这行代码。
AQMChannel还有些其他的内容,都是边缘性的东西,这里还剩下个RpcContinuation要着重阐述下的:
public interface RpcContinuation {
void handleCommand(AMQCommand command);
void handleShutdownSignal(ShutdownSignalException signal);
}
public static abstract class BlockingRpcContinuation implements RpcContinuation {
public final BlockingValueOrException _blocker =
new BlockingValueOrException();
public void handleCommand(AMQCommand command) {
_blocker.setValue(transformReply(command));
}
public void handleShutdownSignal(ShutdownSignalException signal) {
_blocker.setException(signal);
}
public T getReply() throws ShutdownSignalException
{
return _blocker.uninterruptibleGetValue();
}
public T getReply(int timeout)
throws ShutdownSignalException, TimeoutException
{
return _blocker.uninterruptibleGetValue(timeout);
}
public abstract T transformReply(AMQCommand command);
}
public static class SimpleBlockingRpcContinuation
extends BlockingRpcContinuation
{
public AMQCommand transformReply(AMQCommand command) {
return command;
}
}
RPCContinuation只是一个接口,而BlockingRpcContinuation这个抽象类缺似乎略有门道。而SimpleBlockingRpcContinuation只是将BlockingRpcContinuation中的handleCommand方法便成为:
_blocker.setValue(command);
BlockingRpcContinuation类主要操纵了BlockingValueOrException _blocker这个成员变量。再接下深究BlockingValueOrException其实是继承了BlockingCell,对其做了一下简单的封装。最后来看下BlockingCell是个什么鬼, 截取部分代码如下:
public class BlockingCell {
private boolean _filled = false;
private T _value;
public synchronized T get() throws InterruptedException {
while (!_filled) {
wait();
}
return _value;
}
其实这个就是capacity为1的BlockingQueue,顾美其名曰BlockingCell,绕了大半圈,原来AMQChannel中的_activeRpc就是个这么玩意儿~
本文详细探讨了RabbitMQ客户端AMQChannel中的RPC机制,特别是AMQCommand的transmit方法如何将内容发送给broker并处理响应。通过分析AMQConnection的start()方法和AMQChannel的rpc()方法,揭示了如何等待broker返回并使用ActiveRpc处理帧。重点介绍了BlockingRpcContinuation和BlockingCell,它们作为内部实现的关键组件,实现了基于BlockingQueue的RPC通信。
370

被折叠的 条评论
为什么被折叠?



