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/11/24 02:08:57 UTC
[servicecomb-java-chassis] 01/10: [SCB-1034] provide fast
SimpleTimer to replace slow ServoTimer
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/servicecomb-java-chassis.git
commit e6def8244c6990aaf396212adfbdf75eda53d7c0
Author: wujimin <wu...@huawei.com>
AuthorDate: Thu Nov 22 08:57:49 2018 +0800
[SCB-1034] provide fast SimpleTimer to replace slow ServoTimer
---
.../com/netflix/spectator/api/SpectatorUtils.java | 22 +++-
.../AbstractPeriodMeter.java} | 30 ++++--
.../foundation/metrics/meter/PeriodMeter.java} | 15 ++-
.../foundation/metrics/meter/SimpleTimer.java | 93 +++++++++++++++++
.../metrics/registry/GlobalRegistry.java | 114 +++++++++++++++++++++
.../foundation/metrics/meter/TestSimpleTimer.java} | 31 ++++--
.../metrics/metric/DefaultEndpointMetric.java | 32 +++---
java-chassis-dependencies/pom.xml | 2 +-
java-chassis-distribution/src/release/LICENSE | 4 +-
9 files changed, 295 insertions(+), 48 deletions(-)
diff --git a/foundations/foundation-test-scaffolding/src/main/java/com/netflix/spectator/api/SpectatorUtils.java b/foundations/foundation-metrics/src/main/java/com/netflix/spectator/api/SpectatorUtils.java
similarity index 55%
copy from foundations/foundation-test-scaffolding/src/main/java/com/netflix/spectator/api/SpectatorUtils.java
copy to foundations/foundation-metrics/src/main/java/com/netflix/spectator/api/SpectatorUtils.java
index 7a2f785..cccc710 100644
--- a/foundations/foundation-test-scaffolding/src/main/java/com/netflix/spectator/api/SpectatorUtils.java
+++ b/foundations/foundation-metrics/src/main/java/com/netflix/spectator/api/SpectatorUtils.java
@@ -16,8 +16,24 @@
*/
package com.netflix.spectator.api;
-public class SpectatorUtils {
- public static CompositeRegistry createCompositeRegistry(Clock clock) {
- return new CompositeRegistry(clock);
+public final class SpectatorUtils {
+ private SpectatorUtils() {
+ }
+
+ public static Id createDefaultId(String name) {
+ return new DefaultId(name);
+ }
+
+ public static void removeExpiredMeters(Registry registry) {
+ if (registry instanceof AbstractRegistry) {
+ ((AbstractRegistry) registry).removeExpiredMeters();
+ }
+ }
+
+ public static void registerMeter(Registry registry, Meter meter) {
+ if (!(registry instanceof AbstractRegistry)) {
+ throw new IllegalStateException("registry must be a AbstractRegistry, class=" + registry.getClass().getName());
+ }
+ ((AbstractRegistry) registry).getOrCreate(meter.id(), Meter.class, null, _id -> meter);
}
}
diff --git a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/PollEvent.java b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/meter/AbstractPeriodMeter.java
similarity index 60%
copy from foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/PollEvent.java
copy to foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/meter/AbstractPeriodMeter.java
index 80a2055..d9e2f46 100644
--- a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/PollEvent.java
+++ b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/meter/AbstractPeriodMeter.java
@@ -14,19 +14,29 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.servicecomb.foundation.metrics;
+package org.apache.servicecomb.foundation.metrics.meter;
-/**
- * give not standard meters to calc measurement , eg : cpu usage, net throughput, and so on
- */
-public class PollEvent {
- private final long msPollInterval;
+import java.util.Collections;
+import java.util.List;
+
+import com.netflix.spectator.api.Id;
+import com.netflix.spectator.api.Measurement;
+
+public abstract class AbstractPeriodMeter implements PeriodMeter {
+ protected Id id;
+
+ protected List<Measurement> allMeasurements = Collections.emptyList();
+
+ public Id id() {
+ return id;
+ }
- public PollEvent(long msPollInterval) {
- this.msPollInterval = msPollInterval;
+ @Override
+ public Iterable<Measurement> measure() {
+ return allMeasurements;
}
- public long getMsPollInterval() {
- return msPollInterval;
+ public boolean hasExpired() {
+ return false;
}
}
diff --git a/foundations/foundation-test-scaffolding/src/main/java/com/netflix/spectator/api/SpectatorUtils.java b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/meter/PeriodMeter.java
similarity index 68%
rename from foundations/foundation-test-scaffolding/src/main/java/com/netflix/spectator/api/SpectatorUtils.java
rename to foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/meter/PeriodMeter.java
index 7a2f785..f91d781 100644
--- a/foundations/foundation-test-scaffolding/src/main/java/com/netflix/spectator/api/SpectatorUtils.java
+++ b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/meter/PeriodMeter.java
@@ -14,10 +14,15 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.netflix.spectator.api;
+package org.apache.servicecomb.foundation.metrics.meter;
-public class SpectatorUtils {
- public static CompositeRegistry createCompositeRegistry(Clock clock) {
- return new CompositeRegistry(clock);
- }
+import java.util.List;
+
+import com.netflix.spectator.api.Measurement;
+import com.netflix.spectator.api.Meter;
+
+public interface PeriodMeter extends Meter {
+ void calcMeasurements(long msNow, long secondInterval);
+
+ void calcMeasurements(List<Measurement> measurements, long msNow, long secondInterval);
}
diff --git a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/meter/SimpleTimer.java b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/meter/SimpleTimer.java
new file mode 100644
index 0000000..09803a4
--- /dev/null
+++ b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/meter/SimpleTimer.java
@@ -0,0 +1,93 @@
+/*
+ * 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.metrics.meter;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.LongAdder;
+
+import com.netflix.spectator.api.Id;
+import com.netflix.spectator.api.Measurement;
+import com.netflix.spectator.api.Statistic;
+import com.netflix.spectator.impl.AtomicDouble;
+
+/**
+ * ServoTimer is too slow
+ * this is a faster timer
+ */
+public class SimpleTimer extends AbstractPeriodMeter {
+ private static final double CNV_SECONDS = 1.0 / TimeUnit.SECONDS.toNanos(1L);
+
+ private final Id idCount;
+
+ private final Id idTotalTime;
+
+ private final Id idMax;
+
+ private final LongAdder count = new LongAdder();
+
+ private final LongAdder totalTime = new LongAdder();
+
+ private final AtomicDouble max = new AtomicDouble();
+
+ private long lastCount = 0;
+
+ private long lastTotalTime = 0;
+
+ public SimpleTimer(Id id) {
+ this.id = id;
+ this.idCount = id.withTag(Statistic.count);
+ this.idTotalTime = id.withTag(Statistic.totalTime);
+ this.idMax = id.withTag(Statistic.max);
+ }
+
+ public void record(long nanoAmount) {
+ if (nanoAmount >= 0) {
+ totalTime.add(nanoAmount);
+ count.increment();
+ max.max(nanoAmount);
+ }
+ }
+
+ private Measurement newMeasurement(Id id, long msNow, Number n) {
+ return new Measurement(id, msNow, n.doubleValue());
+ }
+
+ @Override
+ public void calcMeasurements(long msNow, long secondInterval) {
+ List<Measurement> measurements = new ArrayList<>(3);
+ calcMeasurements(measurements, msNow, secondInterval);
+ allMeasurements = measurements;
+ }
+
+ @Override
+ public void calcMeasurements(List<Measurement> measurements, long msNow, long secondInterval) {
+ long currentCount = count.longValue();
+ long currentTotalTime = totalTime.longValue();
+
+ measurements.add(newMeasurement(idCount, msNow, (double) (currentCount - lastCount) / secondInterval));
+ measurements
+ .add(newMeasurement(idTotalTime, msNow, (currentTotalTime - lastTotalTime) / secondInterval * CNV_SECONDS));
+ measurements.add(newMeasurement(idMax, msNow, max.get() * CNV_SECONDS));
+
+ lastCount = currentCount;
+ lastTotalTime = currentTotalTime;
+ // maybe lost some max value, but not so important?
+ max.set(0);
+ }
+}
diff --git a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/registry/GlobalRegistry.java b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/registry/GlobalRegistry.java
new file mode 100644
index 0000000..9af39d0
--- /dev/null
+++ b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/registry/GlobalRegistry.java
@@ -0,0 +1,114 @@
+/*
+ * 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.metrics.registry;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+import org.apache.servicecomb.foundation.metrics.PolledEvent;
+import org.apache.servicecomb.foundation.metrics.meter.PeriodMeter;
+
+import com.netflix.spectator.api.Clock;
+import com.netflix.spectator.api.Measurement;
+import com.netflix.spectator.api.Meter;
+import com.netflix.spectator.api.Registry;
+import com.netflix.spectator.api.SpectatorUtils;
+
+public class GlobalRegistry {
+ private Clock clock;
+
+ private List<Registry> registries = new CopyOnWriteArrayList<>();
+
+ private Registry defaultRegistry;
+
+ public GlobalRegistry() {
+ this(Clock.SYSTEM);
+ }
+
+ public GlobalRegistry(Clock clock) {
+ this.clock = clock;
+ }
+
+ public Clock getClock() {
+ return clock;
+ }
+
+ public List<Registry> getRegistries() {
+ return registries;
+ }
+
+ public Registry getDefaultRegistry() {
+ return defaultRegistry;
+ }
+
+ public synchronized void add(Registry registry) {
+ if (registries.isEmpty()) {
+ defaultRegistry = registry;
+ }
+ registries.add(registry);
+ }
+
+ public synchronized void remove(Registry registry) {
+ registries.remove(registry);
+ if (registry != defaultRegistry) {
+ return;
+ }
+
+ if (registries.isEmpty()) {
+ defaultRegistry = null;
+ return;
+ }
+
+ defaultRegistry = registries.get(0);
+ }
+
+ public synchronized void removeAll() {
+ registries.clear();
+ defaultRegistry = null;
+ }
+
+ @SuppressWarnings("unchecked")
+ public <T extends Registry> T find(Class<T> cls) {
+ for (Registry registry : registries) {
+ if (cls.isAssignableFrom(registry.getClass())) {
+ return (T) registry;
+ }
+ }
+ return null;
+ }
+
+ public PolledEvent poll(long secondInterval) {
+ long msNow = clock.wallTime();
+ List<Meter> meters = new ArrayList<>();
+ List<Measurement> measurements = new ArrayList<>();
+ for (Registry registry : registries) {
+ SpectatorUtils.removeExpiredMeters(registry);
+
+ for (Meter meter : registry) {
+ if (meter instanceof PeriodMeter) {
+ ((PeriodMeter) meter).calcMeasurements(msNow, secondInterval);
+ }
+
+ meters.add(meter);
+ meter.measure().forEach(measurements::add);
+ }
+ }
+
+ return new PolledEvent(meters, measurements);
+ }
+}
diff --git a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/PollEvent.java b/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/meter/TestSimpleTimer.java
similarity index 51%
rename from foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/PollEvent.java
rename to foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/meter/TestSimpleTimer.java
index 80a2055..1d34497 100644
--- a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/PollEvent.java
+++ b/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/meter/TestSimpleTimer.java
@@ -14,19 +14,28 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.servicecomb.foundation.metrics;
+package org.apache.servicecomb.foundation.metrics.meter;
-/**
- * give not standard meters to calc measurement , eg : cpu usage, net throughput, and so on
- */
-public class PollEvent {
- private final long msPollInterval;
+import org.junit.Assert;
+import org.junit.Test;
- public PollEvent(long msPollInterval) {
- this.msPollInterval = msPollInterval;
- }
+import com.netflix.spectator.api.SpectatorUtils;
+
+public class TestSimpleTimer {
+ SimpleTimer timer = new SimpleTimer(SpectatorUtils.createDefaultId("name"));
+
+ @Test
+ public void measure() {
+ timer.record(2);
+ timer.record(4);
+
+ Assert.assertFalse(timer.measure().iterator().hasNext());
- public long getMsPollInterval() {
- return msPollInterval;
+ timer.calcMeasurements(1, 2);
+ Assert.assertEquals(
+ "[Measurement(name:statistic=count,1,1.0), Measurement(name:statistic=totalTime,1,3.0000000000000004E-9), Measurement(name:statistic=max,1,4.0E-9)]",
+ timer.measure().toString());
+ Assert.assertFalse(timer.hasExpired());
+ Assert.assertEquals("name", timer.id().name());
}
}
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
index f25ca64..86590ce 100644
--- 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
@@ -16,7 +16,7 @@
*/
package org.apache.servicecomb.foundation.vertx.metrics.metric;
-import java.util.concurrent.atomic.AtomicLong;
+import java.util.concurrent.atomic.LongAdder;
import io.vertx.core.net.SocketAddress;
@@ -28,15 +28,15 @@ public class DefaultEndpointMetric {
// summary of connect times from boot
// by this, we can know how many new connections connected recently
- private AtomicLong connectCount = new AtomicLong();
+ private LongAdder connectCount = new LongAdder();
// summary of disconnect times from boot
// by this, we can know how many connections disconnected recently
- private AtomicLong disconnectCount = new AtomicLong();
+ private LongAdder disconnectCount = new LongAdder();
- private AtomicLong bytesRead = new AtomicLong();
+ private LongAdder bytesRead = new LongAdder();
- private AtomicLong bytesWritten = new AtomicLong();
+ private LongAdder bytesWritten = new LongAdder();
public DefaultEndpointMetric(SocketAddress address) {
this.address = address;
@@ -47,38 +47,38 @@ public class DefaultEndpointMetric {
}
public long getConnectCount() {
- return connectCount.get();
+ return connectCount.longValue();
}
public long getDisconnectCount() {
- return disconnectCount.get();
+ return disconnectCount.longValue();
}
public long getCurrentConnectionCount() {
- return connectCount.get() - disconnectCount.get();
+ return connectCount.longValue() - disconnectCount.longValue();
}
public void onConnect() {
- connectCount.incrementAndGet();
+ connectCount.increment();
}
public void onDisconnect() {
- disconnectCount.incrementAndGet();
+ disconnectCount.increment();
}
public long getBytesRead() {
- return bytesRead.get();
+ return bytesRead.longValue();
}
- public long addBytesRead(long bytes) {
- return bytesRead.addAndGet(bytes);
+ public void addBytesRead(long bytes) {
+ bytesRead.add(bytes);
}
public long getBytesWritten() {
- return bytesWritten.get();
+ return bytesWritten.longValue();
}
- public long addBytesWritten(long bytes) {
- return bytesWritten.addAndGet(bytes);
+ public void addBytesWritten(long bytes) {
+ bytesWritten.add(bytes);
}
}
diff --git a/java-chassis-dependencies/pom.xml b/java-chassis-dependencies/pom.xml
index 50a0778..0847d69 100644
--- a/java-chassis-dependencies/pom.xml
+++ b/java-chassis-dependencies/pom.xml
@@ -366,7 +366,7 @@
<dependency>
<groupId>com.netflix.spectator</groupId>
<artifactId>spectator-reg-servo</artifactId>
- <version>0.63.0</version>
+ <version>0.71.0</version>
</dependency>
<dependency>
<groupId>com.google.inject</groupId>
diff --git a/java-chassis-distribution/src/release/LICENSE b/java-chassis-distribution/src/release/LICENSE
index 31051f3..e166434 100644
--- a/java-chassis-distribution/src/release/LICENSE
+++ b/java-chassis-distribution/src/release/LICENSE
@@ -422,8 +422,8 @@ rxnetty-servo (https://github.com/ReactiveX/RxNetty) io.reactivex:rxnetty-servo:
servo-core (https://github.com/Netflix/servo) com.netflix.servo:servo-core:jar:0.10.1
servo-internal (https://github.com/Netflix/servo) com.netflix.servo:servo-internal:jar:0.10.1
SnakeYAML (http://www.snakeyaml.org) org.yaml:snakeyaml:bundle:1.16
-spectator-api (https://github.com/Netflix/spectator) com.netflix.spectator:spectator-api:0.63.0
-spectator-reg-servo (https://github.com/Netflix/spectator) com.netflix.spectator:spectator-reg-servo:0.63.0
+spectator-api (https://github.com/Netflix/spectator) com.netflix.spectator:spectator-api:0.71.0
+spectator-reg-servo (https://github.com/Netflix/spectator) com.netflix.spectator:spectator-reg-servo:0.71.0
Spring AOP (https://github.com/spring-projects/spring-framework) org.springframework:spring-aop:jar:4.3.16.RELEASE
Spring Aspects (https://github.com/spring-projects/spring-framework) org.springframework:spring-aspects:jar:4.3.16.RELEASE
Spring Beans (https://github.com/spring-projects/spring-framework) org.springframework:spring-beans:jar:4.3.16.RELEASE