pull/9205/head
yang-g 8 years ago
parent c3c475fd14
commit b74cf429fd
  1. 59
      src/cpp/server/health/default_health_check_service.cc
  2. 4
      src/cpp/server/health/default_health_check_service.h
  3. 8
      src/cpp/server/health/health.pb.c
  4. 4
      src/cpp/server/health/health.pb.h
  5. 2
      src/proto/grpc/health/v1/health.options
  6. 13
      test/cpp/end2end/health_service_end2end_test.cc

@ -38,8 +38,9 @@
#include <grpc/support/log.h>
#include "src/cpp/server/health/default_health_check_service.h"
#include "third_party/nanopb/pb_encode.h"
#include "src/cpp/server/health/health.pb.h"
#include "third_party/nanopb/pb_decode.h"
#include "third_party/nanopb/pb_encode.h"
namespace grpc {
namespace {
@ -61,7 +62,60 @@ DefaultHealthCheckService::SyncHealthCheckServiceImpl::
Status DefaultHealthCheckService::SyncHealthCheckServiceImpl::Check(
ServerContext* context, const ByteBuffer* request, ByteBuffer* response) {
// Decode request.
std::vector<Slice> slices;
request->Dump(&slices);
const uint8_t* request_bytes = nullptr;
size_t request_size = 0;
grpc_health_v1_HealthCheckRequest request_struct;
if (slices.empty()) {
request_struct.has_service = false;
} else if (slices.size() == 1) {
request_bytes = slices[0].begin();
request_size = slices[0].size();
} else {
abort(); // TODO
}
if (request_bytes != nullptr) {
pb_istream_t istream = pb_istream_from_buffer(request_bytes, request_size);
bool decode_status = pb_decode(
&istream, grpc_health_v1_HealthCheckRequest_fields, &request_struct);
if (!decode_status) {
return Status(StatusCode::INVALID_ARGUMENT, "");
}
}
// Check status from the associated default health checking service.
DefaultHealthCheckService::ServingStatus serving_status =
service_->GetServingStatus(
request_struct.has_service ? request_struct.service : "");
if (serving_status == DefaultHealthCheckService::NOT_FOUND) {
return Status(StatusCode::NOT_FOUND, "");
}
// Encode response
grpc_health_v1_HealthCheckResponse response_struct;
response_struct.has_status = true;
response_struct.status =
serving_status == DefaultHealthCheckService::SERVING
? grpc_health_v1_HealthCheckResponse_ServingStatus_SERVING
: grpc_health_v1_HealthCheckResponse_ServingStatus_NOT_SERVING;
pb_ostream_t ostream;
memset(&ostream, 0, sizeof(ostream));
pb_encode(&ostream, grpc_health_v1_HealthCheckResponse_fields,
&response_struct);
grpc_slice response_slice = grpc_slice_malloc(ostream.bytes_written);
ostream = pb_ostream_from_buffer(GRPC_SLICE_START_PTR(response_slice),
GRPC_SLICE_LENGTH(response_slice));
bool encode_status = pb_encode(
&ostream, grpc_health_v1_HealthCheckResponse_fields, &response_struct);
if (!encode_status) {
return Status(StatusCode::INTERNAL, "Failed to encode response.");
}
Slice encoded_response(response_slice, Slice::STEAL_REF);
ByteBuffer response_buffer(&encoded_response, 1);
response->Swap(&response_buffer);
return Status::OK;
}
@ -84,7 +138,8 @@ void DefaultHealthCheckService::SetServingStatus(bool serving) {
}
DefaultHealthCheckService::ServingStatus
DefaultHealthCheckService::GetServingStatus(const grpc::string& service_name) {
DefaultHealthCheckService::GetServingStatus(
const grpc::string& service_name) const {
std::lock_guard<std::mutex> lock(mu_);
const auto& iter = services_map_.find(service_name);
if (iter == services_map_.end()) {

@ -60,13 +60,13 @@ class DefaultHealthCheckService : public HealthCheckServiceInterface {
void SetServingStatus(const grpc::string& service_name, bool serving) final;
void SetServingStatus(bool serving) final;
enum ServingStatus { NOT_FOUND, SERVING, NOT_SERVING };
ServingStatus GetServingStatus(const grpc::string& service_name);
ServingStatus GetServingStatus(const grpc::string& service_name) const;
SyncHealthCheckServiceImpl* GetSyncHealthCheckService() const {
return sync_service_.get();
}
private:
std::mutex mu_;
mutable std::mutex mu_;
std::map<grpc::string, bool> services_map_;
std::unique_ptr<SyncHealthCheckServiceImpl> sync_service_;
};

@ -33,7 +33,7 @@
/* Automatically generated nanopb constant definitions */
/* Generated by nanopb-0.3.7-dev */
#include "/usr/local/google/home/yangg/github/grpc/src/cpp/server//health.pb.h"
#include "src/cpp/server/health/health.pb.h"
/* @@protoc_insertion_point(includes) */
#if PB_PROTO_HEADER_VERSION != 30
@ -53,10 +53,4 @@ const pb_field_t grpc_health_v1_HealthCheckResponse_fields[2] = {
};
/* Check that field information fits in pb_field_t */
#if !defined(PB_FIELD_16BIT) && !defined(PB_FIELD_32BIT)
#error Field descriptor for grpc_health_v1_HealthCheckRequest.service is too large. Define PB_FIELD_16BIT to fix this.
#endif
/* @@protoc_insertion_point(eof) */

@ -58,7 +58,7 @@ typedef enum _grpc_health_v1_HealthCheckResponse_ServingStatus {
/* Struct definitions */
typedef struct _grpc_health_v1_HealthCheckRequest {
bool has_service;
char service[2048];
char service[200];
/* @@protoc_insertion_point(struct:grpc_health_v1_HealthCheckRequest) */
} grpc_health_v1_HealthCheckRequest;
@ -85,7 +85,7 @@ extern const pb_field_t grpc_health_v1_HealthCheckRequest_fields[2];
extern const pb_field_t grpc_health_v1_HealthCheckResponse_fields[2];
/* Maximum encoded size of messages (where known) */
#define grpc_health_v1_HealthCheckRequest_size 2051
#define grpc_health_v1_HealthCheckRequest_size 203
#define grpc_health_v1_HealthCheckResponse_size 2
/* Message IDs (where set with "msgid" option) */

@ -1 +1 @@
grpc.health.v1.HealthCheckRequest.service max_size:2048
grpc.health.v1.HealthCheckRequest.service max_size:200

@ -85,7 +85,6 @@ class HealthServiceEnd2endTest : public ::testing::Test {
void ResetStubs() {
std::shared_ptr<Channel> channel =
CreateChannel(server_address_.str(), InsecureChannelCredentials());
stub_ = grpc::testing::EchoTestService::NewStub(channel);
hc_stub_ = grpc::health::v1::Health::NewStub(channel);
}
@ -98,14 +97,12 @@ class HealthServiceEnd2endTest : public ::testing::Test {
ClientContext context;
Status s = hc_stub_->Check(&context, request, &response);
EXPECT_EQ(expected_status.error_code(), s.error_code());
// EXPECT_EQ(expected_status.error_details(), s.error_details());
if (s.ok()) {
EXPECT_EQ(expected_serving_status, response.status());
}
}
TestServiceImpl echo_test_service_;
std::unique_ptr<grpc::testing::EchoTestService::Stub> stub_;
std::unique_ptr<Health::Stub> hc_stub_;
std::unique_ptr<Server> server_;
std::ostringstream server_address_;
@ -129,6 +126,8 @@ TEST_F(HealthServiceEnd2endTest, DefaultHealthService) {
EXPECT_TRUE(default_service != nullptr);
const grpc::string kHealthyService("healthy_service");
const grpc::string kUnhealthyService("unhealthy_service");
const grpc::string kNotRegisteredService("not_registered");
const grpc::string kTooLongServiceName(201, 'x');
default_service->SetServingStatus(kHealthyService, true);
default_service->SetServingStatus(kUnhealthyService, false);
@ -138,6 +137,10 @@ TEST_F(HealthServiceEnd2endTest, DefaultHealthService) {
SendHealthCheckRpc(kHealthyService, Status::OK, HealthCheckResponse::SERVING);
SendHealthCheckRpc(kUnhealthyService, Status::OK,
HealthCheckResponse::NOT_SERVING);
SendHealthCheckRpc(kNotRegisteredService, Status(StatusCode::NOT_FOUND, ""),
HealthCheckResponse::NOT_SERVING);
SendHealthCheckRpc(kTooLongServiceName, Status(StatusCode::INVALID_ARGUMENT, ""),
HealthCheckResponse::NOT_SERVING);
default_service->SetServingStatus(false);
SendHealthCheckRpc("", Status::OK, HealthCheckResponse::NOT_SERVING);
@ -145,6 +148,10 @@ TEST_F(HealthServiceEnd2endTest, DefaultHealthService) {
HealthCheckResponse::NOT_SERVING);
SendHealthCheckRpc(kUnhealthyService, Status::OK,
HealthCheckResponse::NOT_SERVING);
SendHealthCheckRpc(kNotRegisteredService, Status(StatusCode::NOT_FOUND, ""),
HealthCheckResponse::NOT_SERVING);
SendHealthCheckRpc(kTooLongServiceName, Status(StatusCode::INVALID_ARGUMENT, ""),
HealthCheckResponse::NOT_SERVING);
}
} // namespace

Loading…
Cancel
Save