/*
* (C) Copyright 2015-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Contributors:
* ohun@live.cn (夜色)
*/
package com.mpush.netty.http;
import com.google.common.collect.ArrayListMultimap;
import com.mpush.tools.config.CC;
import io.netty.channel.Channel;
import io.netty.util.AttributeKey;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Iterator;
import java.util.List;
/**
* Created by yxx on 2016/5/28.
*
* @author ohun@live.cn (夜色)
*/
/*package*/ class HttpConnectionPool {
private static final int maxConnPerHost = CC.mp.http.max_conn_per_host;
private static final Logger LOGGER = LoggerFactory.getLogger(HttpConnectionPool.class);
private final AttributeKey<String> hostKey = AttributeKey.newInstance("host");
private final ArrayListMultimap<String, Channel> channelPool = ArrayListMultimap.create();
public synchronized Channel tryAcquire(String host) {
List<Channel> channels = channelPool.get(host);
if (channels == null || channels.isEmpty()) return null;
Iterator<Channel> it = channels.iterator();
while (it.hasNext()) {
Channel channel = it.next();
it.remove();
if (channel.isActive()) {
LOGGER.debug("tryAcquire channel success, host={}", host);
channel.attr(hostKey).set(host);
return channel;
} else {//链接由于意外情况不可用了, 比如: keepAlive_timeout
LOGGER.warn("tryAcquire channel false channel is inactive, host={}", host);
}
}
return null;
}
public synchronized void tryRelease(Channel channel) {
String host = channel.attr(hostKey).getAndSet(null);
List<Channel> channels = channelPool.get(host);
if (channels == null || channels.size() < maxConnPerHost) {
LOGGER.debug("tryRelease channel success, host={}", host);
channelPool.put(host, channel);
} else {
LOGGER.debug("tryRelease channel pool size over limit={}, host={}, channel closed.", maxConnPerHost, host);
channel.close();
}
}
public void attachHost(String host, Channel channel) {
channel.attr(hostKey).set(host);
}
public void close() {
channelPool.values().forEach(Channel::close);
channelPool.clear();
}
}