grpc: add health check to go services

Signed-off-by: Ahmet Alp Balkan <ahmetb@google.com>
This commit is contained in:
Ahmet Alp Balkan 2018-08-07 13:21:38 -07:00
parent 3c86418822
commit fc1fb698d2
No known key found for this signature in database
GPG key ID: 5C02521D7B216AD6
15 changed files with 76 additions and 48 deletions

View file

@ -28,13 +28,11 @@ spec:
ports: ports:
- containerPort: 5050 - containerPort: 5050
readinessProbe: readinessProbe:
periodSeconds: 5 exec:
tcpSocket: command: ["/bin/grpc_health_probe", "-addr=:5050"]
port: 5050
livenessProbe: livenessProbe:
periodSeconds: 5 exec:
tcpSocket: command: ["/bin/grpc_health_probe", "-addr=:5050"]
port: 5050
env: env:
- name: PRODUCT_CATALOG_SERVICE_ADDR - name: PRODUCT_CATALOG_SERVICE_ADDR
value: "productcatalogservice:3550" value: "productcatalogservice:3550"

View file

@ -29,13 +29,11 @@ spec:
ports: ports:
- containerPort: 3550 - containerPort: 3550
readinessProbe: readinessProbe:
periodSeconds: 5 exec:
tcpSocket: command: ["/bin/grpc_health_probe", "-addr=:3550"]
port: 3550
livenessProbe: livenessProbe:
periodSeconds: 5 exec:
tcpSocket: command: ["/bin/grpc_health_probe", "-addr=:3550"]
port: 3550
resources: resources:
requests: requests:
cpu: 100m cpu: 100m

View file

@ -29,12 +29,11 @@ spec:
- containerPort: 50051 - containerPort: 50051
readinessProbe: readinessProbe:
periodSeconds: 5 periodSeconds: 5
tcpSocket: exec:
port: 50051 command: ["/bin/grpc_health_probe", "-addr=:50051"]
livenessProbe: livenessProbe:
periodSeconds: 5 exec:
tcpSocket: command: ["/bin/grpc_health_probe", "-addr=:50051"]
port: 50051
resources: resources:
requests: requests:
cpu: 100m cpu: 100m

View file

@ -15,6 +15,9 @@ RUN go build -gcflags='-N -l' -o /checkoutservice .
FROM alpine as release FROM alpine as release
RUN apk add --no-cache ca-certificates RUN apk add --no-cache ca-certificates
RUN GRPC_HEALTH_PROBE_VERSION=v0.1.0-alpha.1 && \
wget -qO/bin/grpc_health_probe https://github.com/grpc-ecosystem/grpc-health-probe/releases/download/${GRPC_HEALTH_PROBE_VERSION}/grpc_health_probe-linux-amd64 && \
chmod +x /bin/grpc_health_probe
COPY --from=builder /checkoutservice /checkoutservice COPY --from=builder /checkoutservice /checkoutservice
EXPOSE 5050 EXPOSE 5050
ENTRYPOINT ["/checkoutservice"] ENTRYPOINT ["/checkoutservice"]

View file

@ -10,8 +10,8 @@
"profiler", "profiler",
"trace/apiv2" "trace/apiv2"
] ]
revision = "aad3f485ee528456e0768f20397b4d9dd941e755" revision = "64a2037ec6be8a4b0c1d1f706ed35b428b989239"
version = "v0.25.0" version = "v0.26.0"
[[projects]] [[projects]]
name = "contrib.go.opencensus.io/exporter/stackdriver" name = "contrib.go.opencensus.io/exporter/stackdriver"
@ -42,7 +42,7 @@
branch = "master" branch = "master"
name = "github.com/google/pprof" name = "github.com/google/pprof"
packages = ["profile"] packages = ["profile"]
revision = "ef437552946f69f7e3bdf1fd81c385c29530944d" revision = "cf6d271c80826ef4d30d55512b5a77b115bd4b9c"
[[projects]] [[projects]]
name = "github.com/google/uuid" name = "github.com/google/uuid"
@ -89,7 +89,7 @@
"internal/timeseries", "internal/timeseries",
"trace" "trace"
] ]
revision = "f4c29de78a2a91c00474a2e689954305c350adf9" revision = "19491d39cadbd9cd33f26ca22cc89ba4ba38251c"
[[projects]] [[projects]]
branch = "master" branch = "master"
@ -113,7 +113,7 @@
branch = "master" branch = "master"
name = "golang.org/x/sys" name = "golang.org/x/sys"
packages = ["unix"] packages = ["unix"]
revision = "0ffbfd41fbef8ffcf9b62b0b0aa3a5873ed7a4fe" revision = "acbc56fc7007d2a01796d5bde54f39e3b3e95945"
[[projects]] [[projects]]
name = "golang.org/x/text" name = "golang.org/x/text"
@ -149,7 +149,7 @@
"transport/grpc", "transport/grpc",
"transport/http" "transport/http"
] ]
revision = "f6d94689cbd71030af1108ddac733886fcae1d75" revision = "9bdf771af19ab16b6a5084e5d542a7e04cb97004"
[[projects]] [[projects]]
name = "google.golang.org/appengine" name = "google.golang.org/appengine"
@ -202,6 +202,7 @@
"encoding", "encoding",
"encoding/proto", "encoding/proto",
"grpclog", "grpclog",
"health/grpc_health_v1",
"internal", "internal",
"internal/backoff", "internal/backoff",
"internal/channelz", "internal/channelz",
@ -225,6 +226,6 @@
[solve-meta] [solve-meta]
analyzer-name = "dep" analyzer-name = "dep"
analyzer-version = 1 analyzer-version = 1
inputs-digest = "54254ec0ccf29fb2b490b54b12e5f3eb752ab9b8f9d4f5ab097d60f96eeed9d9" inputs-digest = "8f72f95f416d2a7991e6f7b5e9883615fb5889241a43b5101118c00a8e0efe0a"
solver-name = "gps-cdcl" solver-name = "gps-cdcl"
solver-version = 1 solver-version = 1

View file

@ -27,7 +27,7 @@
[[constraint]] [[constraint]]
name = "cloud.google.com/go" name = "cloud.google.com/go"
version = "0.25.0" version = "0.26.0"
[[constraint]] [[constraint]]
name = "contrib.go.opencensus.io/exporter/stackdriver" name = "contrib.go.opencensus.io/exporter/stackdriver"

View file

@ -33,6 +33,7 @@ import (
pb "github.com/GoogleCloudPlatform/microservices-demo/src/checkoutservice/genproto" pb "github.com/GoogleCloudPlatform/microservices-demo/src/checkoutservice/genproto"
money "github.com/GoogleCloudPlatform/microservices-demo/src/checkoutservice/money" money "github.com/GoogleCloudPlatform/microservices-demo/src/checkoutservice/money"
healthpb "google.golang.org/grpc/health/grpc_health_v1"
) )
const ( const (
@ -74,6 +75,7 @@ func main() {
} }
srv := grpc.NewServer(grpc.StatsHandler(&ocgrpc.ServerHandler{})) srv := grpc.NewServer(grpc.StatsHandler(&ocgrpc.ServerHandler{}))
pb.RegisterCheckoutServiceServer(srv, svc) pb.RegisterCheckoutServiceServer(srv, svc)
healthpb.RegisterHealthServer(srv, svc)
log.Printf("starting to listen on tcp: %q", lis.Addr().String()) log.Printf("starting to listen on tcp: %q", lis.Addr().String())
log.Fatal(srv.Serve(lis)) log.Fatal(srv.Serve(lis))
} }
@ -128,6 +130,10 @@ func mustMapEnv(target *string, envKey string) {
*target = v *target = v
} }
func (cs *checkoutService) Check(ctx context.Context, req *healthpb.HealthCheckRequest) (*healthpb.HealthCheckResponse, error) {
return &healthpb.HealthCheckResponse{Status: healthpb.HealthCheckResponse_SERVING}, nil
}
func (cs *checkoutService) PlaceOrder(ctx context.Context, req *pb.PlaceOrderRequest) (*pb.PlaceOrderResponse, error) { func (cs *checkoutService) PlaceOrder(ctx context.Context, req *pb.PlaceOrderRequest) (*pb.PlaceOrderResponse, error) {
log.Printf("[PlaceOrder] user_id=%q user_currency=%q", req.UserId, req.UserCurrency) log.Printf("[PlaceOrder] user_id=%q user_currency=%q", req.UserId, req.UserCurrency)

View file

@ -1,4 +1,4 @@
FROM golang:1.10-alpine as builder FROM golang:1.10-alpine AS builder
RUN apk add --no-cache ca-certificates git && \ RUN apk add --no-cache ca-certificates git && \
wget -qO/go/bin/dep https://github.com/golang/dep/releases/download/v0.5.0/dep-linux-amd64 && \ wget -qO/go/bin/dep https://github.com/golang/dep/releases/download/v0.5.0/dep-linux-amd64 && \
chmod +x /go/bin/dep chmod +x /go/bin/dep
@ -13,8 +13,11 @@ RUN dep ensure --vendor-only -v
COPY . . COPY . .
RUN go build -o /productcatalogservice . RUN go build -o /productcatalogservice .
FROM alpine as release FROM alpine AS release
RUN apk add --no-cache ca-certificates RUN apk add --no-cache ca-certificates
RUN GRPC_HEALTH_PROBE_VERSION=v0.1.0-alpha.1 && \
wget -qO/bin/grpc_health_probe https://github.com/grpc-ecosystem/grpc-health-probe/releases/download/${GRPC_HEALTH_PROBE_VERSION}/grpc_health_probe-linux-amd64 && \
chmod +x /bin/grpc_health_probe
WORKDIR /productcatalogservice WORKDIR /productcatalogservice
COPY --from=builder /productcatalogservice ./server COPY --from=builder /productcatalogservice ./server
COPY products.json . COPY products.json .

View file

@ -10,8 +10,8 @@
"profiler", "profiler",
"trace/apiv2" "trace/apiv2"
] ]
revision = "aad3f485ee528456e0768f20397b4d9dd941e755" revision = "64a2037ec6be8a4b0c1d1f706ed35b428b989239"
version = "v0.25.0" version = "v0.26.0"
[[projects]] [[projects]]
name = "contrib.go.opencensus.io/exporter/stackdriver" name = "contrib.go.opencensus.io/exporter/stackdriver"
@ -54,7 +54,7 @@
branch = "master" branch = "master"
name = "github.com/google/pprof" name = "github.com/google/pprof"
packages = ["profile"] packages = ["profile"]
revision = "ef437552946f69f7e3bdf1fd81c385c29530944d" revision = "cf6d271c80826ef4d30d55512b5a77b115bd4b9c"
[[projects]] [[projects]]
name = "github.com/googleapis/gax-go" name = "github.com/googleapis/gax-go"
@ -95,7 +95,7 @@
"internal/timeseries", "internal/timeseries",
"trace" "trace"
] ]
revision = "f4c29de78a2a91c00474a2e689954305c350adf9" revision = "19491d39cadbd9cd33f26ca22cc89ba4ba38251c"
[[projects]] [[projects]]
branch = "master" branch = "master"
@ -119,7 +119,7 @@
branch = "master" branch = "master"
name = "golang.org/x/sys" name = "golang.org/x/sys"
packages = ["unix"] packages = ["unix"]
revision = "0ffbfd41fbef8ffcf9b62b0b0aa3a5873ed7a4fe" revision = "acbc56fc7007d2a01796d5bde54f39e3b3e95945"
[[projects]] [[projects]]
name = "golang.org/x/text" name = "golang.org/x/text"
@ -155,7 +155,7 @@
"transport/grpc", "transport/grpc",
"transport/http" "transport/http"
] ]
revision = "f6d94689cbd71030af1108ddac733886fcae1d75" revision = "9bdf771af19ab16b6a5084e5d542a7e04cb97004"
[[projects]] [[projects]]
name = "google.golang.org/appengine" name = "google.golang.org/appengine"
@ -208,6 +208,7 @@
"encoding", "encoding",
"encoding/proto", "encoding/proto",
"grpclog", "grpclog",
"health/grpc_health_v1",
"internal", "internal",
"internal/backoff", "internal/backoff",
"internal/channelz", "internal/channelz",
@ -231,6 +232,6 @@
[solve-meta] [solve-meta]
analyzer-name = "dep" analyzer-name = "dep"
analyzer-version = 1 analyzer-version = 1
inputs-digest = "c8e8e119ed16d97490ab7d949aa70654738f91a59da70583dfed22ee44661a1b" inputs-digest = "9375853c56aec58c0407e2a95be6b83d632ff9d9921be437ea839904e9da5cf4"
solver-name = "gps-cdcl" solver-name = "gps-cdcl"
solver-version = 1 solver-version = 1

View file

@ -27,7 +27,7 @@
[[constraint]] [[constraint]]
name = "cloud.google.com/go" name = "cloud.google.com/go"
version = "0.25.0" version = "0.26.0"
[[constraint]] [[constraint]]
name = "contrib.go.opencensus.io/exporter/stackdriver" name = "contrib.go.opencensus.io/exporter/stackdriver"

View file

@ -26,6 +26,7 @@ import (
"time" "time"
pb "github.com/GoogleCloudPlatform/microservices-demo/src/productcatalogservice/genproto" pb "github.com/GoogleCloudPlatform/microservices-demo/src/productcatalogservice/genproto"
healthpb "google.golang.org/grpc/health/grpc_health_v1"
"cloud.google.com/go/profiler" "cloud.google.com/go/profiler"
"contrib.go.opencensus.io/exporter/stackdriver" "contrib.go.opencensus.io/exporter/stackdriver"
@ -68,7 +69,9 @@ func run(port int) string {
log.Fatal(err) log.Fatal(err)
} }
srv := grpc.NewServer(grpc.StatsHandler(&ocgrpc.ServerHandler{})) srv := grpc.NewServer(grpc.StatsHandler(&ocgrpc.ServerHandler{}))
pb.RegisterProductCatalogServiceServer(srv, &productCatalog{}) svc := &productCatalog{}
pb.RegisterProductCatalogServiceServer(srv, svc)
healthpb.RegisterHealthServer(srv, svc)
go srv.Serve(l) go srv.Serve(l)
return l.Addr().String() return l.Addr().String()
} }
@ -127,6 +130,10 @@ func parseCatalog() []*pb.Product {
return cat.Products return cat.Products
} }
func (p *productCatalog) Check(ctx context.Context, req *healthpb.HealthCheckRequest) (*healthpb.HealthCheckResponse, error) {
return &healthpb.HealthCheckResponse{Status: healthpb.HealthCheckResponse_SERVING}, nil
}
func (p *productCatalog) ListProducts(context.Context, *pb.Empty) (*pb.ListProductsResponse, error) { func (p *productCatalog) ListProducts(context.Context, *pb.Empty) (*pb.ListProductsResponse, error) {
return &pb.ListProductsResponse{Products: parseCatalog()}, nil return &pb.ListProductsResponse{Products: parseCatalog()}, nil
} }

View file

@ -14,6 +14,9 @@ RUN go install .
FROM alpine as release FROM alpine as release
RUN apk add --no-cache ca-certificates RUN apk add --no-cache ca-certificates
RUN GRPC_HEALTH_PROBE_VERSION=v0.1.0-alpha.1 && \
wget -qO/bin/grpc_health_probe https://github.com/grpc-ecosystem/grpc-health-probe/releases/download/${GRPC_HEALTH_PROBE_VERSION}/grpc_health_probe-linux-amd64 && \
chmod +x /bin/grpc_health_probe
COPY --from=builder /go/bin/shippingservice /shippingservice COPY --from=builder /go/bin/shippingservice /shippingservice
ENV APP_PORT=50051 ENV APP_PORT=50051
EXPOSE 50051 EXPOSE 50051

View file

@ -10,8 +10,8 @@
"profiler", "profiler",
"trace/apiv2" "trace/apiv2"
] ]
revision = "aad3f485ee528456e0768f20397b4d9dd941e755" revision = "64a2037ec6be8a4b0c1d1f706ed35b428b989239"
version = "v0.25.0" version = "v0.26.0"
[[projects]] [[projects]]
name = "contrib.go.opencensus.io/exporter/stackdriver" name = "contrib.go.opencensus.io/exporter/stackdriver"
@ -42,7 +42,7 @@
branch = "master" branch = "master"
name = "github.com/google/pprof" name = "github.com/google/pprof"
packages = ["profile"] packages = ["profile"]
revision = "ef437552946f69f7e3bdf1fd81c385c29530944d" revision = "cf6d271c80826ef4d30d55512b5a77b115bd4b9c"
[[projects]] [[projects]]
name = "github.com/googleapis/gax-go" name = "github.com/googleapis/gax-go"
@ -83,7 +83,7 @@
"internal/timeseries", "internal/timeseries",
"trace" "trace"
] ]
revision = "f4c29de78a2a91c00474a2e689954305c350adf9" revision = "19491d39cadbd9cd33f26ca22cc89ba4ba38251c"
[[projects]] [[projects]]
branch = "master" branch = "master"
@ -107,7 +107,7 @@
branch = "master" branch = "master"
name = "golang.org/x/sys" name = "golang.org/x/sys"
packages = ["unix"] packages = ["unix"]
revision = "0ffbfd41fbef8ffcf9b62b0b0aa3a5873ed7a4fe" revision = "acbc56fc7007d2a01796d5bde54f39e3b3e95945"
[[projects]] [[projects]]
name = "golang.org/x/text" name = "golang.org/x/text"
@ -143,7 +143,7 @@
"transport/grpc", "transport/grpc",
"transport/http" "transport/http"
] ]
revision = "f6d94689cbd71030af1108ddac733886fcae1d75" revision = "9bdf771af19ab16b6a5084e5d542a7e04cb97004"
[[projects]] [[projects]]
name = "google.golang.org/appengine" name = "google.golang.org/appengine"
@ -196,6 +196,7 @@
"encoding", "encoding",
"encoding/proto", "encoding/proto",
"grpclog", "grpclog",
"health/grpc_health_v1",
"internal", "internal",
"internal/backoff", "internal/backoff",
"internal/channelz", "internal/channelz",
@ -221,6 +222,6 @@
[solve-meta] [solve-meta]
analyzer-name = "dep" analyzer-name = "dep"
analyzer-version = 1 analyzer-version = 1
inputs-digest = "3f4776192cec97ef87c4d20a52c9752d106a298befc139e5bca176bf915ed63b" inputs-digest = "e2a0b47948cf03a5d2a05d2baf26b0a1f4da4102b2c7bbba377d46c1095444f9"
solver-name = "gps-cdcl" solver-name = "gps-cdcl"
solver-version = 1 solver-version = 1

View file

@ -27,7 +27,7 @@
[[constraint]] [[constraint]]
name = "cloud.google.com/go" name = "cloud.google.com/go"
version = "0.25.0" version = "0.26.0"
[[constraint]] [[constraint]]
name = "contrib.go.opencensus.io/exporter/stackdriver" name = "contrib.go.opencensus.io/exporter/stackdriver"

View file

@ -30,6 +30,7 @@ import (
"google.golang.org/grpc/reflection" "google.golang.org/grpc/reflection"
pb "github.com/GoogleCloudPlatform/microservices-demo/src/shippingservice/genproto" pb "github.com/GoogleCloudPlatform/microservices-demo/src/shippingservice/genproto"
healthpb "google.golang.org/grpc/health/grpc_health_v1"
) )
const ( const (
@ -50,13 +51,15 @@ func main() {
if err != nil { if err != nil {
log.Fatalf("failed to listen: %v", err) log.Fatalf("failed to listen: %v", err)
} }
s := grpc.NewServer(grpc.StatsHandler(&ocgrpc.ServerHandler{})) srv := grpc.NewServer(grpc.StatsHandler(&ocgrpc.ServerHandler{}))
pb.RegisterShippingServiceServer(s, &server{}) svc := &server{}
pb.RegisterShippingServiceServer(srv, svc)
healthpb.RegisterHealthServer(srv, svc)
log.Printf("Shipping Service listening on port %s", port) log.Printf("Shipping Service listening on port %s", port)
// Register reflection service on gRPC server. // Register reflection service on gRPC server.
reflection.Register(s) reflection.Register(srv)
if err := s.Serve(lis); err != nil { if err := srv.Serve(lis); err != nil {
log.Fatalf("failed to serve: %v", err) log.Fatalf("failed to serve: %v", err)
} }
} }
@ -64,6 +67,11 @@ func main() {
// server controls RPC service responses. // server controls RPC service responses.
type server struct{} type server struct{}
// Check is for health checking.
func (s *server) Check(ctx context.Context, req *healthpb.HealthCheckRequest) (*healthpb.HealthCheckResponse, error) {
return &healthpb.HealthCheckResponse{Status: healthpb.HealthCheckResponse_SERVING}, nil
}
// GetQuote produces a shipping quote (cost) in USD. // GetQuote produces a shipping quote (cost) in USD.
func (s *server) GetQuote(ctx context.Context, in *pb.GetQuoteRequest) (*pb.GetQuoteResponse, error) { func (s *server) GetQuote(ctx context.Context, in *pb.GetQuoteRequest) (*pb.GetQuoteResponse, error) {
log.Printf("[GetQuote] received request") log.Printf("[GetQuote] received request")