优化client
This commit is contained in:
@@ -102,11 +102,11 @@ public abstract class ClientCodec<R extends ClientRequest, P> implements Complet
|
|||||||
try {
|
try {
|
||||||
if (request != null && !request.isCompleted()) {
|
if (request != null && !request.isCompleted()) {
|
||||||
if (exc == null) {
|
if (exc == null) {
|
||||||
connection.sendHalfWrite(exc);
|
connection.sendHalfWrite(request, exc);
|
||||||
//request没有发送完,respFuture需要再次接收
|
//request没有发送完,respFuture需要再次接收
|
||||||
return;
|
return;
|
||||||
} else { //异常了需要清掉半包
|
} else { //异常了需要清掉半包
|
||||||
connection.sendHalfWrite(exc);
|
connection.sendHalfWrite(request, exc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (request != null) {
|
if (request != null) {
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ import java.nio.channels.ClosedChannelException;
|
|||||||
import java.util.*;
|
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.*;
|
|
||||||
import java.util.function.*;
|
import java.util.function.*;
|
||||||
import org.redkale.net.*;
|
import org.redkale.net.*;
|
||||||
|
|
||||||
@@ -34,15 +33,9 @@ public abstract class ClientConnection<R extends ClientRequest, P> implements Co
|
|||||||
|
|
||||||
protected final LongAdder respWaitingCounter;
|
protected final LongAdder respWaitingCounter;
|
||||||
|
|
||||||
protected final AtomicBoolean pauseWriting = new AtomicBoolean();
|
final AtomicBoolean pauseWriting = new AtomicBoolean();
|
||||||
|
|
||||||
protected final AtomicBoolean pauseResuming = new AtomicBoolean();
|
final ConcurrentLinkedQueue<ClientFuture> pauseRequests = new ConcurrentLinkedQueue<>();
|
||||||
|
|
||||||
protected final List<ClientFuture> pauseRequests = new CopyOnWriteArrayList<>();
|
|
||||||
|
|
||||||
private final ReentrantLock pauseLock = new ReentrantLock();
|
|
||||||
|
|
||||||
private final Condition pauseCondition = pauseLock.newCondition();
|
|
||||||
|
|
||||||
protected final AsyncConnection channel;
|
protected final AsyncConnection channel;
|
||||||
|
|
||||||
@@ -140,8 +133,8 @@ public abstract class ClientConnection<R extends ClientRequest, P> implements Co
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void sendHalfWrite(Throwable halfRequestExc) {
|
void sendHalfWrite(R request, Throwable halfRequestExc) {
|
||||||
writeThread.sendHalfWrite(this, halfRequestExc);
|
writeThread.sendHalfWrite(this, request, halfRequestExc);
|
||||||
}
|
}
|
||||||
|
|
||||||
//只会在WriteIOThread中调用
|
//只会在WriteIOThread中调用
|
||||||
@@ -186,25 +179,6 @@ public abstract class ClientConnection<R extends ClientRequest, P> implements Co
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void signalPauseRequest() {
|
|
||||||
pauseLock.lock();
|
|
||||||
try {
|
|
||||||
pauseCondition.signalAll();
|
|
||||||
} finally {
|
|
||||||
pauseLock.unlock();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void awaitPauseRequest() {
|
|
||||||
pauseLock.lock();
|
|
||||||
try {
|
|
||||||
pauseCondition.await(3_000, TimeUnit.SECONDS);
|
|
||||||
} catch (Exception e) {
|
|
||||||
} finally {
|
|
||||||
pauseLock.unlock();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isAuthenticated() {
|
public boolean isAuthenticated() {
|
||||||
return authenticated;
|
return authenticated;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,6 +26,8 @@ public class ClientFuture<R extends ClientRequest, T> extends CompletableFuture<
|
|||||||
|
|
||||||
private ScheduledFuture timeout;
|
private ScheduledFuture timeout;
|
||||||
|
|
||||||
|
Boolean resumeHalfRequestFlag;
|
||||||
|
|
||||||
ClientFuture(ClientConnection conn, R request) {
|
ClientFuture(ClientConnection conn, R request) {
|
||||||
super();
|
super();
|
||||||
Objects.requireNonNull(conn);
|
Objects.requireNonNull(conn);
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import java.nio.ByteBuffer;
|
|||||||
import java.nio.channels.CompletionHandler;
|
import java.nio.channels.CompletionHandler;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.*;
|
import java.util.concurrent.*;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
|
||||||
import org.redkale.net.AsyncIOThread;
|
import org.redkale.net.AsyncIOThread;
|
||||||
import org.redkale.util.*;
|
import org.redkale.util.*;
|
||||||
|
|
||||||
@@ -35,25 +34,13 @@ public class ClientWriteIOThread extends AsyncIOThread {
|
|||||||
requestQueue.offer(respFuture);
|
requestQueue.offer(respFuture);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendHalfWrite(ClientConnection conn, Throwable halfRequestExc) {
|
public void sendHalfWrite(ClientConnection conn, ClientRequest request, Throwable halfRequestExc) {
|
||||||
if (conn.pauseWriting.get()) {
|
ClientFuture respFuture = conn.createClientFuture(request);
|
||||||
conn.pauseResuming.set(true);
|
respFuture.resumeHalfRequestFlag = true;
|
||||||
try {
|
if (halfRequestExc != null) { //halfRequestExc不为null时需要把当前halfRequest移除
|
||||||
AtomicBoolean skipFirst = new AtomicBoolean(halfRequestExc != null);
|
conn.pauseRequests.poll();
|
||||||
conn.pauseRequests.removeIf(e -> {
|
|
||||||
if (e != null) {
|
|
||||||
if (!skipFirst.compareAndSet(true, false)) {
|
|
||||||
requestQueue.offer((ClientFuture) e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
} finally {
|
|
||||||
conn.pauseResuming.set(false);
|
|
||||||
conn.pauseWriting.set(false);
|
|
||||||
conn.signalPauseRequest();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
requestQueue.offer(respFuture);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -71,24 +58,38 @@ public class ClientWriteIOThread extends AsyncIOThread {
|
|||||||
try {
|
try {
|
||||||
while ((entry = requestQueue.take()) != null) {
|
while ((entry = requestQueue.take()) != null) {
|
||||||
map.clear();
|
map.clear();
|
||||||
if (!entry.isDone()) {
|
if (entry.resumeHalfRequestFlag != null) { //将暂停的pauseRequests写入list
|
||||||
|
List<ClientFuture> cl = map.computeIfAbsent(entry.conn, c -> listPool.get());
|
||||||
|
for (ClientFuture f : (List<ClientFuture>) entry.conn.pauseRequests) {
|
||||||
|
if (!f.isDone()) {
|
||||||
|
entry.conn.offerRespFuture(f);
|
||||||
|
cl.add(f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
entry.conn.pauseRequests.clear();
|
||||||
|
entry.conn.pauseWriting.set(false);
|
||||||
|
} else if (!entry.isDone()) {
|
||||||
entry.conn.offerRespFuture(entry);
|
entry.conn.offerRespFuture(entry);
|
||||||
if (entry.conn.pauseWriting.get()) {
|
if (entry.conn.pauseWriting.get()) {
|
||||||
if (entry.conn.pauseResuming.get()) {
|
|
||||||
entry.conn.awaitPauseRequest();
|
|
||||||
}
|
|
||||||
entry.conn.pauseRequests.add(entry);
|
entry.conn.pauseRequests.add(entry);
|
||||||
} else {
|
} else {
|
||||||
map.computeIfAbsent(entry.conn, c -> listPool.get()).add(entry);
|
map.computeIfAbsent(entry.conn, c -> listPool.get()).add(entry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
while ((entry = requestQueue.poll()) != null) {
|
while ((entry = requestQueue.poll()) != null) {
|
||||||
if (!entry.isDone()) {
|
if (entry.resumeHalfRequestFlag != null) { //将暂停的pauseRequests写入list
|
||||||
|
List<ClientFuture> cl = map.computeIfAbsent(entry.conn, c -> listPool.get());
|
||||||
|
for (ClientFuture f : (List<ClientFuture>) entry.conn.pauseRequests) {
|
||||||
|
if (!f.isDone()) {
|
||||||
|
entry.conn.offerRespFuture(f);
|
||||||
|
cl.add(f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
entry.conn.pauseRequests.clear();
|
||||||
|
entry.conn.pauseWriting.set(false);
|
||||||
|
} else if (!entry.isDone()) {
|
||||||
entry.conn.offerRespFuture(entry);
|
entry.conn.offerRespFuture(entry);
|
||||||
if (entry.conn.pauseWriting.get()) {
|
if (entry.conn.pauseWriting.get()) {
|
||||||
if (entry.conn.pauseResuming.get()) {
|
|
||||||
entry.conn.awaitPauseRequest();
|
|
||||||
}
|
|
||||||
entry.conn.pauseRequests.add(entry);
|
entry.conn.pauseRequests.add(entry);
|
||||||
} else {
|
} else {
|
||||||
map.computeIfAbsent(entry.conn, c -> listPool.get()).add(entry);
|
map.computeIfAbsent(entry.conn, c -> listPool.get()).add(entry);
|
||||||
|
|||||||
@@ -6,21 +6,13 @@
|
|||||||
package org.redkale.test.convert;
|
package org.redkale.test.convert;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
import org.junit.jupiter.api.Assertions;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
import org.redkale.annotation.ConstructorParameters;
|
|
||||||
import org.redkale.convert.bson.BsonByteBufferWriter;
|
|
||||||
import org.redkale.convert.bson.BsonFactory;
|
|
||||||
import org.redkale.persistence.Id;
|
|
||||||
import org.redkale.persistence.Transient;
|
|
||||||
import org.redkale.util.Utility;
|
|
||||||
import org.redkale.convert.bson.BsonConvert;
|
|
||||||
|
|
||||||
import java.nio.*;
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import org.junit.jupiter.api.*;
|
||||||
import org.redkale.convert.json.*;
|
import org.redkale.annotation.ConstructorParameters;
|
||||||
|
import org.redkale.convert.bson.*;
|
||||||
|
import org.redkale.convert.json.JsonConvert;
|
||||||
|
import org.redkale.persistence.*;
|
||||||
import org.redkale.util.*;
|
import org.redkale.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -46,7 +38,7 @@ public class BsonMainTest {
|
|||||||
SimpleChildEntity entry = SimpleChildEntity.create();
|
SimpleChildEntity entry = SimpleChildEntity.create();
|
||||||
byte[] bytes = convert.convertTo(SimpleEntity.class, entry);
|
byte[] bytes = convert.convertTo(SimpleEntity.class, entry);
|
||||||
System.out.println("长度: " + bytes.length);
|
System.out.println("长度: " + bytes.length);
|
||||||
Assertions.assertEquals(260, bytes.length);
|
Assertions.assertEquals(271, bytes.length);
|
||||||
BsonByteBufferWriter writer = convert.pollBsonWriter(() -> ByteBuffer.allocate(1));
|
BsonByteBufferWriter writer = convert.pollBsonWriter(() -> ByteBuffer.allocate(1));
|
||||||
convert.convertTo(writer, SimpleEntity.class, entry);
|
convert.convertTo(writer, SimpleEntity.class, entry);
|
||||||
ByteBuffer[] buffers = writer.toBuffers();
|
ByteBuffer[] buffers = writer.toBuffers();
|
||||||
@@ -60,7 +52,7 @@ public class BsonMainTest {
|
|||||||
b.flip();
|
b.flip();
|
||||||
}
|
}
|
||||||
System.out.println("长度: " + len);
|
System.out.println("长度: " + len);
|
||||||
Assertions.assertEquals(260, len);
|
Assertions.assertEquals(271, len);
|
||||||
SimpleChildEntity entry2 = convert.convertFrom(SimpleChildEntity.class, buffers);
|
SimpleChildEntity entry2 = convert.convertFrom(SimpleChildEntity.class, buffers);
|
||||||
System.out.println(entry);
|
System.out.println(entry);
|
||||||
Assertions.assertEquals(entry.toString(), entry2.toString());
|
Assertions.assertEquals(entry.toString(), entry2.toString());
|
||||||
@@ -83,7 +75,7 @@ public class BsonMainTest {
|
|||||||
convert.convertTo(writer, bean);
|
convert.convertTo(writer, bean);
|
||||||
bytes2 = writer.toArray();
|
bytes2 = writer.toArray();
|
||||||
System.out.println(convert.convertFrom(ComplextEntity.class, bytes2).toString());
|
System.out.println(convert.convertFrom(ComplextEntity.class, bytes2).toString());
|
||||||
Assertions.assertEquals("{\"flag\":true,\"userid\":0}", convert.convertFrom(ComplextEntity.class, bytes2).toString());
|
Assertions.assertEquals("{\"chname\":\"\",\"flag\":true,\"userid\":0}", convert.convertFrom(ComplextEntity.class, bytes2).toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
Reference in New Issue
Block a user