mirror of https://github.com/grpc/grpc-java.git
services: add qps in orca api (#9866)
This commit is contained in:
parent
fb70a66e2c
commit
6119f6ec94
|
|
@ -95,10 +95,10 @@ def grpc_java_repositories():
|
||||||
if not native.existing_rule("com_github_cncf_xds"):
|
if not native.existing_rule("com_github_cncf_xds"):
|
||||||
http_archive(
|
http_archive(
|
||||||
name = "com_github_cncf_xds",
|
name = "com_github_cncf_xds",
|
||||||
strip_prefix = "xds-d92e9ce0af512a73a3a126b32fa4920bee12e180",
|
strip_prefix = "xds-06c439db220b89134a8a49bad41994560d6537c6",
|
||||||
sha256 = "27be88b1ff2844885d3b2d0d579546f3a8b3f26b4871eed89082c9709e49a4bd",
|
sha256 = "41ea212940ab44bf7f8a8b4169cfbc612ed2166dafabc0a56a8820ef665fc6a4",
|
||||||
urls = [
|
urls = [
|
||||||
"https://github.com/cncf/xds/archive/d92e9ce0af512a73a3a126b32fa4920bee12e180.tar.gz",
|
"https://github.com/cncf/xds/archive/06c439db220b89134a8a49bad41994560d6537c6.tar.gz",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
if not native.existing_rule("com_github_grpc_grpc"):
|
if not native.existing_rule("com_github_grpc_grpc"):
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,7 @@ public final class CallMetricRecorder {
|
||||||
new AtomicReference<>();
|
new AtomicReference<>();
|
||||||
private double cpuUtilizationMetric = 0;
|
private double cpuUtilizationMetric = 0;
|
||||||
private double memoryUtilizationMetric = 0;
|
private double memoryUtilizationMetric = 0;
|
||||||
|
private double qps = 0;
|
||||||
private volatile boolean disabled;
|
private volatile boolean disabled;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -158,6 +159,23 @@ public final class CallMetricRecorder {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Records a call metric measurement for qps.
|
||||||
|
* If RPC has already finished, this method is no-op.
|
||||||
|
*
|
||||||
|
* <p>A latter record will overwrite its former name-sakes.
|
||||||
|
*
|
||||||
|
* @return this recorder object
|
||||||
|
* @since 1.54.0
|
||||||
|
*/
|
||||||
|
public CallMetricRecorder recordQpsMetric(double value) {
|
||||||
|
if (disabled) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
qps = value;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns all request cost metric values. No more metric values will be recorded after this
|
* Returns all request cost metric values. No more metric values will be recorded after this
|
||||||
|
|
@ -187,8 +205,8 @@ public final class CallMetricRecorder {
|
||||||
if (savedUtilizationMetrics == null) {
|
if (savedUtilizationMetrics == null) {
|
||||||
savedUtilizationMetrics = Collections.emptyMap();
|
savedUtilizationMetrics = Collections.emptyMap();
|
||||||
}
|
}
|
||||||
return new MetricReport(cpuUtilizationMetric,
|
return new MetricReport(cpuUtilizationMetric, memoryUtilizationMetric, qps,
|
||||||
memoryUtilizationMetric, Collections.unmodifiableMap(savedRequestCostMetrics),
|
Collections.unmodifiableMap(savedRequestCostMetrics),
|
||||||
Collections.unmodifiableMap(savedUtilizationMetrics)
|
Collections.unmodifiableMap(savedUtilizationMetrics)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -46,8 +46,8 @@ public final class InternalCallMetricRecorder {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static MetricReport createMetricReport(double cpuUtilization, double memoryUtilization,
|
public static MetricReport createMetricReport(double cpuUtilization, double memoryUtilization,
|
||||||
Map<String, Double> requestCostMetrics, Map<String, Double> utilizationMetrics) {
|
double qps, Map<String, Double> requestCostMetrics, Map<String, Double> utilizationMetrics) {
|
||||||
return new MetricReport(cpuUtilization, memoryUtilization,
|
return new MetricReport(cpuUtilization, memoryUtilization, qps, requestCostMetrics,
|
||||||
requestCostMetrics, utilizationMetrics);
|
utilizationMetrics);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@ public final class MetricRecorder {
|
||||||
private volatile ConcurrentHashMap<String, Double> metricsData = new ConcurrentHashMap<>();
|
private volatile ConcurrentHashMap<String, Double> metricsData = new ConcurrentHashMap<>();
|
||||||
private volatile double cpuUtilization;
|
private volatile double cpuUtilization;
|
||||||
private volatile double memoryUtilization;
|
private volatile double memoryUtilization;
|
||||||
|
private volatile double qps;
|
||||||
|
|
||||||
public static MetricRecorder newInstance() {
|
public static MetricRecorder newInstance() {
|
||||||
return new MetricRecorder();
|
return new MetricRecorder();
|
||||||
|
|
@ -86,8 +87,22 @@ public final class MetricRecorder {
|
||||||
memoryUtilization = 0;
|
memoryUtilization = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the QPS metrics data.
|
||||||
|
*/
|
||||||
|
public void setQps(double value) {
|
||||||
|
qps = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear the QPS metrics data.
|
||||||
|
*/
|
||||||
|
public void clearQps() {
|
||||||
|
qps = 0;
|
||||||
|
}
|
||||||
|
|
||||||
MetricReport getMetricReport() {
|
MetricReport getMetricReport() {
|
||||||
return new MetricReport(cpuUtilization, memoryUtilization,
|
return new MetricReport(cpuUtilization, memoryUtilization, qps,
|
||||||
Collections.emptyMap(), Collections.unmodifiableMap(metricsData));
|
Collections.emptyMap(), Collections.unmodifiableMap(metricsData));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,14 +30,16 @@ import java.util.Map;
|
||||||
public final class MetricReport {
|
public final class MetricReport {
|
||||||
private double cpuUtilization;
|
private double cpuUtilization;
|
||||||
private double memoryUtilization;
|
private double memoryUtilization;
|
||||||
|
private double qps;
|
||||||
private Map<String, Double> requestCostMetrics;
|
private Map<String, Double> requestCostMetrics;
|
||||||
private Map<String, Double> utilizationMetrics;
|
private Map<String, Double> utilizationMetrics;
|
||||||
|
|
||||||
MetricReport(double cpuUtilization, double memoryUtilization,
|
MetricReport(double cpuUtilization, double memoryUtilization, double qps,
|
||||||
Map<String, Double> requestCostMetrics,
|
Map<String, Double> requestCostMetrics,
|
||||||
Map<String, Double> utilizationMetrics) {
|
Map<String, Double> utilizationMetrics) {
|
||||||
this.cpuUtilization = cpuUtilization;
|
this.cpuUtilization = cpuUtilization;
|
||||||
this.memoryUtilization = memoryUtilization;
|
this.memoryUtilization = memoryUtilization;
|
||||||
|
this.qps = qps;
|
||||||
this.requestCostMetrics = checkNotNull(requestCostMetrics, "requestCostMetrics");
|
this.requestCostMetrics = checkNotNull(requestCostMetrics, "requestCostMetrics");
|
||||||
this.utilizationMetrics = checkNotNull(utilizationMetrics, "utilizationMetrics");
|
this.utilizationMetrics = checkNotNull(utilizationMetrics, "utilizationMetrics");
|
||||||
}
|
}
|
||||||
|
|
@ -58,6 +60,10 @@ public final class MetricReport {
|
||||||
return utilizationMetrics;
|
return utilizationMetrics;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public double getQps() {
|
||||||
|
return qps;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return MoreObjects.toStringHelper(this)
|
return MoreObjects.toStringHelper(this)
|
||||||
|
|
@ -65,6 +71,7 @@ public final class MetricReport {
|
||||||
.add("memoryUtilization", memoryUtilization)
|
.add("memoryUtilization", memoryUtilization)
|
||||||
.add("requestCost", requestCostMetrics)
|
.add("requestCost", requestCostMetrics)
|
||||||
.add("utilization", utilizationMetrics)
|
.add("utilization", utilizationMetrics)
|
||||||
|
.add("qps", qps)
|
||||||
.toString();
|
.toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,7 @@ public class CallMetricRecorderTest {
|
||||||
recorder.recordRequestCostMetric("cost3", 1.0);
|
recorder.recordRequestCostMetric("cost3", 1.0);
|
||||||
recorder.recordCpuUtilizationMetric(0.1928);
|
recorder.recordCpuUtilizationMetric(0.1928);
|
||||||
recorder.recordMemoryUtilizationMetric(47.4);
|
recorder.recordMemoryUtilizationMetric(47.4);
|
||||||
|
recorder.recordQpsMetric(2522.54);
|
||||||
|
|
||||||
MetricReport dump = recorder.finalizeAndDump2();
|
MetricReport dump = recorder.finalizeAndDump2();
|
||||||
Truth.assertThat(dump.getUtilizationMetrics())
|
Truth.assertThat(dump.getUtilizationMetrics())
|
||||||
|
|
@ -54,6 +55,7 @@ public class CallMetricRecorderTest {
|
||||||
.containsExactly("cost1", 37465.12, "cost2", 10293.0, "cost3", 1.0);
|
.containsExactly("cost1", 37465.12, "cost2", 10293.0, "cost3", 1.0);
|
||||||
Truth.assertThat(dump.getCpuUtilization()).isEqualTo(0.1928);
|
Truth.assertThat(dump.getCpuUtilization()).isEqualTo(0.1928);
|
||||||
Truth.assertThat(dump.getMemoryUtilization()).isEqualTo(47.4);
|
Truth.assertThat(dump.getMemoryUtilization()).isEqualTo(47.4);
|
||||||
|
Truth.assertThat(dump.getQps()).isEqualTo(2522.54);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
@ -75,6 +77,8 @@ public class CallMetricRecorderTest {
|
||||||
recorder.recordUtilizationMetric("util1", 28374.21);
|
recorder.recordUtilizationMetric("util1", 28374.21);
|
||||||
recorder.recordMemoryUtilizationMetric(9384.0);
|
recorder.recordMemoryUtilizationMetric(9384.0);
|
||||||
recorder.recordUtilizationMetric("util1", 84323.3);
|
recorder.recordUtilizationMetric("util1", 84323.3);
|
||||||
|
recorder.recordQpsMetric(1928.3);
|
||||||
|
recorder.recordQpsMetric(100.8);
|
||||||
|
|
||||||
MetricReport dump = recorder.finalizeAndDump2();
|
MetricReport dump = recorder.finalizeAndDump2();
|
||||||
Truth.assertThat(dump.getRequestCostMetrics())
|
Truth.assertThat(dump.getRequestCostMetrics())
|
||||||
|
|
@ -83,6 +87,7 @@ public class CallMetricRecorderTest {
|
||||||
Truth.assertThat(dump.getUtilizationMetrics())
|
Truth.assertThat(dump.getUtilizationMetrics())
|
||||||
.containsExactly("util1", 84323.3);
|
.containsExactly("util1", 84323.3);
|
||||||
Truth.assertThat(dump.getCpuUtilization()).isEqualTo(0);
|
Truth.assertThat(dump.getCpuUtilization()).isEqualTo(0);
|
||||||
|
Truth.assertThat(dump.getQps()).isEqualTo(100.8);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
||||||
|
|
@ -254,8 +254,8 @@ public abstract class OrcaPerRequestUtil {
|
||||||
|
|
||||||
static MetricReport fromOrcaLoadReport(OrcaLoadReport loadReport) {
|
static MetricReport fromOrcaLoadReport(OrcaLoadReport loadReport) {
|
||||||
return InternalCallMetricRecorder.createMetricReport(loadReport.getCpuUtilization(),
|
return InternalCallMetricRecorder.createMetricReport(loadReport.getCpuUtilization(),
|
||||||
loadReport.getMemUtilization(), loadReport.getRequestCostMap(),
|
loadReport.getMemUtilization(), loadReport.getRpsFractional(),
|
||||||
loadReport.getUtilizationMap());
|
loadReport.getRequestCostMap(), loadReport.getUtilizationMap());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -150,6 +150,7 @@ public final class OrcaServiceImpl implements BindableService {
|
||||||
InternalMetricRecorder.getMetricReport(metricRecorder);
|
InternalMetricRecorder.getMetricReport(metricRecorder);
|
||||||
return OrcaLoadReport.newBuilder().setCpuUtilization(internalReport.getCpuUtilization())
|
return OrcaLoadReport.newBuilder().setCpuUtilization(internalReport.getCpuUtilization())
|
||||||
.setMemUtilization(internalReport.getMemoryUtilization())
|
.setMemUtilization(internalReport.getMemoryUtilization())
|
||||||
|
.setRpsFractional(internalReport.getQps())
|
||||||
.putAllUtilization(internalReport.getUtilizationMetrics())
|
.putAllUtilization(internalReport.getUtilizationMetrics())
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -143,19 +143,23 @@ public class OrcaServiceImplTest {
|
||||||
ClientCall<OrcaLoadReportRequest, OrcaLoadReport> call = channel.newCall(
|
ClientCall<OrcaLoadReportRequest, OrcaLoadReport> call = channel.newCall(
|
||||||
OpenRcaServiceGrpc.getStreamCoreMetricsMethod(), CallOptions.DEFAULT);
|
OpenRcaServiceGrpc.getStreamCoreMetricsMethod(), CallOptions.DEFAULT);
|
||||||
defaultTestService.putUtilizationMetric("buffer", 0.2);
|
defaultTestService.putUtilizationMetric("buffer", 0.2);
|
||||||
|
defaultTestService.setQps(1.9);
|
||||||
call.start(listener, new Metadata());
|
call.start(listener, new Metadata());
|
||||||
call.sendMessage(OrcaLoadReportRequest.newBuilder()
|
call.sendMessage(OrcaLoadReportRequest.newBuilder()
|
||||||
.setReportInterval(Duration.newBuilder().setSeconds(0).setNanos(500).build()).build());
|
.setReportInterval(Duration.newBuilder().setSeconds(0).setNanos(500).build()).build());
|
||||||
call.halfClose();
|
call.halfClose();
|
||||||
call.request(1);
|
call.request(1);
|
||||||
OrcaLoadReport expect = OrcaLoadReport.newBuilder().putUtilization("buffer", 0.2).build();
|
OrcaLoadReport expect = OrcaLoadReport.newBuilder().putUtilization("buffer", 0.2)
|
||||||
|
.setRpsFractional(1.9).build();
|
||||||
verify(listener).onMessage(eq(expect));
|
verify(listener).onMessage(eq(expect));
|
||||||
reset(listener);
|
reset(listener);
|
||||||
defaultTestService.removeUtilizationMetric("buffer0");
|
defaultTestService.removeUtilizationMetric("buffer0");
|
||||||
|
defaultTestService.clearQps();
|
||||||
assertThat(fakeClock.forwardTime(500, TimeUnit.NANOSECONDS)).isEqualTo(0);
|
assertThat(fakeClock.forwardTime(500, TimeUnit.NANOSECONDS)).isEqualTo(0);
|
||||||
verifyNoInteractions(listener);
|
verifyNoInteractions(listener);
|
||||||
assertThat(fakeClock.forwardTime(1, TimeUnit.SECONDS)).isEqualTo(1);
|
assertThat(fakeClock.forwardTime(1, TimeUnit.SECONDS)).isEqualTo(1);
|
||||||
call.request(1);
|
call.request(1);
|
||||||
|
expect = OrcaLoadReport.newBuilder().putUtilization("buffer", 0.2).build();
|
||||||
verify(listener).onMessage(eq(expect));
|
verify(listener).onMessage(eq(expect));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -245,17 +249,20 @@ public class OrcaServiceImplTest {
|
||||||
.setMemUtilization(random.nextDouble())
|
.setMemUtilization(random.nextDouble())
|
||||||
.putAllUtilization(firstUtilization)
|
.putAllUtilization(firstUtilization)
|
||||||
.putUtilization("queue", 1.0)
|
.putUtilization("queue", 1.0)
|
||||||
|
.setRpsFractional(1239.01)
|
||||||
.build();
|
.build();
|
||||||
defaultTestService.setCpuUtilizationMetric(goldenReport.getCpuUtilization());
|
defaultTestService.setCpuUtilizationMetric(goldenReport.getCpuUtilization());
|
||||||
defaultTestService.setMemoryUtilizationMetric(goldenReport.getMemUtilization());
|
defaultTestService.setMemoryUtilizationMetric(goldenReport.getMemUtilization());
|
||||||
defaultTestService.setAllUtilizationMetrics(firstUtilization);
|
defaultTestService.setAllUtilizationMetrics(firstUtilization);
|
||||||
defaultTestService.putUtilizationMetric("queue", 1.0);
|
defaultTestService.putUtilizationMetric("queue", 1.0);
|
||||||
|
defaultTestService.setQps(1239.01);
|
||||||
Iterator<OrcaLoadReport> reports = OpenRcaServiceGrpc.newBlockingStub(channel)
|
Iterator<OrcaLoadReport> reports = OpenRcaServiceGrpc.newBlockingStub(channel)
|
||||||
.streamCoreMetrics(OrcaLoadReportRequest.newBuilder().build());
|
.streamCoreMetrics(OrcaLoadReportRequest.newBuilder().build());
|
||||||
assertThat(reports.next()).isEqualTo(goldenReport);
|
assertThat(reports.next()).isEqualTo(goldenReport);
|
||||||
|
|
||||||
defaultTestService.clearCpuUtilizationMetric();
|
defaultTestService.clearCpuUtilizationMetric();
|
||||||
defaultTestService.clearMemoryUtilizationMetric();
|
defaultTestService.clearMemoryUtilizationMetric();
|
||||||
|
defaultTestService.clearQps();
|
||||||
fakeClock.forwardTime(1, TimeUnit.SECONDS);
|
fakeClock.forwardTime(1, TimeUnit.SECONDS);
|
||||||
goldenReport = OrcaLoadReport.newBuilder()
|
goldenReport = OrcaLoadReport.newBuilder()
|
||||||
.putAllUtilization(firstUtilization)
|
.putAllUtilization(firstUtilization)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue