Skip to content

Commit

Permalink
Add health checks to Node.js services (GoogleCloudPlatform#26)
Browse files Browse the repository at this point in the history
* Move Node healthchecks to gRPC

* gitignore proto files

* Switch to standard health RPC

* Fix lint

* Update client.js

* Add protos back + update them

* node services: fix & run genproto.sh

this gets currencyservice to work but paymentservice is still crashing
in the docker container.

Signed-off-by: Ahmet Alp Balkan <ahmetb@google.com>

* Fix docker breaking

* update dockerfiles with released health probe

Signed-off-by: Ahmet Alp Balkan <ahmetb@google.com>
  • Loading branch information
Ace Nassri authored and ahmetb committed Sep 19, 2018
1 parent 360d983 commit 6c37a96
Show file tree
Hide file tree
Showing 18 changed files with 313 additions and 109 deletions.
10 changes: 4 additions & 6 deletions kubernetes-manifests/currencyservice.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,11 @@ spec:
- name: grpc
containerPort: 7000
readinessProbe:
periodSeconds: 5
tcpSocket:
port: 7000
exec:
command: ["/bin/grpc_health_probe", "-addr=:7000"]
livenessProbe:
periodSeconds: 5
tcpSocket:
port: 7000
exec:
command: ["/bin/grpc_health_probe", "-addr=:7000"]
resources:
requests:
cpu: 100m
Expand Down
10 changes: 4 additions & 6 deletions kubernetes-manifests/paymentservice.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,11 @@ spec:
ports:
- containerPort: 50051
readinessProbe:
periodSeconds: 5
tcpSocket:
port: 50051
exec:
command: ["/bin/grpc_health_probe", "-addr=:50051"]
livenessProbe:
periodSeconds: 5
tcpSocket:
port: 50051
exec:
command: ["/bin/grpc_health_probe", "-addr=:50051"]
resources:
requests:
cpu: 100m
Expand Down
43 changes: 43 additions & 0 deletions pb/grpc/health/v1/health.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// Copyright 2015 The 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
//
// 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.

// The canonical version of this proto can be found at
// https://github.com/grpc/grpc-proto/blob/master/grpc/health/v1/health.proto

syntax = "proto3";

package grpc.health.v1;

option csharp_namespace = "Grpc.Health.V1";
option go_package = "google.golang.org/grpc/health/grpc_health_v1";
option java_multiple_files = true;
option java_outer_classname = "HealthProto";
option java_package = "io.grpc.health.v1";

message HealthCheckRequest {
string service = 1;
}

message HealthCheckResponse {
enum ServingStatus {
UNKNOWN = 0;
SERVING = 1;
NOT_SERVING = 2;
}
ServingStatus status = 1;
}

service Health {
rpc Check(HealthCheckRequest) returns (HealthCheckResponse);
}
3 changes: 3 additions & 0 deletions src/currencyservice/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
FROM node:8
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 /usr/src/app
COPY package*.json ./
RUN npm install --only=production
Expand Down
4 changes: 2 additions & 2 deletions src/currencyservice/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ const grpc = require('grpc');
const leftPad = require('left-pad');

const PROTO_PATH = path.join(__dirname, './proto/demo.proto');
const PORT = 31337;
const PORT = 7000;

const shopProto = grpc.load(PROTO_PATH).hipstershop;
const client = new shopProto.CurrencyService(`localhost:${PORT}`,
Expand All @@ -49,7 +49,7 @@ client.getSupportedCurrencies({}, (err, response) => {
}
});

client.convert(request, function (err, response) {
client.convert(request, (err, response) => {
if (err) {
console.error(`Error in convert: ${err}`);
} else {
Expand Down
5 changes: 2 additions & 3 deletions src/currencyservice/genproto.sh
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.

#!/bin/bash -e
# protos are loaded dynamically for node, simply copies over the proto.
mkdir -p proto && \
cp ../../pb/demo.proto proto
mkdir -p proto
cp -r ../../pb/* ./proto
10 changes: 9 additions & 1 deletion src/currencyservice/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,25 @@
"name": "grpc-currency-service",
"version": "0.1.0",
"description": "A gRPC currency conversion microservice",
"repository": "TODO",
"repository": "https://github.com/GoogleCloudPlatform/microservices-demo",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"lint": "semistandard *.js"
},
"license": "Apache-2.0",
"dependencies": {
"@google-cloud/debug-agent": "^2.6.0",
"@google-cloud/profiler": "^0.1.14",
"@google-cloud/trace-agent": "^2.11.0",
"@grpc/proto-loader": "^0.3.0",
"async": "^1.5.2",
"google-protobuf": "^3.0.0",
"grpc": "^1.0.0",
"left-pad": "^1.3.0",
"request": "^2.87.0",
"xml2js": "^0.4.19"
},
"devDependencies": {
"semistandard": "^12.0.1"
}
}
41 changes: 26 additions & 15 deletions src/currencyservice/proto/demo.proto
Original file line number Diff line number Diff line change
Expand Up @@ -108,9 +108,9 @@ message ShipOrderResponse {
}

message Address {
string street_address_1 = 1;
string street_address_2 = 2;
string city= 3;
string street_address = 1;
string city = 2;
string state = 3;
string country = 4;
int32 zip_code = 5;
}
Expand Down Expand Up @@ -202,21 +202,9 @@ message SendOrderConfirmationRequest {
// -------------Checkout service-----------------

service CheckoutService {
rpc CreateOrder(CreateOrderRequest) returns (CreateOrderResponse) {}
rpc PlaceOrder(PlaceOrderRequest) returns (PlaceOrderResponse) {}
}

message CreateOrderRequest {
string user_id = 1;
string user_currency = 2;
Address address = 3;
}

message CreateOrderResponse {
repeated OrderItem items = 1;
Money shipping_cost = 2;
}

message PlaceOrderRequest {
string user_id = 1;
string user_currency = 2;
Expand All @@ -229,3 +217,26 @@ message PlaceOrderRequest {
message PlaceOrderResponse {
OrderResult order = 1;
}

// ------------Ads service------------------

service AdsService {
rpc GetAds(AdsRequest) returns (AdsResponse) {}
}

message AdsRequest {
// List of important key words from the current page describing the context.
repeated string context_keys = 1;
}

message AdsResponse {
repeated Ad ads = 1;
}

message Ad {
// url to redirect to when an ad is clicked.
string redirect_url = 1;

// short advertisement text to display.
string text = 2;
}
43 changes: 43 additions & 0 deletions src/currencyservice/proto/grpc/health/v1/health.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// Copyright 2015 The 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
//
// 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.

// The canonical version of this proto can be found at
// https://github.com/grpc/grpc-proto/blob/master/grpc/health/v1/health.proto

syntax = "proto3";

package grpc.health.v1;

option csharp_namespace = "Grpc.Health.V1";
option go_package = "google.golang.org/grpc/health/grpc_health_v1";
option java_multiple_files = true;
option java_outer_classname = "HealthProto";
option java_package = "io.grpc.health.v1";

message HealthCheckRequest {
string service = 1;
}

message HealthCheckResponse {
enum ServingStatus {
UNKNOWN = 0;
SERVING = 1;
NOT_SERVING = 2;
}
ServingStatus status = 1;
}

service Health {
rpc Check(HealthCheckRequest) returns (HealthCheckResponse);
}
48 changes: 39 additions & 9 deletions src/currencyservice/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,27 +16,49 @@

require('@google-cloud/profiler').start({
serviceContext: {
service: 'currencyservice',
version: '1.0.0'
service: 'currencyservice',
version: '1.0.0'
}
});
require('@google-cloud/trace-agent').start();
require('@google-cloud/debug-agent').start({
require('@google-cloud/trace-agent').start();
require('@google-cloud/debug-agent').start({
serviceContext: {
service: 'currencyservice',
version: 'VERSION'
}
})
});

const path = require('path');
const grpc = require('grpc');
const request = require('request');
const xml2js = require('xml2js');
const protoLoader = require('@grpc/proto-loader');

const MAIN_PROTO_PATH = path.join(__dirname, './proto/demo.proto');
const HEALTH_PROTO_PATH = path.join(__dirname, './proto/grpc/health/v1/health.proto');

const PROTO_PATH = path.join(__dirname, './proto/demo.proto');
const PORT = 7000;
const DATA_URL = 'http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml';
const shopProto = grpc.load(PROTO_PATH).hipstershop;

const shopProto = _loadProto(MAIN_PROTO_PATH).hipstershop;
const healthProto = _loadProto(HEALTH_PROTO_PATH).grpc.health.v1;

/**
* Helper function that loads a protobuf file.
*/
function _loadProto (path) {
const packageDefinition = protoLoader.loadSync(
path,
{
keepCase: true,
longs: String,
enums: String,
defaults: true,
oneofs: true
}
);
return grpc.loadPackageDefinition(packageDefinition);
}

/**
* Helper function that gets currency data from an XML webpage
Expand Down Expand Up @@ -116,8 +138,8 @@ function convert (call, callback) {
nanos: euros.nanos * data[request.to_code]
});

result.units = Math.floor(result.units)
result.nanos = Math.floor(result.nanos)
result.units = Math.floor(result.units);
result.nanos = Math.floor(result.nanos);
result.currency_code = request.to_code;

console.log(`conversion request successful`);
Expand All @@ -130,6 +152,13 @@ function convert (call, callback) {
}
}

/**
* Endpoint for health checks
*/
function check (call, callback) {
callback(null, { status: 'SERVING' });
}

/**
* Starts an RPC server that receives requests for the
* CurrencyConverter service at the sample server port
Expand All @@ -138,6 +167,7 @@ function main () {
console.log(`Starting gRPC server on port ${PORT}...`);
const server = new grpc.Server();
server.addService(shopProto.CurrencyService.service, {getSupportedCurrencies, convert});
server.addService(healthProto.Health.service, {check});
server.bind(`0.0.0.0:${PORT}`, grpc.ServerCredentials.createInsecure());
server.start();
}
Expand Down
3 changes: 3 additions & 0 deletions src/paymentservice/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
FROM node:8
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 /usr/src/app

Expand Down
Loading

0 comments on commit 6c37a96

Please sign in to comment.