Add health checks to Node.js services (#26)
* 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>
This commit is contained in:
parent
360d983512
commit
6c37a96f3a
18 changed files with 313 additions and 109 deletions
|
@ -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
|
||||
|
|
|
@ -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}`,
|
||||
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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
src/currencyservice/proto/grpc/health/v1/health.proto
Normal file
43
src/currencyservice/proto/grpc/health/v1/health.proto
Normal file
|
@ -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);
|
||||
}
|
|
@ -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
|
||||
|
@ -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`);
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue