-
Notifications
You must be signed in to change notification settings - Fork 839
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1043 from fengli79/master
Add an end to end example for gRPC A66 metrics.
- Loading branch information
Showing
17 changed files
with
2,126 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,130 @@ | ||
# gRPC-Observability Example | ||
|
||
## Features | ||
|
||
* End to end examples to generate the gRPC metrics with Prometheus, including: | ||
* A frontend microservice ( | ||
in [gRPC-Spring](https://github.com/grpc-ecosystem/grpc-spring)), which | ||
keeps calling the backend microservices. | ||
* A backend microservice ( | ||
in [gRPC-Spring](https://github.com/grpc-ecosystem/grpc-spring)), which | ||
serves unary/client streaming/server streaming and bidi streaming example | ||
services. | ||
* Instructions to containerize them and deploy them in kubernetes | ||
* Monitoring dashboards to support | ||
the [gRPC A66](https://github.com/grpc/proposal/blob/master/A66-otel-stats.md) | ||
spec. | ||
* Deploy the Grafana and import | ||
the [gRPC A66](https://github.com/grpc/proposal/blob/master/A66-otel-stats.md) | ||
dashboard | ||
|
||
## Build the end to end example | ||
|
||
Under the root directory of your grpc-spring repo | ||
|
||
``` | ||
./gradlew build | ||
``` | ||
|
||
## Run the end to end example | ||
|
||
Run the backend microservice locally | ||
|
||
``` | ||
./gradlew examples:grpc-observability:backend:bootRun | ||
``` | ||
|
||
Run the frontend microservice locally. Please note that the backend needs to be | ||
started first to be ready to serve the client calls. | ||
|
||
``` | ||
./gradlew examples:grpc-observability:frontend:bootRun | ||
``` | ||
|
||
The backend microservice will | ||
|
||
- listen on the TCP port 9091 for the gRPC calls from the frontend microservice. | ||
- listen on the TCP port 8081 for the Prometheus scrape requests. | ||
The frontend microservice will | ||
- send the unary/client streaming/server streaming/bidi streaming calls to the | ||
backend microservices via TCP port 9091. | ||
- listen on the TCP port 8080 for the Prometheus scrape requests. | ||
|
||
## Containerize the frontend/backend microservices | ||
|
||
Build the docker image for the backend microservice | ||
|
||
``` | ||
docker build -t grpc-observability/grpc-spring-example-backend examples/grpc-observability/backend | ||
``` | ||
|
||
Run the backend microservice with docker | ||
|
||
``` | ||
docker run --network host grpc-observability/grpc-spring-example-backend | ||
``` | ||
|
||
Build the docker image for the frontend microservice | ||
|
||
``` | ||
docker build -t grpc-observability/grpc-spring-example-frontend examples/grpc-observability/frontend | ||
``` | ||
|
||
Run the frontend microservice with docker | ||
|
||
``` | ||
docker run --network host grpc-observability/grpc-spring-example-frontend | ||
``` | ||
|
||
## Deploy the end to end example to kubernetes | ||
|
||
To deploy the example to kubernetes, please upload the docker images to a | ||
registry by yourself and modify the frontend.yaml/backend.yaml with your docker | ||
image location, and then run following commands. | ||
|
||
Deploy the backend microservice in kubernetes | ||
|
||
``` | ||
kubectl apply -f ./examples/grpc-observability/backend/backend.yaml | ||
``` | ||
|
||
Deploy the frontend microservice in kubernetes | ||
|
||
``` | ||
kubectl apply -f ./examples/grpc-observability/frontend/frontend.yaml | ||
``` | ||
|
||
## Set up the Prometheus to collect the gRPC metrics | ||
|
||
Once the frontend/backend microservices are deployed (either locally or on | ||
cloud), you may set up the Prometheus to start scraping the metrics from them. | ||
Depends on where you run the frontend/backend microservices, you may need to | ||
deploy the Prometheus to a proper location to be able to access them, such as, | ||
the same cloud, etc. | ||
|
||
If you | ||
use [Google Managed Prometheus](https://cloud.google.com/stackdriver/docs/managed-prometheus), | ||
you may need to configure the PodMonitoring resource to tell where are endpoints | ||
to scrape the Prometheus metrics. | ||
|
||
``` | ||
kubectl apply -f ./examples/grpc-observability/pod_monitoring.yaml | ||
``` | ||
|
||
## Set up the Grafana dashboard | ||
|
||
Once we have the gRPC metrics scraped by the Prometheus, we may set up a Grafana | ||
server to visualize them. | ||
|
||
- Set up a Grafana server, deploy it to a place where can connect the Prometheus | ||
server as its data source. | ||
- Create a Grafana dashboard by importing the | ||
[examples/grpc-observability/grafana/prometheus/microservices-grpc-dashboard.json](http://github.com/grpc-ecosystem/grpc-spring/blob/master/examples/grpc-observability/grafana/prometheus/microservices-grpc-dashboard.json) | ||
file. | ||
|
||
If you | ||
use [Google Managed Prometheus](https://cloud.google.com/stackdriver/docs/managed-prometheus), | ||
you need to follow | ||
the [Grafana Query User Guide](https://cloud.google.com/stackdriver/docs/managed-prometheus/query) | ||
to set up the Grafana server | ||
and [data source syncer](https://github.com/GoogleCloudPlatform/prometheus-engine/tree/main/cmd/datasource-syncer). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
FROM eclipse-temurin:17-jdk-alpine | ||
COPY build/libs/backend.jar backend.jar | ||
ENTRYPOINT ["java","-jar","/backend.jar"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
# Copyright 2023 gRPC Authors | ||
# | ||
# Licensed 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 | ||
# | ||
# https://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. | ||
# | ||
apiVersion: apps/v1 | ||
kind: Deployment | ||
metadata: | ||
name: backend | ||
spec: | ||
replicas: 1 | ||
selector: | ||
matchLabels: | ||
app: backend | ||
template: | ||
metadata: | ||
labels: | ||
app: backend | ||
monitor: prometheus | ||
spec: | ||
containers: | ||
- name: backend | ||
# Please upload the docker image of grpc-observability/grpc-spring-example-backend to an image registry, such as https://cloud.google.com/artifact-registry. | ||
image: <your image of the backend> | ||
ports: | ||
- name: monitoring | ||
containerPort: 8081 | ||
- name: grpc | ||
containerPort: 9091 | ||
--- | ||
apiVersion: v1 | ||
kind: Service | ||
metadata: | ||
name: backend | ||
spec: | ||
clusterIP: None | ||
selector: | ||
app: backend | ||
ports: | ||
- name: monitoring | ||
port: 8081 | ||
- name: grpc | ||
port: 9091 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
// Copyright 2023 The gRPC-GCP-Mobile Authors | ||
// All rights reserved. | ||
// | ||
// Licensed 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. | ||
// | ||
plugins { | ||
id 'org.springframework.boot' | ||
} | ||
|
||
dependencies { | ||
implementation project(':examples:grpc-observability:proto') | ||
implementation project(':grpc-server-spring-boot-starter') | ||
implementation 'org.springframework.boot:spring-boot-starter-actuator' | ||
implementation "org.springframework.boot:spring-boot-starter-web" | ||
implementation 'io.micrometer:micrometer-registry-prometheus' | ||
} |
29 changes: 29 additions & 0 deletions
29
...d/src/main/java/net/devh/boot/grpc/examples/observability/backend/BackendApplication.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
/* | ||
* Copyright (c) 2016-2023 The gRPC-Spring Authors | ||
* | ||
* Licensed 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 net.devh.boot.grpc.examples.observability.backend; | ||
|
||
import org.springframework.boot.SpringApplication; | ||
import org.springframework.boot.autoconfigure.SpringBootApplication; | ||
|
||
@SpringBootApplication | ||
public class BackendApplication { | ||
|
||
public static void main(String[] args) { | ||
SpringApplication.run(BackendApplication.class, args); | ||
} | ||
|
||
} |
116 changes: 116 additions & 0 deletions
116
...d/src/main/java/net/devh/boot/grpc/examples/observability/backend/ExampleServiceImpl.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
/* | ||
* Copyright (c) 2016-2023 The gRPC-Spring Authors | ||
* | ||
* Licensed 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 net.devh.boot.grpc.examples.observability.backend; | ||
|
||
import java.util.concurrent.ThreadLocalRandom; | ||
|
||
import io.grpc.Status; | ||
import io.grpc.stub.StreamObserver; | ||
import net.devh.boot.grpc.examples.observability.proto.BidiStreamingRequest; | ||
import net.devh.boot.grpc.examples.observability.proto.BidiStreamingResponse; | ||
import net.devh.boot.grpc.examples.observability.proto.ClientStreamingRequest; | ||
import net.devh.boot.grpc.examples.observability.proto.ClientStreamingResponse; | ||
import net.devh.boot.grpc.examples.observability.proto.ExampleServiceGrpc.ExampleServiceImplBase; | ||
import net.devh.boot.grpc.examples.observability.proto.ServerStreamingRequest; | ||
import net.devh.boot.grpc.examples.observability.proto.ServerStreamingResponse; | ||
import net.devh.boot.grpc.examples.observability.proto.UnaryRequest; | ||
import net.devh.boot.grpc.examples.observability.proto.UnaryResponse; | ||
import net.devh.boot.grpc.server.service.GrpcService; | ||
|
||
@GrpcService | ||
public class ExampleServiceImpl extends ExampleServiceImplBase { | ||
|
||
private boolean InjectError() { | ||
// We create ~5% error. | ||
return ThreadLocalRandom.current().nextInt(0, 99) >= 95; | ||
} | ||
|
||
@Override | ||
public void unaryRpc(UnaryRequest request, | ||
StreamObserver<UnaryResponse> responseObserver) { | ||
if (InjectError()) { | ||
responseObserver.onError(Status.INTERNAL.asException()); | ||
} else { | ||
responseObserver.onNext(UnaryResponse.newBuilder().setMessage(request.getMessage()).build()); | ||
responseObserver.onCompleted(); | ||
} | ||
} | ||
|
||
@Override | ||
public StreamObserver<ClientStreamingRequest> clientStreamingRpc( | ||
StreamObserver<ClientStreamingResponse> responseObserver) { | ||
return new StreamObserver<>() { | ||
@Override | ||
public void onNext(ClientStreamingRequest value) { | ||
responseObserver.onNext( | ||
ClientStreamingResponse.newBuilder().setMessage(value.getMessage()).build()); | ||
} | ||
|
||
@Override | ||
public void onError(Throwable t) { | ||
responseObserver.onError(t); | ||
} | ||
|
||
@Override | ||
public void onCompleted() { | ||
if (InjectError()) { | ||
responseObserver.onError(Status.INTERNAL.asException()); | ||
} else { | ||
responseObserver.onCompleted(); | ||
} | ||
} | ||
}; | ||
} | ||
|
||
@Override | ||
public void serverStreamingRpc(ServerStreamingRequest request, | ||
StreamObserver<ServerStreamingResponse> responseObserver) { | ||
if (InjectError()) { | ||
responseObserver.onError(Status.INTERNAL.asException()); | ||
} else { | ||
responseObserver.onNext( | ||
ServerStreamingResponse.newBuilder().setMessage(request.getMessage()).build()); | ||
responseObserver.onCompleted(); | ||
} | ||
} | ||
|
||
@Override | ||
public StreamObserver<BidiStreamingRequest> bidiStreamingRpc( | ||
StreamObserver<BidiStreamingResponse> responseObserver) { | ||
return new StreamObserver<>() { | ||
@Override | ||
public void onNext(BidiStreamingRequest value) { | ||
responseObserver.onNext( | ||
BidiStreamingResponse.newBuilder().setMessage(value.getMessage()).build()); | ||
} | ||
|
||
@Override | ||
public void onError(Throwable t) { | ||
responseObserver.onError(t); | ||
} | ||
|
||
@Override | ||
public void onCompleted() { | ||
if (InjectError()) { | ||
responseObserver.onError(Status.INTERNAL.asException()); | ||
} else { | ||
responseObserver.onCompleted(); | ||
} | ||
} | ||
}; | ||
} | ||
} |
7 changes: 7 additions & 0 deletions
7
examples/grpc-observability/backend/src/main/resources/application.properties
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
# Port serves the monitoring traffic. | ||
server.port=8081 | ||
# Expose the prometheus metrics via the monitoring port. | ||
# By default, expose on `/actuator/prometheus`. | ||
management.endpoints.web.exposure.include=prometheus | ||
# Port serves the gRPC traffic. | ||
grpc.server.port=9091 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
FROM eclipse-temurin:17-jdk-alpine | ||
COPY build/libs/frontend.jar frontend.jar | ||
ENTRYPOINT ["java","-jar","/frontend.jar"] |
Oops, something went wrong.