这是由spring amqp框架简化而来的一个自定义框架,去除了很多平时用不到的东西,同时也根据自己的需要,在特定的地方做了一些修改。
核心类是下面的4个:
CacheConnectionFactory 这个工厂,缓存了连接和信道
UdConsumerContainer 消费者池
BlockingQueueConsumer 消费者
RabbitMQHelper 帮助类(提供了各种声明方法)
接下来先说CacheConnectionFactory 类:
主要作用是创建连接,以及信道池。
public Channel createChannel(CacheConnectionFactory.ChannelCachingConnectionProxy proxy)这方法用于创建信道。
创建信道之前,先检查连接是否开启或是否存在,如果没有开启,则开启连接
synchronized(this.connectionMonitor) {
if(!this.connection.isOpen()) {
this.connection.target = null;
try {
this.createConnection();
} catch (Exception var5) {
throw new RuntimeException();
}
}
}
然后使用连接创建信道,这里使用了信号量来限制一个连接可以创建的信道的数量。每次创建一个信道时,checkoutPermits会减1。
再从缓存的信道池中获取一个信道,检查信道是否可用,如果不可用,则表示信道损坏,需要重新创建。
这里将真实的信道,包装在了一个代理类ChannelProxy中。
private Channel doCreateBareChannel(CacheConnectionFactory.ChannelCachingConnectionProxy connection) {
ChannelProxy channelProxy = null;
Semaphore checkoutPermits = null;
if(this.channelCheckoutTimeout > 0L) {
checkoutPermits = (Semaphore)this.checkoutPermits.get(connection);
if(checkoutPermits == null) {
throw new IllegalStateException("没有为连接设置permits的值 " + connection);
}
try {
if(!checkoutPermits.tryAcquire(this.channelCheckoutTimeout, TimeUnit.MILLISECONDS)) {
throw new RuntimeException("没有可用的信道");
}
} catch (InterruptedException var10) {
Thread.currentThread().interrupt();
throw new RuntimeException("获取信道时发生了中断");
}
}
LinkedList<ChannelProxy> channelList = this.channelProxyLinkedList;
if(connection.isOpen()) {
synchronized(channelList) {
for(; !channelList.isEmpty(); channelProxy = null) {
channelProxy = (ChannelProxy)channelList.removeFirst();
if(channelProxy.isOpen()) {
break;
}
try {
Channel target = channelProxy.getTargetChannel();
if(target != null) {
target.close();
}
} catch (TimeoutException var8) {
;
} catch (IOException var9) {
;
}
}
if(channelProxy == null) {
try {
channelProxy = this.createBareChannel(connection, channelList);
} catch (Exception var11) {
if(checkoutPermits != null) {
checkoutPermits.release();
}
throw new RuntimeException(var11);
}
}
}
}
return channelProxy;
}
创建信道时,使用了动态代理,目的是修改信道的关闭方法,在关闭信道时,把信道还回信道池。
private final class CacheChannelInvocationHandler implements InvocationHandler {
private final CacheConnectionFactory.ChannelCachingConnectionProxy connectionProxy;
private final LinkedList<ChannelProxy> channelProxyLinkedList;
private final String channelListIdentity;
private final Object targetMonitor = new Object();
private volatile Channel target;
private volatile boolean txStarted;
public CacheChannelInvocationHandler(CacheConnectionFactory.ChannelCachingConnectionProxy var1, LinkedList<ChannelProxy> connectionProxy, Channel channelProxyLinkedList) {
this.connectionProxy = connectionProxy;
this.channelProxyLinkedList = channelProxyLinkedList;
this.target = channel;
this.channelListIdentity = ObjectUtils.getIdentityHexString(channelProxyLinkedList);
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
String methodName = method.getName();
if(methodName.equals("equals")) {
return Boolean.valueOf(proxy == args[0]);
} else if(methodName.equals("hashCode")) {
return Integer.valueOf(System.identityHashCode(proxy));
} else if(methodName.equals("toString")) {
return "Cache Rabbit Channel: " + this.target + ",conn:" + this.connectionProxy;
} else if(methodName.equals("close")) {
if(CacheConnectionFactory.this.active) {
LinkedList var14 = this.channelProxyLinkedList;
synchronized(this.channelProxyLinkedList) {
if(this.channelProxyLinkedList.size() < CacheConnectionFactory.this.channelCacheSize || this.channelProxyLinkedList.contains(proxy)) {
this.releasePermit(proxy);
this.logicClose((ChannelProxy)proxy);
return null;
}
}
}
this.physicalClose();
this.releasePermit(proxy);
return null;
} else if(methodName.equals("isOpen")) {
return Boolean.valueOf(this.target != null && this.target.isOpen());
} else {
Object result;
try {
if(this.target == null || !this.target.isOpen()) {
this.target = null;
}
Object monitor = this.targetMonitor;
synchronized(monitor) {
if(this.target == null) {
this.target = CacheConnectionFactory.this.createChannel(this.connectionProxy);
}
result = method.invoke(this.target, args);
return result;
}
} catch (InvocationTargetException var13) {
if(this.target == null || !this.target.isOpen()) {
this.target = null;
result = this.targetMonitor;
Object var7 = this.targetMonitor;
synchronized(this.targetMonitor) {
if(this.target == null) {
this.target = CacheConnectionFactory.this.createChannel(this.connectionProxy);
}
}
}
throw var13.getTargetException();
}
}
}
private void physicalClose() {
if(this.target != null) {
try {
this.asyncClose();
} finally {
this.target = null;
}
}
}
private void asyncClose() {
CacheConnectionFactory.this.deferredCloseExecutor.execute(() -> {
try {
Thread.sleep(5000L);
} catch (InterruptedException var14) {
Thread.currentThread().interrupt();
} finally {
try {
this.target.close();
} catch (IOException var12) {
;
} catch (TimeoutException var13) {
;
}
}
});
}
private void logicClose(ChannelProxy proxy) {
if(this.target != null) {
if(this.target != null && !this.target.isOpen()) {
Object var2 = this.targetMonitor;
synchronized(this.targetMonitor) {
if(this.target != null && !this.target.isOpen()) {
if(this.channelProxyLinkedList.contains(proxy)) {
this.channelProxyLinkedList.remove(proxy);
}
this.target = null;
return;
}
}
}
if(!this.channelProxyLinkedList.contains(proxy)) {
this.channelProxyLinkedList.addLast(proxy);
}
}
}
private void releasePermit(Object proxy) {
if(CacheConnectionFactory.this.channelCheckoutTimeout > 0L) {
LinkedList<ChannelProxy> channelProxies = this.channelProxyLinkedList;
LinkedList var3 = this.channelProxyLinkedList;
synchronized(this.channelProxyLinkedList) {
if(channelProxies.contains(proxy)) {
return;
}
}
Semaphore checkoutPermits = (Semaphore)CacheConnectionFactory.this.checkoutPermits.get(this.connectionProxy);
if(checkoutPermits != null) {
checkoutPermits.release();
}
}
}
}
源码:
public class CacheConnectionFactory {
private final ConnectionFactory rabbitConnectionFactory = new ConnectionFactory();
private final Map<CacheConnectionFactory.ChannelCachingConnectionProxy, Semaphore> checkoutPermits;
private final Object connectionMonitor;
private final CacheConnectionFactory.ChannelCachingConnectionProxy connection;
private volatile int channelCacheSize;
private volatile long channelCheckoutTimeout;
private final LinkedList<ChannelProxy> channelProxyLinkedList;
private volatile boolean active = true;
private final ExecutorService deferredCloseExecutor;
public CacheConnectionFactory(@Value("${rabbitmq.ip}") String hostName, @Value("${rabbitmq.port}") int port, @Value("${rabbitmq.username}") String username, @Value("${rabbitmq.password}") String password, @Value("${rabbitmq.channels}") int channelCacheSize, @Value("${rabbitmq.checkTimeOut}") long channelCheckoutTimeout) {
this.rabbitConnectionFactory.setPort(port);
this.rabbitConnectionFactory.setHost(hostName);
this.rabbitConnectionFactory.setUsername(username);
this.rabbitConnectionFactory.setPassword(password);
this.channelCacheSize = channelCacheSize;
this.channelCheckoutTimeout = channelCheckoutTimeout;
this.checkoutPermits = new HashMap();
this.connectionMonitor = new Object();
this.connection = new CacheConnectionFactory.ChannelCachingConnectionProxy((Connection)null);
this.channelProxyLinkedList = new LinkedList();
this.deferredCloseExecutor = Executors.newCachedThreadPool();
}
public final CacheConnectionFactory.ChannelCachingConnectionProxy createConnection() throws IOException, TimeoutException {
if(this.connection.target == null) {
Object var1 = this.connectionMonitor;
synchronized(this.connectionMonitor) {
if(this.connection.target == null) {
this.connection.target = this.rabbitConnectionFactory.newConnection();
if(!this.checkoutPermits.containsKey(this.connection)) {
this.checkoutPermits.put(this.connection, new Semaphore(this.channelCacheSize));
}
this.connection.closeNotified.set(false);
}
}
}
return this.connection;
}
public Channel createChannel(CacheConnectionFactory.ChannelCachingConnectionProxy proxy) {
if(!this.connection.isOpen()) {
Object var2 = this.connectionMonitor;
synchronized(this.connectionMonitor) {
if(!this.connection.isOpen()) {
this.connection.target = null;
try {
this.createConnection();
} catch (Exception var5) {
throw new RuntimeException();
}
}
}
}
return this.doCreateBareChannel(this.connection);
}
private Channel doCreateBareChannel(CacheConnectionFactory.ChannelCachingConnectionProxy connection) {
ChannelProxy channelProxy = null;
Semaphore checkoutPermits = null;
if(this.channelCheckoutTimeout > 0L) {
checkoutPermits = (Semaphore)this.checkoutPermits.get(connection);
if(checkoutPermits == null) {
throw new IllegalStateException("没有为连接设置permits的值 " + connection);
}
try {
if(!checkoutPermits.tryAcquire(this.channelCheckoutTimeout, TimeUnit.MILLISECONDS)) {
throw new RuntimeException("没有可用的信道");
}
} catch (InterruptedException var10) {
Thread.currentThread().interrupt();
throw new RuntimeException("获取信道时发生了中断");
}
}
LinkedList<ChannelProxy> channelList = this.channelProxyLinkedList;
if(connection.isOpen()) {
synchronized(channelList) {
for(; !channelList.isEmpty(); channelProxy = null) {
channelProxy = (ChannelProxy)channelList.removeFirst();
if(channelProxy.isOpen()) {
break;
}
try {
Channel target = channelProxy.getTargetChannel();
if(target != null) {
target.close();
}
} catch (TimeoutException var8) {
;
} catch (IOException var9) {
;
}
}
if(channelProxy == null) {
try {
channelProxy = this.createBareChannel(connection, channelList);
} catch (Exception var11) {
if(checkoutPermits != null) {
checkoutPermits.release();
}
throw new RuntimeException(var11);
}
}
}
}
return channelProxy;
}
private ChannelProxy createBareChannel(CacheConnectionFactory.ChannelCachingConnectionProxy connection, LinkedList<ChannelProxy> channelList) throws IOException {
Channel channel = connection.createChannel();
Class[] interfaces = new Class[]{ChannelProxy.class};
return (ChannelProxy)Proxy.newProxyInstance(ChannelProxy.class.getClassLoader(), interfaces, new CacheConnectionFactory.CacheChannelInvocationHandler(this.connection, channelList, channel));
}
final class ChannelCachingConnectionProxy implements Closeable {
Connection target;
final AtomicBoolean closeNotified = new AtomicBoolean(false);
public ChannelCachingConnectionProxy(Connection connection) {
this.target = connection;
}
public void close() {
try {
this.target.close();
} catch (IOException var2) {
throw new RuntimeException("ChannelCachingConnectionProxy:close失败");
}
}
public Channel createChannel() throws IOException {
return this.target.createChannel();
}
public boolean isOpen() {
return this.target != null && this.target.isOpen();
}
}
private final class CacheChannelInvocationHandler implements InvocationHandler {
private final CacheConnectionFactory.ChannelCachingConnectionProxy connectionProxy;
private final LinkedList<ChannelProxy> channelProxyLinkedList;
private final String channelListIdentity;
private final Object targetMonitor = new Object();
private volatile Channel target;
private volatile boolean txStarted;
public CacheChannelInvocationHandler(CacheConnectionFactory.ChannelCachingConnectionProxy var1, LinkedList<ChannelProxy> connectionProxy, Channel channelProxyLinkedList) {
this.connectionProxy = connectionProxy;
this.channelProxyLinkedList = channelProxyLinkedList;
this.target = channel;
this.channelListIdentity = ObjectUtils.getIdentityHexString(channelProxyLinkedList);
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
String methodName = method.getName();
if(methodName.equals("equals")) {
return Boolean.valueOf(proxy == args[0]);
} else if(methodName.equals("hashCode")) {
return Integer.valueOf(System.identityHashCode(proxy));
} else if(methodName.equals("toString")) {
return "Cache Rabbit Channel: " + this.target + ",conn:" + this.connectionProxy;
} else if(methodName.equals("close")) {
if(CacheConnectionFactory.this.active) {
LinkedList var14 = this.channelProxyLinkedList;
synchronized(this.channelProxyLinkedList) {
if(this.channelProxyLinkedList.size() < CacheConnectionFactory.this.channelCacheSize || this.channelProxyLinkedList.contains(proxy)) {
this.releasePermit(proxy);
this.logicClose((ChannelProxy)proxy);
return null;
}
}
}
this.physicalClose();
this.releasePermit(proxy);
return null;
} else if(methodName.equals("isOpen")) {
return Boolean.valueOf(this.target != null && this.target.isOpen());
} else {
Object result;
try {
if(this.target == null || !this.target.isOpen()) {
this.target = null;
}
Object monitor = this.targetMonitor;
synchronized(monitor) {
if(this.target == null) {
this.target = CacheConnectionFactory.this.createChannel(this.connectionProxy);
}
result = method.invoke(this.target, args);
return result;
}
} catch (InvocationTargetException var13) {
if(this.target == null || !this.target.isOpen()) {
this.target = null;
result = this.targetMonitor;
Object var7 = this.targetMonitor;
synchronized(this.targetMonitor) {
if(this.target == null) {
this.target = CacheConnectionFactory.this.createChannel(this.connectionProxy);
}
}
}
throw var13.getTargetException();
}
}
}
private void physicalClose() {
if(this.target != null) {
try {
this.asyncClose();
} finally {
this.target = null;
}
}
}
private void asyncClose() {
CacheConnectionFactory.this.deferredCloseExecutor.execute(() -> {
try {
Thread.sleep(5000L);
} catch (InterruptedException var14) {
Thread.currentThread().interrupt();
} finally {
try {
this.target.close();
} catch (IOException var12) {
;
} catch (TimeoutException var13) {
;
}
}
});
}
private void logicClose(ChannelProxy proxy) {
if(this.target != null) {
if(this.target != null && !this.target.isOpen()) {
Object var2 = this.targetMonitor;
synchronized(this.targetMonitor) {
if(this.target != null && !this.target.isOpen()) {
if(this.channelProxyLinkedList.contains(proxy)) {
this.channelProxyLinkedList.remove(proxy);
}
this.target = null;
return;
}
}
}
if(!this.channelProxyLinkedList.contains(proxy)) {
this.channelProxyLinkedList.addLast(proxy);
}
}
}
private void releasePermit(Object proxy) {
if(CacheConnectionFactory.this.channelCheckoutTimeout > 0L) {
LinkedList<ChannelProxy> channelProxies = this.channelProxyLinkedList;
LinkedList var3 = this.channelProxyLinkedList;
synchronized(this.channelProxyLinkedList) {
if(channelProxies.contains(proxy)) {
return;
}
}
Semaphore checkoutPermits = (Semaphore)CacheConnectionFactory.this.checkoutPermits.get(this.connectionProxy);
if(checkoutPermits != null) {
checkoutPermits.release();
}
}
}
}
}