Skip to content

Commit 47d4773

Browse files
author
wujimin
committed
[SCB-1023] limit max connection by vertx metrics
1 parent 55cefbb commit 47d4773

File tree

4 files changed

+100
-0
lines changed
  • foundations/foundation-vertx/src
  • transports
    • transport-highway/src/main/java/org/apache/servicecomb/transport/highway
    • transport-rest/transport-rest-vertx/src/main/java/org/apache/servicecomb/transport/rest/vertx

4 files changed

+100
-0
lines changed

foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/server/TcpServer.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,15 @@
2626
import org.apache.servicecomb.foundation.ssl.SSLOptionFactory;
2727
import org.apache.servicecomb.foundation.vertx.AsyncResultCallback;
2828
import org.apache.servicecomb.foundation.vertx.VertxTLSBuilder;
29+
import org.apache.servicecomb.foundation.vertx.metrics.DefaultTcpServerMetrics;
30+
import org.apache.servicecomb.foundation.vertx.metrics.metric.DefaultServerEndpointMetric;
2931
import org.slf4j.Logger;
3032
import org.slf4j.LoggerFactory;
3133

3234
import io.vertx.core.Vertx;
3335
import io.vertx.core.net.NetServer;
3436
import io.vertx.core.net.NetServerOptions;
37+
import io.vertx.core.net.impl.NetSocketImpl;
3538

3639
public class TcpServer {
3740
private static final Logger LOGGER = LoggerFactory.getLogger(TcpServer.class);
@@ -62,6 +65,16 @@ public void init(Vertx vertx, String sslKey, AsyncResultCallback<InetSocketAddre
6265
}
6366

6467
netServer.connectHandler(netSocket -> {
68+
DefaultTcpServerMetrics serverMetrics = (DefaultTcpServerMetrics) ((NetSocketImpl) netSocket).metrics();
69+
DefaultServerEndpointMetric endpointMetric = serverMetrics.getEndpointMetric();
70+
long connectedCount = endpointMetric.getCurrentConnectionCount();
71+
int connectionLimit = getConnectionLimit();
72+
if (connectedCount > connectionLimit) {
73+
netSocket.close();
74+
endpointMetric.onRejectByConnectionLimit();
75+
return;
76+
}
77+
6578
TcpServerConnection connection = createTcpServerConnection();
6679
connection.init(netSocket);
6780
});
@@ -81,6 +94,10 @@ public void init(Vertx vertx, String sslKey, AsyncResultCallback<InetSocketAddre
8194
});
8295
}
8396

97+
protected int getConnectionLimit() {
98+
return Integer.MAX_VALUE;
99+
}
100+
84101
protected TcpServerConnection createTcpServerConnection() {
85102
return new TcpServerConnection();
86103
}

foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/server/TestTcpServer.java

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,20 @@
2121

2222
import org.apache.servicecomb.foundation.common.net.URIEndpointObject;
2323
import org.apache.servicecomb.foundation.vertx.AsyncResultCallback;
24+
import org.apache.servicecomb.foundation.vertx.metrics.DefaultTcpServerMetrics;
25+
import org.apache.servicecomb.foundation.vertx.metrics.metric.DefaultServerEndpointMetric;
26+
import org.junit.Assert;
2427
import org.junit.Test;
2528

2629
import io.vertx.core.Handler;
2730
import io.vertx.core.Vertx;
2831
import io.vertx.core.net.NetServer;
2932
import io.vertx.core.net.NetServerOptions;
3033
import io.vertx.core.net.NetSocket;
34+
import io.vertx.core.net.impl.NetSocketImpl;
3135
import mockit.Expectations;
36+
import mockit.Mock;
37+
import mockit.MockUp;
3238
import mockit.Mocked;
3339

3440
public class TestTcpServer {
@@ -83,4 +89,59 @@ public void testTcpServerSSL(@Mocked Vertx vertx, @Mocked AsyncResultCallback<In
8389
// assert done in Expectations
8490
server.init(vertx, "", callback);
8591
}
92+
93+
Handler<NetSocket> connectHandler;
94+
95+
boolean netSocketClosed;
96+
97+
@SuppressWarnings({"rawtypes", "unchecked"})
98+
@Test
99+
public void testConnectionLimit(@Mocked Vertx vertx, @Mocked AsyncResultCallback<InetSocketAddress> callback,
100+
@Mocked NetServer netServer, @Mocked NetSocketImpl netSocket) {
101+
DefaultServerEndpointMetric endpointMetric = new DefaultServerEndpointMetric(null);
102+
DefaultTcpServerMetrics tcpServerMetrics = new DefaultTcpServerMetrics(endpointMetric);
103+
104+
new MockUp<NetServer>(netServer) {
105+
@Mock
106+
NetServer connectHandler(Handler<NetSocket> handler) {
107+
connectHandler = handler;
108+
return netServer;
109+
}
110+
};
111+
new MockUp<NetSocketImpl>(netSocket) {
112+
@Mock
113+
void close() {
114+
netSocketClosed = true;
115+
}
116+
};
117+
new Expectations() {
118+
{
119+
vertx.createNetServer((NetServerOptions) any);
120+
result = netServer;
121+
netServer.listen(anyInt, anyString, (Handler) any);
122+
netSocket.metrics();
123+
result = tcpServerMetrics;
124+
}
125+
};
126+
URIEndpointObject endpointObject = new URIEndpointObject("highway://127.0.0.1:6663?sslEnabled=true");
127+
TcpServer server = new TcpServerForTest(endpointObject) {
128+
@Override
129+
protected int getConnectionLimit() {
130+
return 2;
131+
}
132+
};
133+
// assert done in Expectations
134+
server.init(vertx, "", callback);
135+
136+
// no problem
137+
endpointMetric.onConnect();
138+
endpointMetric.onConnect();
139+
connectHandler.handle(netSocket);
140+
141+
// reject
142+
endpointMetric.onConnect();
143+
connectHandler.handle(netSocket);
144+
Assert.assertTrue(netSocketClosed);
145+
Assert.assertEquals(1, endpointMetric.getRejectByConnectionLimitCount());
146+
}
86147
}

transports/transport-highway/src/main/java/org/apache/servicecomb/transport/highway/HighwayServer.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
import org.apache.servicecomb.foundation.vertx.server.TcpServer;
2323
import org.apache.servicecomb.foundation.vertx.server.TcpServerConnection;
2424

25+
import com.netflix.config.DynamicPropertyFactory;
26+
2527
public class HighwayServer extends TcpServer {
2628
private Endpoint endpoint;
2729

@@ -34,4 +36,10 @@ public HighwayServer(Endpoint endpoint) {
3436
protected TcpServerConnection createTcpServerConnection() {
3537
return new HighwayServerConnection(endpoint);
3638
}
39+
40+
@Override
41+
protected int getConnectionLimit() {
42+
return DynamicPropertyFactory.getInstance()
43+
.getIntProperty("servicecomb.highway.server.connection-limit", Integer.MAX_VALUE).get();
44+
}
3745
}

transports/transport-rest/transport-rest-vertx/src/main/java/org/apache/servicecomb/transport/rest/vertx/RestServerVerticle.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@
3232
import org.apache.servicecomb.foundation.ssl.SSLOption;
3333
import org.apache.servicecomb.foundation.ssl.SSLOptionFactory;
3434
import org.apache.servicecomb.foundation.vertx.VertxTLSBuilder;
35+
import org.apache.servicecomb.foundation.vertx.metrics.DefaultHttpServerMetrics;
36+
import org.apache.servicecomb.foundation.vertx.metrics.metric.DefaultServerEndpointMetric;
3537
import org.apache.servicecomb.swagger.invocation.exception.CommonExceptionData;
3638
import org.apache.servicecomb.swagger.invocation.exception.InvocationException;
3739
import org.apache.servicecomb.transport.rest.vertx.accesslog.AccessLogConfiguration;
@@ -52,6 +54,7 @@
5254
import io.vertx.core.http.HttpServer;
5355
import io.vertx.core.http.HttpServerOptions;
5456
import io.vertx.core.http.HttpServerResponse;
57+
import io.vertx.core.net.impl.ConnectionBase;
5558
import io.vertx.ext.web.Router;
5659
import io.vertx.ext.web.RoutingContext;
5760
import io.vertx.ext.web.handler.CorsHandler;
@@ -89,6 +92,17 @@ public void start(Future<Void> startFuture) throws Exception {
8992
initDispatcher(mainRouter);
9093
HttpServer httpServer = createHttpServer();
9194
httpServer.requestHandler(mainRouter::accept);
95+
httpServer.connectionHandler(connection -> {
96+
DefaultHttpServerMetrics serverMetrics = (DefaultHttpServerMetrics) ((ConnectionBase) connection).metrics();
97+
DefaultServerEndpointMetric endpointMetric = serverMetrics.getEndpointMetric();
98+
long connectedCount = endpointMetric.getCurrentConnectionCount();
99+
int connectionLimit = DynamicPropertyFactory.getInstance()
100+
.getIntProperty("servicecomb.rest.server.connection-limit", Integer.MAX_VALUE).get();
101+
if (connectedCount > connectionLimit) {
102+
connection.close();
103+
endpointMetric.onRejectByConnectionLimit();
104+
}
105+
});
92106
httpServer.exceptionHandler(e -> {
93107
LOGGER.error("Unexpected error in server.{}", ExceptionUtils.getExceptionMessageWithoutTrace(e));
94108
});

0 commit comments

Comments
 (0)