pull connection in async way. #223
parent
994bb2da47
commit
3f09bcb4cb
@ -0,0 +1,147 @@
|
||||
/**
|
||||
* Copyright 2014 Nikita Koksharov, Nickolay Borbit
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
package org.redisson.misc;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
import org.redisson.MasterSlaveServersConfig;
|
||||
import org.redisson.client.RedisConnection;
|
||||
import org.redisson.client.RedisConnectionException;
|
||||
import org.redisson.client.RedisException;
|
||||
import org.redisson.connection.LoadBalancer;
|
||||
import org.redisson.connection.SubscribesConnectionEntry;
|
||||
|
||||
import io.netty.channel.EventLoopGroup;
|
||||
import io.netty.util.concurrent.EventExecutor;
|
||||
import io.netty.util.concurrent.Future;
|
||||
import io.netty.util.concurrent.Promise;
|
||||
import io.netty.util.internal.OneTimeTask;
|
||||
|
||||
public class ConnectionPool<T extends RedisConnection> {
|
||||
|
||||
final List<SubscribesConnectionEntry> entries = new CopyOnWriteArrayList<SubscribesConnectionEntry>();
|
||||
|
||||
EventExecutor executor;
|
||||
|
||||
MasterSlaveServersConfig config;
|
||||
|
||||
LoadBalancer loadBalancer;
|
||||
|
||||
public ConnectionPool(MasterSlaveServersConfig config, LoadBalancer loadBalancer, EventLoopGroup eventLoopGroup) {
|
||||
this.config = config;
|
||||
this.loadBalancer = loadBalancer;
|
||||
this.executor = eventLoopGroup.next();
|
||||
}
|
||||
|
||||
public void add(SubscribesConnectionEntry entry) {
|
||||
entries.add(entry);
|
||||
}
|
||||
|
||||
public void remove(SubscribesConnectionEntry entry) {
|
||||
entries.remove(entry);
|
||||
}
|
||||
|
||||
public Future<T> get() {
|
||||
for (int j = entries.size()-1; j >= 0 ; j--) {
|
||||
SubscribesConnectionEntry entry;
|
||||
if (ConnectionPool.this.loadBalancer != null) {
|
||||
entry = ConnectionPool.this.loadBalancer.getEntry(entries);
|
||||
} else {
|
||||
entry = entries.get(0);
|
||||
}
|
||||
if (!entry.isFreezed() && tryAcquireConnection(entry)) {
|
||||
Promise<T> promise = executor.newPromise();
|
||||
connect(entry, promise);
|
||||
return promise;
|
||||
}
|
||||
}
|
||||
|
||||
RedisConnectionException exception = new RedisConnectionException("Connection pool exhausted!");
|
||||
return executor.newFailedFuture(exception);
|
||||
}
|
||||
|
||||
public Future<T> get(SubscribesConnectionEntry entry) {
|
||||
if (!entry.isFreezed() && tryAcquireConnection(entry)) {
|
||||
Promise<T> promise = executor.newPromise();
|
||||
connect(entry, promise);
|
||||
return promise;
|
||||
}
|
||||
|
||||
RedisConnectionException exception = new RedisConnectionException("Can't aquire connection for " + entry.getClient());
|
||||
return executor.newFailedFuture(exception);
|
||||
}
|
||||
|
||||
protected boolean tryAcquireConnection(SubscribesConnectionEntry entry) {
|
||||
return entry.tryAcquireConnection();
|
||||
}
|
||||
|
||||
protected T poll(SubscribesConnectionEntry entry) {
|
||||
return (T) entry.pollConnection();
|
||||
}
|
||||
|
||||
protected T connect(SubscribesConnectionEntry entry) {
|
||||
return (T) entry.connect(config);
|
||||
}
|
||||
|
||||
private Future<T> connect(final SubscribesConnectionEntry entry, final Promise<T> promise) {
|
||||
T conn = poll(entry);
|
||||
if (conn != null) {
|
||||
if (!promise.trySuccess(conn)) {
|
||||
releaseConnection(entry, conn);
|
||||
releaseConnection(entry);
|
||||
}
|
||||
} else {
|
||||
executor.execute(new OneTimeTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
T conn = connect(entry);
|
||||
if (!promise.trySuccess(conn)) {
|
||||
releaseConnection(entry, conn);
|
||||
releaseConnection(entry);
|
||||
}
|
||||
} catch (RedisException e) {
|
||||
releaseConnection(entry);
|
||||
promise.setFailure(e);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
return promise;
|
||||
}
|
||||
|
||||
public void returnConnection(SubscribesConnectionEntry entry, T connection) {
|
||||
if (entry.isFreezed()) {
|
||||
connection.closeAsync();
|
||||
} else {
|
||||
if (connection.getFailAttempts() == config.getRefreshConnectionAfterFails()) {
|
||||
connection.forceReconnect();
|
||||
}
|
||||
releaseConnection(entry, connection);
|
||||
}
|
||||
releaseConnection(entry);
|
||||
}
|
||||
|
||||
protected void releaseConnection(SubscribesConnectionEntry entry) {
|
||||
entry.releaseConnection();
|
||||
}
|
||||
|
||||
protected void releaseConnection(SubscribesConnectionEntry entry, T conn) {
|
||||
entry.releaseConnection(conn);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
/**
|
||||
* Copyright 2014 Nikita Koksharov, Nickolay Borbit
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
package org.redisson.misc;
|
||||
|
||||
import org.redisson.MasterSlaveServersConfig;
|
||||
import org.redisson.client.RedisPubSubConnection;
|
||||
import org.redisson.connection.LoadBalancer;
|
||||
import org.redisson.connection.SubscribesConnectionEntry;
|
||||
|
||||
import io.netty.channel.EventLoopGroup;
|
||||
|
||||
public class PubSubConnectionPoll extends ConnectionPool<RedisPubSubConnection> {
|
||||
|
||||
public PubSubConnectionPoll(MasterSlaveServersConfig config,
|
||||
LoadBalancer loadBalancer, EventLoopGroup eventLoopGroup) {
|
||||
super(config, loadBalancer, eventLoopGroup);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected RedisPubSubConnection poll(SubscribesConnectionEntry entry) {
|
||||
return entry.pollFreeSubscribeConnection();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected RedisPubSubConnection connect(SubscribesConnectionEntry entry) {
|
||||
return entry.connectPubSub(config);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean tryAcquireConnection(SubscribesConnectionEntry entry) {
|
||||
return entry.tryAcquireSubscribeConnection();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void releaseConnection(SubscribesConnectionEntry entry) {
|
||||
entry.releaseSubscribeConnection();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void releaseConnection(SubscribesConnectionEntry entry, RedisPubSubConnection conn) {
|
||||
entry.releaseSubscribeConnection(conn);
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue