You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@servicecomb.apache.org by li...@apache.org on 2018/09/07 02:45:07 UTC
[incubator-servicecomb-java-chassis] 02/03: [SCB-894][WIP] measure
http server
This is an automated email from the ASF dual-hosted git repository.
liubao pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-servicecomb-java-chassis.git
commit 664f83d1dc9533c08a1a62228c90479872ff441f
Author: wujimin <wu...@huawei.com>
AuthorDate: Fri Sep 7 02:51:12 2018 +0800
[SCB-894][WIP] measure http server
---
.../vertx/metrics/DefaultHttpServerMetrics.java | 140 ++++++++++++++
.../metrics/metric/DefaultEndpointMetric.java | 84 +++++++++
.../metrics/metric/DefaultHttpSocketMetric.java | 70 +++++++
.../metrics/TestDefaultHttpServerMetrics.java | 209 +++++++++++++++++++++
4 files changed, 503 insertions(+)
diff --git a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/metrics/DefaultHttpServerMetrics.java b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/metrics/DefaultHttpServerMetrics.java
new file mode 100644
index 0000000..ddfb958
--- /dev/null
+++ b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/metrics/DefaultHttpServerMetrics.java
@@ -0,0 +1,140 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.servicecomb.foundation.vertx.metrics;
+
+import org.apache.servicecomb.foundation.vertx.metrics.metric.DefaultEndpointMetric;
+import org.apache.servicecomb.foundation.vertx.metrics.metric.DefaultHttpSocketMetric;
+
+import io.vertx.core.http.HttpMethod;
+import io.vertx.core.http.HttpServer;
+import io.vertx.core.http.HttpServerOptions;
+import io.vertx.core.http.HttpServerRequest;
+import io.vertx.core.http.HttpServerResponse;
+import io.vertx.core.http.ServerWebSocket;
+import io.vertx.core.net.SocketAddress;
+import io.vertx.core.spi.metrics.HttpServerMetrics;
+
+/**
+ * important: not singleton, every HttpServer instance relate to a HttpServerMetrics instance
+ */
+public class DefaultHttpServerMetrics implements HttpServerMetrics<Object, Object, DefaultHttpSocketMetric> {
+ private final DefaultEndpointMetric endpointMetric;
+
+ private final HttpServer server;
+
+ private final SocketAddress localAddress;
+
+ private final HttpServerOptions options;
+
+ public DefaultHttpServerMetrics(DefaultEndpointMetric endpointMetric, HttpServer server,
+ SocketAddress localAddress, HttpServerOptions options) {
+ this.endpointMetric = endpointMetric;
+ this.server = server;
+ this.localAddress = localAddress;
+ this.options = options;
+ }
+
+ public DefaultEndpointMetric getEndpointMetric() {
+ return endpointMetric;
+ }
+
+ public HttpServer getServer() {
+ return server;
+ }
+
+ public SocketAddress getLocalAddress() {
+ return localAddress;
+ }
+
+ public HttpServerOptions getOptions() {
+ return options;
+ }
+
+ @Override
+ public Object requestBegin(DefaultHttpSocketMetric socketMetric, HttpServerRequest request) {
+ return null;
+ }
+
+ @Override
+ public void requestReset(Object requestMetric) {
+
+ }
+
+ @Override
+ public Object responsePushed(DefaultHttpSocketMetric socketMetric, HttpMethod method, String uri,
+ HttpServerResponse response) {
+ return null;
+ }
+
+ @Override
+ public void responseEnd(Object requestMetric, HttpServerResponse response) {
+
+ }
+
+ @Override
+ public Object upgrade(Object requestMetric, ServerWebSocket serverWebSocket) {
+ return null;
+ }
+
+ @Override
+ public Object connected(DefaultHttpSocketMetric socketMetric, ServerWebSocket serverWebSocket) {
+ return null;
+ }
+
+ @Override
+ public void disconnected(Object serverWebSocketMetric) {
+
+ }
+
+ @Override
+ public DefaultHttpSocketMetric connected(SocketAddress remoteAddress, String remoteName) {
+ endpointMetric.onConnect();
+ return new DefaultHttpSocketMetric(endpointMetric);
+ }
+
+ @Override
+ public void disconnected(DefaultHttpSocketMetric socketMetric, SocketAddress remoteAddress) {
+ endpointMetric.onDisconnect();
+ socketMetric.setConnected(false);
+ }
+
+ @Override
+ public void bytesRead(DefaultHttpSocketMetric socketMetric, SocketAddress remoteAddress, long numberOfBytes) {
+ endpointMetric.addBytesRead(numberOfBytes);
+ }
+
+ @Override
+ public void bytesWritten(DefaultHttpSocketMetric socketMetric, SocketAddress remoteAddress, long numberOfBytes) {
+ endpointMetric.addBytesWritten(numberOfBytes);
+ }
+
+ @Override
+ public void exceptionOccurred(DefaultHttpSocketMetric socketMetric, SocketAddress remoteAddress, Throwable t) {
+
+ }
+
+ @Override
+ @Deprecated
+ public boolean isEnabled() {
+ return true;
+ }
+
+ @Override
+ public void close() {
+
+ }
+}
diff --git a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/metrics/metric/DefaultEndpointMetric.java b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/metrics/metric/DefaultEndpointMetric.java
new file mode 100644
index 0000000..f25ca64
--- /dev/null
+++ b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/metrics/metric/DefaultEndpointMetric.java
@@ -0,0 +1,84 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.servicecomb.foundation.vertx.metrics.metric;
+
+import java.util.concurrent.atomic.AtomicLong;
+
+import io.vertx.core.net.SocketAddress;
+
+/**
+ * for one listen address, include multiple httpClient or httpServer
+ */
+public class DefaultEndpointMetric {
+ private SocketAddress address;
+
+ // summary of connect times from boot
+ // by this, we can know how many new connections connected recently
+ private AtomicLong connectCount = new AtomicLong();
+
+ // summary of disconnect times from boot
+ // by this, we can know how many connections disconnected recently
+ private AtomicLong disconnectCount = new AtomicLong();
+
+ private AtomicLong bytesRead = new AtomicLong();
+
+ private AtomicLong bytesWritten = new AtomicLong();
+
+ public DefaultEndpointMetric(SocketAddress address) {
+ this.address = address;
+ }
+
+ public SocketAddress getAddress() {
+ return address;
+ }
+
+ public long getConnectCount() {
+ return connectCount.get();
+ }
+
+ public long getDisconnectCount() {
+ return disconnectCount.get();
+ }
+
+ public long getCurrentConnectionCount() {
+ return connectCount.get() - disconnectCount.get();
+ }
+
+ public void onConnect() {
+ connectCount.incrementAndGet();
+ }
+
+ public void onDisconnect() {
+ disconnectCount.incrementAndGet();
+ }
+
+ public long getBytesRead() {
+ return bytesRead.get();
+ }
+
+ public long addBytesRead(long bytes) {
+ return bytesRead.addAndGet(bytes);
+ }
+
+ public long getBytesWritten() {
+ return bytesWritten.get();
+ }
+
+ public long addBytesWritten(long bytes) {
+ return bytesWritten.addAndGet(bytes);
+ }
+}
diff --git a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/metrics/metric/DefaultHttpSocketMetric.java b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/metrics/metric/DefaultHttpSocketMetric.java
new file mode 100644
index 0000000..b486b62
--- /dev/null
+++ b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/metrics/metric/DefaultHttpSocketMetric.java
@@ -0,0 +1,70 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.servicecomb.foundation.vertx.metrics.metric;
+
+public class DefaultHttpSocketMetric {
+ private DefaultEndpointMetric endpointMetric;
+
+ private boolean connected = true;
+
+ private long connectedTime = System.nanoTime();
+
+ private long requestBeginTime;
+
+ private long requestEndTime;
+
+ public DefaultHttpSocketMetric(DefaultEndpointMetric endpointMetric) {
+ this.endpointMetric = endpointMetric;
+ }
+
+ public void setEndpointMetric(DefaultEndpointMetric endpointMetric) {
+ this.endpointMetric = endpointMetric;
+ }
+
+ @SuppressWarnings("unchecked")
+ public <T extends DefaultEndpointMetric> T getEndpointMetric() {
+ return (T) endpointMetric;
+ }
+
+ public boolean isConnected() {
+ return connected;
+ }
+
+ public void setConnected(boolean connected) {
+ this.connected = connected;
+ }
+
+ public long getConnectedTime() {
+ return connectedTime;
+ }
+
+ public long getRequestBeginTime() {
+ return requestBeginTime;
+ }
+
+ public void requestBegin() {
+ this.requestBeginTime = System.nanoTime();
+ }
+
+ public long getRequestEndTime() {
+ return requestEndTime;
+ }
+
+ public void requestEnd() {
+ this.requestEndTime = System.nanoTime();
+ }
+}
diff --git a/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/metrics/TestDefaultHttpServerMetrics.java b/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/metrics/TestDefaultHttpServerMetrics.java
new file mode 100644
index 0000000..b039cdd
--- /dev/null
+++ b/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/metrics/TestDefaultHttpServerMetrics.java
@@ -0,0 +1,209 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.servicecomb.foundation.vertx.metrics;
+
+import java.util.IdentityHashMap;
+import java.util.Map;
+
+import org.apache.servicecomb.foundation.vertx.metrics.metric.DefaultEndpointMetric;
+import org.apache.servicecomb.foundation.vertx.metrics.metric.DefaultHttpSocketMetric;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import io.vertx.core.Vertx;
+import io.vertx.core.VertxOptions;
+import io.vertx.core.http.HttpServer;
+import io.vertx.core.http.HttpServerOptions;
+import io.vertx.core.net.SocketAddress;
+import mockit.Mocked;
+
+public class TestDefaultHttpServerMetrics {
+ @Mocked
+ Vertx vertx;
+
+ VertxOptions vertxOptions = new VertxOptions();
+
+ MetricsOptionsEx metricsOptionsEx = new MetricsOptionsEx();
+
+ DefaultVertxMetrics defaultVertxMetrics;
+
+ @Mocked
+ HttpServer listen1_server1;
+
+ @Mocked
+ HttpServer listen1_server2;
+
+ @Mocked
+ SocketAddress listen1_addr;
+
+ @Mocked
+ HttpServer listen2_server1;
+
+ @Mocked
+ HttpServer listen2_server2;
+
+ @Mocked
+ SocketAddress listen2_addr;
+
+ @Mocked
+ HttpServerOptions options;
+
+ @Mocked
+ SocketAddress anyRemoteAddr;
+
+ DefaultHttpServerMetrics metrics_listen1_server1;
+
+ DefaultHttpServerMetrics metrics_listen1_server2;
+
+ DefaultEndpointMetric endpointMetric1;
+
+ DefaultHttpServerMetrics metrics_listen2_server1;
+
+ DefaultHttpServerMetrics metrics_listen2_server2;
+
+ DefaultEndpointMetric endpointMetric2;
+
+ String remoteName = "remote";
+
+ DefaultHttpSocketMetric socketMetric_listen1_1;
+
+ DefaultHttpSocketMetric socketMetric_listen1_2;
+
+ DefaultHttpSocketMetric socketMetric_listen2_1;
+
+ DefaultHttpSocketMetric socketMetric_listen2_2;
+
+ DefaultHttpSocketMetric socketMetric_listen2_3;
+
+ @Before
+ public void setup() {
+ vertxOptions.setMetricsOptions(metricsOptionsEx);
+ defaultVertxMetrics = new DefaultVertxMetrics(vertx, vertxOptions);
+
+ metrics_listen1_server1 = (DefaultHttpServerMetrics) defaultVertxMetrics
+ .createMetrics(listen1_server1, listen1_addr, options);
+ metrics_listen1_server2 = (DefaultHttpServerMetrics) defaultVertxMetrics
+ .createMetrics(listen1_server2, listen1_addr, options);
+ endpointMetric1 = metrics_listen1_server1.getEndpointMetric();
+
+ metrics_listen2_server1 = (DefaultHttpServerMetrics) defaultVertxMetrics
+ .createMetrics(listen2_server1, listen2_addr, options);
+ metrics_listen2_server2 = (DefaultHttpServerMetrics) defaultVertxMetrics
+ .createMetrics(listen2_server2, listen2_addr, options);
+ endpointMetric2 = metrics_listen2_server1.getEndpointMetric();
+
+ socketMetric_listen1_1 = metrics_listen1_server1.connected(anyRemoteAddr, remoteName);
+ socketMetric_listen1_2 = metrics_listen1_server2.connected(anyRemoteAddr, remoteName);
+ socketMetric_listen2_1 = metrics_listen2_server1.connected(anyRemoteAddr, remoteName);
+ socketMetric_listen2_2 = metrics_listen2_server2.connected(anyRemoteAddr, remoteName);
+ socketMetric_listen2_3 = metrics_listen2_server2.connected(anyRemoteAddr, remoteName);
+ }
+
+ @Test
+ public void createMetrics() {
+ Map<Object, Object> instances = new IdentityHashMap<>();
+ instances.put(metrics_listen1_server1, null);
+ instances.put(metrics_listen1_server2, null);
+ instances.put(metrics_listen2_server1, null);
+ instances.put(metrics_listen2_server2, null);
+ Assert.assertEquals(4, instances.size());
+
+ Assert.assertSame(metrics_listen1_server1.getEndpointMetric(), metrics_listen1_server2.getEndpointMetric());
+ Assert.assertNotSame(metrics_listen1_server1.getEndpointMetric(), metrics_listen2_server1.getEndpointMetric());
+ Assert.assertSame(metrics_listen2_server1.getEndpointMetric(), metrics_listen2_server2.getEndpointMetric());
+ }
+
+ @Test
+ public void connectionCount() {
+ Map<Object, Object> instances = new IdentityHashMap<>();
+ instances.put(socketMetric_listen1_1, null);
+ instances.put(socketMetric_listen1_2, null);
+ instances.put(socketMetric_listen2_1, null);
+ instances.put(socketMetric_listen2_2, null);
+ instances.put(socketMetric_listen2_3, null);
+ Assert.assertEquals(5, instances.size());
+
+ Assert.assertTrue(socketMetric_listen1_1.isConnected());
+ Assert.assertTrue(socketMetric_listen1_2.isConnected());
+ Assert.assertTrue(socketMetric_listen2_1.isConnected());
+ Assert.assertTrue(socketMetric_listen2_2.isConnected());
+ Assert.assertTrue(socketMetric_listen2_3.isConnected());
+
+ Assert.assertEquals(2, endpointMetric1.getCurrentConnectionCount());
+ Assert.assertEquals(3, endpointMetric2.getCurrentConnectionCount());
+
+ // disconnect
+ metrics_listen1_server1.disconnected(socketMetric_listen1_1, anyRemoteAddr);
+ metrics_listen1_server2.disconnected(socketMetric_listen1_2, anyRemoteAddr);
+ metrics_listen2_server1.disconnected(socketMetric_listen2_1, anyRemoteAddr);
+ metrics_listen2_server2.disconnected(socketMetric_listen2_2, anyRemoteAddr);
+ metrics_listen2_server2.disconnected(socketMetric_listen2_3, anyRemoteAddr);
+
+ Assert.assertFalse(socketMetric_listen1_1.isConnected());
+ Assert.assertFalse(socketMetric_listen1_2.isConnected());
+ Assert.assertFalse(socketMetric_listen2_1.isConnected());
+ Assert.assertFalse(socketMetric_listen2_2.isConnected());
+ Assert.assertFalse(socketMetric_listen2_3.isConnected());
+
+ Assert.assertEquals(0, endpointMetric1.getCurrentConnectionCount());
+ Assert.assertEquals(0, endpointMetric2.getCurrentConnectionCount());
+ }
+
+ @Test
+ public void bytesRead() {
+ metrics_listen1_server1.bytesRead(socketMetric_listen1_1, anyRemoteAddr, 1);
+ metrics_listen1_server2.bytesRead(socketMetric_listen1_2, anyRemoteAddr, 2);
+ metrics_listen2_server1.bytesRead(socketMetric_listen2_1, anyRemoteAddr, 3);
+ metrics_listen2_server2.bytesRead(socketMetric_listen2_2, anyRemoteAddr, 4);
+ metrics_listen2_server2.bytesRead(socketMetric_listen2_3, anyRemoteAddr, 5);
+
+ Assert.assertEquals(3, endpointMetric1.getBytesRead());
+ Assert.assertEquals(12, endpointMetric2.getBytesRead());
+ }
+
+ @Test
+ public void bytesWritten() {
+ metrics_listen1_server1.bytesWritten(socketMetric_listen1_1, anyRemoteAddr, 1);
+ metrics_listen1_server2.bytesWritten(socketMetric_listen1_2, anyRemoteAddr, 2);
+ metrics_listen2_server1.bytesWritten(socketMetric_listen2_1, anyRemoteAddr, 3);
+ metrics_listen2_server2.bytesWritten(socketMetric_listen2_2, anyRemoteAddr, 4);
+ metrics_listen2_server2.bytesWritten(socketMetric_listen2_3, anyRemoteAddr, 5);
+
+ Assert.assertEquals(3, endpointMetric1.getBytesWritten());
+ Assert.assertEquals(12, endpointMetric2.getBytesWritten());
+ }
+
+ @SuppressWarnings("deprecation")
+ @Test
+ public void meaningless() {
+ Assert.assertSame(listen1_server1, metrics_listen1_server1.getServer());
+ Assert.assertSame(listen1_addr, metrics_listen1_server1.getLocalAddress());
+ Assert.assertSame(options, metrics_listen1_server1.getOptions());
+ Assert.assertTrue(metrics_listen1_server1.isEnabled());
+
+ metrics_listen1_server1.requestBegin(null, null);
+ metrics_listen1_server1.requestReset(null);
+ metrics_listen1_server1.responsePushed(null, null, null, null);
+ metrics_listen1_server1.responseEnd(null, null);
+ metrics_listen1_server1.upgrade(null, null);
+ metrics_listen1_server1.connected((DefaultHttpSocketMetric) null, null);
+ metrics_listen1_server1.disconnected(null);
+ metrics_listen1_server1.exceptionOccurred(null, null, null);
+ metrics_listen1_server1.close();
+ }
+}