This is an automated email from the ASF dual-hosted git repository.

wwbmmm pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/brpc.git


The following commit(s) were added to refs/heads/master by this push:
     new ff75449b support grpc health check (#2493)
ff75449b is described below

commit ff75449bef3f7a677415eaa8025ce2bb7ce41511
Author: jiangyt-git <[email protected]>
AuthorDate: Tue Jan 23 13:21:45 2024 +0800

    support grpc health check (#2493)
    
    * support grpc health check protocol
    
    * add grpc health check ut
    
    ---------
    
    Co-authored-by: jiangyuting <[email protected]>
---
 CMakeLists.txt                                 |  1 +
 src/brpc/builtin/grpc_health_check_service.cpp | 41 +++++++++++++++
 src/brpc/builtin/grpc_health_check_service.h   | 37 ++++++++++++++
 src/brpc/grpc_health_check.proto               | 41 +++++++++++++++
 src/brpc/server.cpp                            |  5 ++
 test/brpc_builtin_service_unittest.cpp         | 69 ++++++++++++++++++++++++++
 6 files changed, 194 insertions(+)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 337701f3..b912dc8e 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -456,6 +456,7 @@ set(PROTO_FILES idl_options.proto
                 brpc/get_favicon.proto
                 brpc/span.proto
                 brpc/builtin_service.proto
+                brpc/grpc_health_check.proto
                 brpc/get_js.proto
                 brpc/errno.proto
                 brpc/nshead_meta.proto
diff --git a/src/brpc/builtin/grpc_health_check_service.cpp 
b/src/brpc/builtin/grpc_health_check_service.cpp
new file mode 100644
index 00000000..cba3dc8c
--- /dev/null
+++ b/src/brpc/builtin/grpc_health_check_service.cpp
@@ -0,0 +1,41 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you 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.
+
+#include "brpc/builtin/common.h"
+#include "brpc/builtin/grpc_health_check_service.h"
+#include "brpc/controller.h"           // Controller
+#include "brpc/closure_guard.h"        // ClosureGuard
+#include "brpc/server.h"               // Server
+
+namespace brpc {
+    void GrpcHealthCheckService::Check(::google::protobuf::RpcController* 
cntl_base,
+                                  const grpc::health::v1::HealthCheckRequest* 
request,
+                                  grpc::health::v1::HealthCheckResponse* 
response,
+                                  ::google::protobuf::Closure* done) {
+        ClosureGuard done_guard(done);
+        Controller *cntl = static_cast<Controller*>(cntl_base);
+        const Server* server = cntl->server();
+        if (server->options().health_reporter) {
+            server->options().health_reporter->GenerateReport(
+                    cntl, done_guard.release());
+        } else {
+            
response->set_status(grpc::health::v1::HealthCheckResponse_ServingStatus_SERVING);
+        }
+    }
+
+} // namespace brpc
+
diff --git a/src/brpc/builtin/grpc_health_check_service.h 
b/src/brpc/builtin/grpc_health_check_service.h
new file mode 100644
index 00000000..b5380639
--- /dev/null
+++ b/src/brpc/builtin/grpc_health_check_service.h
@@ -0,0 +1,37 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you 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.
+
+
+#ifndef BRPC_GRPC_HEALTH_CHECK_SERVICE_H
+#define BRPC_GRPC_HEALTH_CHECK_SERVICE_H
+
+#include "brpc/grpc_health_check.pb.h"
+
+namespace brpc {
+
+class GrpcHealthCheckService : public grpc::health::v1::Health {
+public:
+    void Check(::google::protobuf::RpcController* cntl_base,
+               const grpc::health::v1::HealthCheckRequest* request,
+               grpc::health::v1::HealthCheckResponse* response,
+               ::google::protobuf::Closure* done);
+
+};
+
+} // namespace brpc
+
+#endif //BRPC_GRPC_HEALTH_CHECK_SERVICE_H
diff --git a/src/brpc/grpc_health_check.proto b/src/brpc/grpc_health_check.proto
new file mode 100644
index 00000000..273840b8
--- /dev/null
+++ b/src/brpc/grpc_health_check.proto
@@ -0,0 +1,41 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you 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.
+
+syntax = "proto2";
+package grpc.health.v1;
+option cc_generic_services = true;
+
+message HealthCheckRequest {
+    optional string service = 1;
+}
+
+message HealthCheckResponse {
+    enum ServingStatus {
+        UNKNOWN = 0;
+        SERVING = 1;
+        NOT_SERVING = 2;
+        SERVICE_UNKNOWN = 3;  // Used only by the Watch method.
+    }
+    optional ServingStatus status = 1;
+}
+
+service Health {
+    rpc Check(HealthCheckRequest) returns (HealthCheckResponse);
+
+    rpc Watch(HealthCheckRequest) returns (stream HealthCheckResponse);
+}
+
diff --git a/src/brpc/server.cpp b/src/brpc/server.cpp
index ead24568..1b25f70e 100644
--- a/src/brpc/server.cpp
+++ b/src/brpc/server.cpp
@@ -45,6 +45,7 @@
 #include "brpc/builtin/bad_method_service.h"   // BadMethodService
 #include "brpc/builtin/get_favicon_service.h"
 #include "brpc/builtin/get_js_service.h"
+#include "brpc/builtin/grpc_health_check_service.h"  // GrpcHealthCheckService
 #include "brpc/builtin/version_service.h"
 #include "brpc/builtin/health_service.h"
 #include "brpc/builtin/list_service.h"
@@ -564,6 +565,10 @@ int Server::AddBuiltinServices() {
         LOG(ERROR) << "Fail to add GetJsService";
         return -1;
     }
+    if (AddBuiltinService(new (std::nothrow) GrpcHealthCheckService)) {
+        LOG(ERROR) << "Fail to add GrpcHealthCheckService";
+        return -1;
+    }
     return 0;
 }
 
diff --git a/test/brpc_builtin_service_unittest.cpp 
b/test/brpc_builtin_service_unittest.cpp
index 21f6f502..10e7d2ec 100644
--- a/test/brpc_builtin_service_unittest.cpp
+++ b/test/brpc_builtin_service_unittest.cpp
@@ -53,6 +53,8 @@
 #include "brpc/builtin/common.h"
 #include "brpc/builtin/bad_method_service.h"
 #include "echo.pb.h"
+#include "brpc/grpc_health_check.pb.h"
+#include "json2pb/pb_to_json.h"
 
 DEFINE_bool(foo, false, "Flags for UT");
 BRPC_VALIDATE_GFLAG(foo, brpc::PassValidate);
@@ -552,6 +554,73 @@ TEST_F(BuiltinServiceTest, customized_health) {
     EXPECT_EQ("i'm ok", cntl.response_attachment());
 }
 
+class MyGrpcHealthReporter : public brpc::HealthReporter {
+public:
+    void GenerateReport(brpc::Controller* cntl,
+                        google::protobuf::Closure* done) {
+        grpc::health::v1::HealthCheckResponse response;
+        
response.set_status(grpc::health::v1::HealthCheckResponse_ServingStatus_UNKNOWN);
+
+        if (cntl->response()) {
+            cntl->response()->CopyFrom(response);
+        } else {
+            std::string json;
+            json2pb::ProtoMessageToJson(response, &json);
+            cntl->http_response().set_content_type("application/json");
+            cntl->response_attachment().append(json);
+        }
+        done->Run();
+    }
+};
+
+TEST_F(BuiltinServiceTest, normal_grpc_health) {
+    brpc::ServerOptions opt;
+    ASSERT_EQ(0, _server.Start(9798, &opt));
+
+    grpc::health::v1::HealthCheckResponse response;
+    grpc::health::v1::HealthCheckRequest request;
+    request.set_service("grpc_req_from_brpc");
+    brpc::Controller cntl;
+    brpc::ChannelOptions copt;
+    copt.protocol = "h2:grpc";
+    brpc::Channel chan;
+    ASSERT_EQ(0, chan.Init("127.0.0.1:9798", &copt));
+    grpc::health::v1::Health_Stub stub(&chan);
+    stub.Check(&cntl, &request, &response, NULL);
+    EXPECT_FALSE(cntl.Failed()) << cntl.ErrorText();
+    EXPECT_EQ(response.status(), 
grpc::health::v1::HealthCheckResponse_ServingStatus_SERVING);
+
+    response.Clear();
+    brpc::Controller cntl1;
+    cntl1.http_request().uri() = "/grpc.health.v1.Health/Check";
+    chan.CallMethod(NULL, &cntl1, &request, &response, NULL);
+    EXPECT_FALSE(cntl.Failed()) << cntl.ErrorText();
+    EXPECT_EQ(response.status(), 
grpc::health::v1::HealthCheckResponse_ServingStatus_SERVING);
+}
+
+TEST_F(BuiltinServiceTest, customized_grpc_health) {
+    brpc::ServerOptions opt;
+    MyGrpcHealthReporter hr;
+    opt.health_reporter = &hr;
+    ASSERT_EQ(0, _server.Start(9798, &opt));
+
+    grpc::health::v1::HealthCheckResponse response;
+    grpc::health::v1::HealthCheckRequest request;
+    request.set_service("grpc_req_from_brpc");
+    brpc::Controller cntl;
+
+    brpc::ChannelOptions copt;
+    copt.protocol = "h2:grpc";
+    brpc::Channel chan;
+    ASSERT_EQ(0, chan.Init("127.0.0.1:9798", &copt));
+
+    grpc::health::v1::Health_Stub stub(&chan);
+    stub.Check(&cntl, &request, &response, NULL);
+
+    EXPECT_FALSE(cntl.Failed()) << cntl.ErrorText();
+    EXPECT_EQ(response.status(), 
grpc::health::v1::HealthCheckResponse_ServingStatus_UNKNOWN);
+}
+
 TEST_F(BuiltinServiceTest, status) {
     TestStatus(false);
     TestStatus(true);


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to