Client增加批量请求方法
This commit is contained in:
@@ -6,7 +6,7 @@
|
|||||||
package org.redkale.net.client;
|
package org.redkale.net.client;
|
||||||
|
|
||||||
import java.net.SocketAddress;
|
import java.net.SocketAddress;
|
||||||
import java.util.Queue;
|
import java.util.*;
|
||||||
import java.util.concurrent.*;
|
import java.util.concurrent.*;
|
||||||
import java.util.concurrent.atomic.*;
|
import java.util.concurrent.atomic.*;
|
||||||
import java.util.function.*;
|
import java.util.function.*;
|
||||||
@@ -254,6 +254,50 @@ public abstract class Client<C extends ClientConnection<R, P>, R extends ClientR
|
|||||||
return conn.writeChannel(request, respTransfer);
|
return conn.writeChannel(request, respTransfer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final CompletableFuture<List<P>> sendAsync(R[] requests) {
|
||||||
|
for (R request : requests) {
|
||||||
|
if (request.workThread == null) {
|
||||||
|
request.workThread = WorkThread.currentWorkThread();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return connect().thenCompose(conn -> writeChannel(conn, requests));
|
||||||
|
}
|
||||||
|
|
||||||
|
public final <T> CompletableFuture<List<T>> sendAsync(R[] requests, Function<P, T> respTransfer) {
|
||||||
|
for (R request : requests) {
|
||||||
|
if (request.workThread == null) {
|
||||||
|
request.workThread = WorkThread.currentWorkThread();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return connect().thenCompose(conn -> writeChannel(conn, requests, respTransfer));
|
||||||
|
}
|
||||||
|
|
||||||
|
public final CompletableFuture<List<P>> sendAsync(SocketAddress addr, R[] requests) {
|
||||||
|
for (R request : requests) {
|
||||||
|
if (request.workThread == null) {
|
||||||
|
request.workThread = WorkThread.currentWorkThread();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return connect(addr).thenCompose(conn -> writeChannel(conn, requests));
|
||||||
|
}
|
||||||
|
|
||||||
|
public final <T> CompletableFuture<List<T>> sendAsync(SocketAddress addr, R[] requests, Function<P, T> respTransfer) {
|
||||||
|
for (R request : requests) {
|
||||||
|
if (request.workThread == null) {
|
||||||
|
request.workThread = WorkThread.currentWorkThread();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return connect(addr).thenCompose(conn -> writeChannel(conn, requests, respTransfer));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected CompletableFuture<List<P>> writeChannel(ClientConnection conn, R[] requests) {
|
||||||
|
return conn.writeChannel(requests);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected <T> CompletableFuture<List<T>> writeChannel(ClientConnection conn, R[] requests, Function<P, T> respTransfer) {
|
||||||
|
return conn.writeChannel(requests, respTransfer);
|
||||||
|
}
|
||||||
|
|
||||||
private C createConnection(int index, AsyncConnection channel) {
|
private C createConnection(int index, AsyncConnection channel) {
|
||||||
C conn = createClientConnection(index, channel);
|
C conn = createClientConnection(index, channel);
|
||||||
if (!channel.isReadPending()) {
|
if (!channel.isReadPending()) {
|
||||||
|
|||||||
@@ -9,14 +9,14 @@ import java.io.Serializable;
|
|||||||
import java.net.SocketAddress;
|
import java.net.SocketAddress;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.channels.*;
|
import java.nio.channels.*;
|
||||||
import java.util.Iterator;
|
import java.util.*;
|
||||||
import java.util.concurrent.*;
|
import java.util.concurrent.*;
|
||||||
import java.util.concurrent.atomic.*;
|
import java.util.concurrent.atomic.*;
|
||||||
import java.util.concurrent.locks.ReentrantLock;
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
import java.util.function.*;
|
import java.util.function.*;
|
||||||
import org.redkale.annotation.*;
|
import org.redkale.annotation.*;
|
||||||
import org.redkale.net.*;
|
import org.redkale.net.*;
|
||||||
import org.redkale.util.ByteArray;
|
import org.redkale.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 注意: 要确保AsyncConnection的读写过程都必须在channel.ioThread中运行
|
* 注意: 要确保AsyncConnection的读写过程都必须在channel.ioThread中运行
|
||||||
@@ -112,6 +112,10 @@ public abstract class ClientConnection<R extends ClientRequest, P> implements Co
|
|||||||
return writeChannel(request, null);
|
return writeChannel(request, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected final CompletableFuture<List<P>> writeChannel(R[] requests) {
|
||||||
|
return writeChannel(requests, null);
|
||||||
|
}
|
||||||
|
|
||||||
//respTransfer只会在ClientCodec的读线程里调用
|
//respTransfer只会在ClientCodec的读线程里调用
|
||||||
protected final <T> CompletableFuture<T> writeChannel(R request, Function<P, T> respTransfer) {
|
protected final <T> CompletableFuture<T> writeChannel(R request, Function<P, T> respTransfer) {
|
||||||
request.respTransfer = respTransfer;
|
request.respTransfer = respTransfer;
|
||||||
@@ -135,6 +139,36 @@ public abstract class ClientConnection<R extends ClientRequest, P> implements Co
|
|||||||
return respFuture;
|
return respFuture;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//respTransfer只会在ClientCodec的读线程里调用
|
||||||
|
protected final <T> CompletableFuture<List<T>> writeChannel(R[] requests, Function<P, T> respTransfer) {
|
||||||
|
ClientFuture[] respFutures = new ClientFuture[requests.length];
|
||||||
|
int rts = this.channel.getReadTimeoutSeconds();
|
||||||
|
for (int i = 0; i < respFutures.length; i++) {
|
||||||
|
R request = requests[i];
|
||||||
|
request.respTransfer = respTransfer;
|
||||||
|
ClientFuture respFuture = createClientFuture(requests[i]);
|
||||||
|
respFutures[i] = respFuture;
|
||||||
|
if (rts > 0 && !request.isCloseType()) {
|
||||||
|
respFuture.setTimeout(client.timeoutScheduler.schedule(respFuture, rts, TimeUnit.SECONDS));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
respWaitingCounter.add(respFutures.length);//放在writeChannelInWriteThread计数会延迟,导致不准确
|
||||||
|
|
||||||
|
writeLock.lock();
|
||||||
|
try {
|
||||||
|
for (ClientFuture respFuture : respFutures) {
|
||||||
|
offerRespFuture(respFuture);
|
||||||
|
if (pauseWriting.get()) {
|
||||||
|
pauseRequests.add(respFuture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sendRequestInLocking(respFutures);
|
||||||
|
} finally {
|
||||||
|
writeLock.unlock();
|
||||||
|
}
|
||||||
|
return Utility.allOfFutures(respFutures);
|
||||||
|
}
|
||||||
|
|
||||||
private void sendRequestInLocking(R request, ClientFuture respFuture) {
|
private void sendRequestInLocking(R request, ClientFuture respFuture) {
|
||||||
if (true) { //新方式
|
if (true) { //新方式
|
||||||
ByteArray array = arrayThreadLocal.get();
|
ByteArray array = arrayThreadLocal.get();
|
||||||
@@ -170,6 +204,26 @@ public abstract class ClientConnection<R extends ClientRequest, P> implements Co
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void sendRequestInLocking(ClientFuture[] respFutures) {
|
||||||
|
ByteArray array = arrayThreadLocal.get();
|
||||||
|
array.clear();
|
||||||
|
for (ClientFuture respFuture : respFutures) {
|
||||||
|
if (pauseWriting.get()) {
|
||||||
|
pauseRequests.add(respFuture);
|
||||||
|
} else {
|
||||||
|
ClientRequest request = respFuture.request;
|
||||||
|
request.writeTo(this, array);
|
||||||
|
if (request.isCompleted()) {
|
||||||
|
doneRequestCounter.increment();
|
||||||
|
} else { //还剩半包没发送完
|
||||||
|
pauseWriting.set(true);
|
||||||
|
currHalfWriteFuture = respFuture;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
channel.fastWrite(array.getBytes(), writeHandler);
|
||||||
|
}
|
||||||
|
|
||||||
//发送半包和积压的请求数据包
|
//发送半包和积压的请求数据包
|
||||||
void sendHalfWriteInReadThread(R request, Throwable halfRequestExc) {
|
void sendHalfWriteInReadThread(R request, Throwable halfRequestExc) {
|
||||||
writeLock.lock();
|
writeLock.lock();
|
||||||
@@ -198,7 +252,12 @@ public abstract class ClientConnection<R extends ClientRequest, P> implements Co
|
|||||||
return CompletableFuture.failedFuture(new RuntimeException("ClientVirtualRequest must be virtualType = true"));
|
return CompletableFuture.failedFuture(new RuntimeException("ClientVirtualRequest must be virtualType = true"));
|
||||||
}
|
}
|
||||||
ClientFuture<R, P> respFuture = createClientFuture(request);
|
ClientFuture<R, P> respFuture = createClientFuture(request);
|
||||||
|
writeLock.lock();
|
||||||
|
try {
|
||||||
offerRespFuture(respFuture);
|
offerRespFuture(respFuture);
|
||||||
|
} finally {
|
||||||
|
writeLock.unlock();
|
||||||
|
}
|
||||||
return respFuture;
|
return respFuture;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -241,7 +300,7 @@ public abstract class ClientConnection<R extends ClientRequest, P> implements Co
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//只会在WriteIOThread中调用
|
//只会在WriteIOThread中调用, 必须在writeLock内执行
|
||||||
void offerFirstRespFuture(ClientFuture<R, P> respFuture) {
|
void offerFirstRespFuture(ClientFuture<R, P> respFuture) {
|
||||||
Serializable requestid = respFuture.request.getRequestid();
|
Serializable requestid = respFuture.request.getRequestid();
|
||||||
if (requestid == null) {
|
if (requestid == null) {
|
||||||
@@ -251,7 +310,7 @@ public abstract class ClientConnection<R extends ClientRequest, P> implements Co
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//只会在WriteIOThread中调用
|
//必须在writeLock内执行
|
||||||
void offerRespFuture(ClientFuture<R, P> respFuture) {
|
void offerRespFuture(ClientFuture<R, P> respFuture) {
|
||||||
Serializable requestid = respFuture.request.getRequestid();
|
Serializable requestid = respFuture.request.getRequestid();
|
||||||
if (requestid == null) {
|
if (requestid == null) {
|
||||||
|
|||||||
Reference in New Issue
Block a user