pipelineWrite

This commit is contained in:
redkale
2024-10-18 14:41:48 +08:00
parent 062f9a09db
commit c0960b21f1
4 changed files with 94 additions and 8 deletions

View File

@@ -205,6 +205,16 @@ public abstract class AsyncConnection implements Channel, AutoCloseable {
return ioWriteThread; return ioWriteThread;
} }
public abstract AsyncConnection pipelineHandler(CompletionHandler handler);
/**
* 快速发送
*
* @see org.redkale.net.AsyncNioConnection#pipelineWrite(java.util.function.Consumer)
* @param consumers Consumer
*/
public abstract void pipelineWrite(Consumer<ByteArray> consumer);
public abstract boolean isTCP(); public abstract boolean isTCP();
public abstract boolean shutdownInput(); public abstract boolean shutdownInput();

View File

@@ -138,6 +138,10 @@ public class AsyncIOThread extends WorkThread {
selector.wakeup(); selector.wakeup();
} }
public final void wakeup() {
selector.wakeup();
}
public Supplier<ByteBuffer> getBufferSupplier() { public Supplier<ByteBuffer> getBufferSupplier() {
return bufferSupplier; return bufferSupplier;
} }

View File

@@ -10,9 +10,12 @@ import java.net.SocketAddress;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.channels.*; import java.nio.channels.*;
import java.util.*; import java.util.*;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.function.Consumer; import java.util.function.Consumer;
import javax.net.ssl.SSLContext; import javax.net.ssl.SSLContext;
import org.redkale.util.ByteArray;
import org.redkale.util.ByteBufferWriter; import org.redkale.util.ByteBufferWriter;
import org.redkale.util.RedkaleException;
/** /**
* 详情见: https://redkale.org * 详情见: https://redkale.org
@@ -37,6 +40,13 @@ abstract class AsyncNioConnection extends AsyncConnection {
protected CompletionHandler<Integer, ByteBuffer> readCompletionHandler; protected CompletionHandler<Integer, ByteBuffer> readCompletionHandler;
protected SelectionKey readKey; protected SelectionKey readKey;
// ------------------------------ pipeline写操作 ------------------------------------
protected ByteArray pipelineWriteArray;
protected Queue<Consumer<ByteArray>> pipelineWriteQueue;
protected CompletionHandler pipelineWriteHandler;
// -------------------------------- 写操作 -------------------------------------- // -------------------------------- 写操作 --------------------------------------
protected byte[] writeByteTuple1Array; protected byte[] writeByteTuple1Array;
@@ -84,12 +94,6 @@ abstract class AsyncNioConnection extends AsyncConnection {
return remoteAddress; return remoteAddress;
} }
// @Override
// public <A> AsyncConnection fastHandler(CompletionHandler<Integer, ? super A> handler) {
// Objects.requireNonNull(handler);
// this.writeFastHandler = (CompletionHandler) handler;
// return this;
// }
@Override @Override
protected void startHandshake(final Consumer<Throwable> callback) { protected void startHandshake(final Consumer<Throwable> callback) {
ioReadThread.register(t -> super.startHandshake(callback)); ioReadThread.register(t -> super.startHandshake(callback));
@@ -158,6 +162,66 @@ abstract class AsyncNioConnection extends AsyncConnection {
doRead(this.ioReadThread.inCurrThread()); doRead(this.ioReadThread.inCurrThread());
} }
@Override
public final AsyncConnection pipelineHandler(CompletionHandler handler) {
if (!clientMode) {
throw new RedkaleException("fast-writer only for client connection");
}
this.pipelineWriteHandler = Objects.requireNonNull(handler);
this.pipelineWriteArray = new ByteArray();
this.pipelineWriteQueue = new ConcurrentLinkedQueue<>();
return this;
}
@Override
public final void pipelineWrite(Consumer<ByteArray> consumer) {
if (pipelineWriteHandler == null) {
throw new RedkaleException("fast-writer handler is null");
}
this.pipelineWriteQueue.offer(consumer);
if (writeKey == null) {
this.ioWriteThread.register(this::pipelineWriteRegister);
} else {
this.writeCompletionHandler = this.pipelineWriteHandler;
writeKey.interestOps(writeKey.interestOps() | SelectionKey.OP_WRITE);
this.ioWriteThread.wakeup();
}
}
private void pipelineWriteRegister(Selector selector) {
try {
if (writeKey == null) {
writeKey = keyFor(selector);
}
if (writeKey == null) {
writeKey = implRegister(selector, SelectionKey.OP_WRITE);
writeKey.attach(this);
} else {
writeKey.interestOps(writeKey.interestOps() | SelectionKey.OP_WRITE);
}
// writeCompletionHandler必须赋值不然会跳过doWrite
this.writeCompletionHandler = this.pipelineWriteHandler;
} catch (ClosedChannelException e) {
e.printStackTrace();
this.pipelineWriteQueue.clear();
handleWrite(0, e);
}
}
private void pipelineWritePrepare() {
ByteArray array = this.pipelineWriteArray.clear();
Consumer<ByteArray> func;
while ((func = pipelineWriteQueue.poll()) != null) {
func.accept(array);
}
this.writePending = true;
this.writeAttachment = null;
this.writeByteTuple1Array = array.content();
this.writeByteTuple1Offset = array.offset();
this.writeByteTuple1Length = array.length();
this.writeCompletionHandler = this.pipelineWriteHandler;
}
@Override @Override
public void write( public void write(
byte[] headerContent, byte[] headerContent,
@@ -300,6 +364,10 @@ abstract class AsyncNioConnection extends AsyncConnection {
boolean hasRemain = true; boolean hasRemain = true;
boolean writeCompleted = true; boolean writeCompleted = true;
boolean error = false; boolean error = false;
// pipelineWrite
if (clientMode && pipelineWriteArray != null && writeByteBuffer == null && writeByteBuffers == null) {
pipelineWritePrepare();
}
int batchOffset = writeBuffersOffset; int batchOffset = writeBuffersOffset;
int batchLength = writeBuffersLength; int batchLength = writeBuffersLength;
while (hasRemain) { // 必须要将buffer写完为止 while (hasRemain) { // 必须要将buffer写完为止

View File

@@ -94,7 +94,7 @@ public abstract class ClientConnection<R extends ClientRequest, P extends Client
public ClientConnection(Client<? extends ClientConnection<R, P>, R, P> client, AsyncConnection channel) { public ClientConnection(Client<? extends ClientConnection<R, P>, R, P> client, AsyncConnection channel) {
this.client = client; this.client = client;
this.codec = createCodec(); this.codec = createCodec();
this.channel = channel.beforeCloseListener(this); // .fastHandler(writeHandler); this.channel = channel.beforeCloseListener(this); // .pipelineHandler(writeHandler);
this.writeBuffer = channel.pollWriteBuffer(); this.writeBuffer = channel.pollWriteBuffer();
} }
@@ -150,7 +150,7 @@ public abstract class ClientConnection<R extends ClientRequest, P extends Client
for (ClientFuture respFuture : respFutures) { for (ClientFuture respFuture : respFutures) {
offerRespFuture(respFuture); offerRespFuture(respFuture);
} }
sendRequestToChannel(respFutures); sendRequestInLocking(respFutures);
} }
} finally { } finally {
writeLock.unlock(); writeLock.unlock();
@@ -158,6 +158,10 @@ public abstract class ClientConnection<R extends ClientRequest, P extends Client
return respFutures; return respFutures;
} }
protected void sendRequestInLocking(ClientFuture... respFutures) {
sendRequestToChannel(respFutures);
}
protected final void sendRequestToChannel(ClientFuture... respFutures) { protected final void sendRequestToChannel(ClientFuture... respFutures) {
// 发送请求数据包 // 发送请求数据包
writeArray.clear(); writeArray.clear();