From 0e600b94bc8bdffd261f06491e2f7e365787a061 Mon Sep 17 00:00:00 2001 From: lambdaliu Date: Sun, 26 Dec 2021 17:37:42 +0800 Subject: [PATCH 1/4] add quick start example --- examples/quickstart/Makefile | 27 ++++ examples/quickstart/README-zh.md | 53 +++++++ examples/quickstart/consumer.cpp | 258 +++++++++++++++++++++++++++++++ examples/quickstart/provider.cpp | 252 ++++++++++++++++++++++++++++++ 4 files changed, 590 insertions(+) create mode 100644 examples/quickstart/Makefile create mode 100644 examples/quickstart/README-zh.md create mode 100644 examples/quickstart/consumer.cpp create mode 100644 examples/quickstart/provider.cpp diff --git a/examples/quickstart/Makefile b/examples/quickstart/Makefile new file mode 100644 index 0000000..230c88d --- /dev/null +++ b/examples/quickstart/Makefile @@ -0,0 +1,27 @@ +BIT = $(shell getconf LONG_BIT) + +POLARIS_CPP = ../.. +POLARIS_INCL = $(POLARIS_CPP)/include +POLARIS_LIB_DIR = $(POLARIS_CPP)/build$(BIT)/lib +POLARIS_LIB = $(POLARIS_LIB_DIR)/libpolaris_api.a +PROTOBUF_LIB = $(POLARIS_CPP)/third_party/protobuf/build$(BIT)/libprotobuf.a + +CXX = g++ +CXXFLAGS += -g -Wall -Wno-write-strings -Werror -std=c++11 + +SRC = $(wildcard *.cpp) +OBJECTS = $(SRC:%.cpp=%) + +all: $(OBJECTS) + +%: %.cpp $(POLARIS_LIB) + @echo -e Building $< ... + $(CXX) $(CXXFLAGS) -I$(POLARIS_INCL) $< $(POLARIS_LIB) $(PROTOBUF_LIB) -pthread -lz -o $@ + +$(POLARIS_LIB): + @echo build polaris-cpp lib + make -C ${POLARIS_CPP} + +clean: + @echo -e Clean $(OBJECTS) + @-rm -rf $(OBJECTS) diff --git a/examples/quickstart/README-zh.md b/examples/quickstart/README-zh.md new file mode 100644 index 0000000..37ee1f2 --- /dev/null +++ b/examples/quickstart/README-zh.md @@ -0,0 +1,53 @@ +# 快速开始样例 + +## 样例说明 + +样例演示如何使用 polaris-cpp 完成被调端以及主调端应用接入polaris,并完成服务调用流程。 + +consumer: 接收用户tcp请求,通过polaris发现provider服务,并将请求转发给provider处理 +provider:启动服务监听端口,并自身注册到北极星,且开启健康检查 + +## 编译 + +```bash +make clean +make +``` + +编译完成后,会在当前目录生成两个二进制文件,consumer和provider + +## 运行 + +在当前目录下创建配置文件 polaris.yaml,配置文件中配置 Polaris Server 地址。 + +```yaml +global: + serverConnector: + addresses: + - 127.0.0.1:8081 +``` + +执行样例 + +需要在控制台先创建被调服务 Test/quickstart.echo.service + +启动被调方: + +```bash +# 监听地址端口 127.0.0.1:9091 注册到服务 Test/quickstart.echo.service 服务token为xxx +./provider Test quickstart.echo.service xxx 127.0.0.1 9092 +``` + +启动主调方: + +```bash +# 监听地址端口 127.0.0.1:9093 转发请求到被调服务 Test/quickstart.echo.service +./consumer 127.0.0.1 9093 Test quickstart.echo.service +``` + +发送测试请求: + +```bash +# 向consumer监听端口发送hello +echo hello | nc 127.0.0.1 9093 +``` diff --git a/examples/quickstart/consumer.cpp b/examples/quickstart/consumer.cpp new file mode 100644 index 0000000..fa4a25b --- /dev/null +++ b/examples/quickstart/consumer.cpp @@ -0,0 +1,258 @@ +// Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. +// +// Licensed under the BSD 3-Clause License (the "License"); you may not use this file +// except in compliance with the License. You may obtain a copy of the License at +// +// https://opensource.org/licenses/BSD-3-Clause +// +// 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 +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "polaris/consumer.h" + +class ConsumerServer { +public: + ConsumerServer(const std::string& host, int port, const polaris::ServiceKey& provider_service); + + ~ConsumerServer(); + + int Start(); + + void Stop(); + +private: + std::string Proccess(const std::string& message); + + int Send(const std::string& host, int port, const std::string& request, std::string& response); + +private: + std::string host_; + int port_; + polaris::ServiceKey provider_service_; + + std::atomic stop_; + std::unique_ptr accept_thread_; + + std::unique_ptr consumer_; +}; + +bool signal_received = false; +void SignalHandler(int signum) { + std::cout << "Interrupt signal (" << signum << ") received." << std::endl; + signal_received = true; +} + +int main(int argc, char** argv) { + if (argc < 5) { + std::cout << "usage: " << argv[0] << " host port service_namespace service_name" << std::endl; + return -1; + } + // register signal handler + signal(SIGINT, SignalHandler); + + polaris::ServiceKey service_key = {argv[3], argv[4]}; + ConsumerServer server(argv[1], atoi(argv[2]), service_key); + + // 启动服务 + if (server.Start() != 0) { + return -2; + } + + // 循环等待退出信号 + while (!signal_received) { + sleep(1); + } + + // 反注册完成以后再停止服务 + server.Stop(); + + return 0; +} + +ConsumerServer::ConsumerServer(const std::string& host, int port, + const polaris::ServiceKey& provider_service) + : host_(host), port_(port), provider_service_(provider_service), stop_(false) { + consumer_ = std::unique_ptr(polaris::ConsumerApi::CreateWithDefaultFile()); +} + +ConsumerServer::~ConsumerServer() {} + +int ConsumerServer::Start() { + auto sock_listener = socket(AF_INET, SOCK_STREAM, 0); + if (sock_listener < 0) { + std::cerr << "create socket with error: " << errno << std::endl; + return -1; + } + + // address info to bind socket + sockaddr_in server_addr; + server_addr.sin_family = AF_INET; + inet_pton(AF_INET, host_.c_str(), &server_addr.sin_addr); + server_addr.sin_port = htons(port_); + + // bind socket + if (bind(sock_listener, (sockaddr*)&server_addr, sizeof(server_addr)) < 0) { + std::cerr << "bind to " << host_ << ":" << port_ << " failed with error: " << errno + << std::endl; + close(sock_listener); + return -2; + } + + // start listening + if (listen(sock_listener, SOMAXCONN) < 0) { + std::cerr << "listen to " << host_ << ":" << port_ << " failed with error: " << errno + << std::endl; + close(sock_listener); + return -3; + } + std::cout << "listen to " << host_ << ":" << port_ << " success" << std::endl; + + // create accept thread + accept_thread_ = std::unique_ptr(new std::thread([=] { + while (!stop_) { + fd_set set; + FD_ZERO(&set); + FD_SET(sock_listener, &set); + struct timeval timeout; + timeout.tv_sec = 2; + timeout.tv_usec = 0; + int ret = select(sock_listener + 1, &set, NULL, NULL, &timeout); + if (ret <= 0) { + continue; + } + sockaddr_in client_addr; + socklen_t client_addr_size = sizeof(client_addr); + int sock_client; + if ((sock_client = accept(sock_listener, (sockaddr*)&client_addr, &client_addr_size)) < 0) { + std::cerr << "accept connection failed with error:" << errno << std::endl; + continue; + } + + // 处理客户端连接 + std::async(std::launch::async, [=] { + char buffer[1024]; + auto bytes = recv(sock_client, buffer, sizeof(buffer), 0); + if (bytes <= 0) { + std::cerr << "received message failed: " << errno << std::endl; + close(sock_client); + return; + } + std::string response = Proccess(buffer); + bytes = send(sock_client, response.data(), response.size(), 0); + close(sock_client); + + if (bytes < 0) { + std::cerr << "send response failed: " << errno << std::endl; + } + }); + } + close(sock_listener); + })); + + return 0; +} + +std::string ConsumerServer::Proccess(const std::string& message) { + // 获取provider服务实例 + polaris::GetOneInstanceRequest instance_requst(provider_service_); + polaris::Instance instance; + auto ret_code = consumer_->GetOneInstance(instance_requst, instance); + if (ret_code != polaris::kReturnOk) { + std::cout << "get one instance for service with error: " + << polaris::ReturnCodeToMsg(ret_code).c_str() << std::endl; + } + + // 调用业务 + std::string response; + auto begin_time = std::chrono::steady_clock::now(); + int send_ret = Send(instance.GetHost(), instance.GetPort(), message, response); + auto end_time = std::chrono::steady_clock::now(); + + // 上报调用结果 + polaris::ServiceCallResult result; + result.SetServiceNamespace(provider_service_.namespace_); + result.SetServiceName(provider_service_.name_); + result.SetInstanceId(instance.GetId()); + result.SetDelay( + std::chrono::duration_cast(end_time - begin_time).count()); + result.SetRetCode(send_ret); + result.SetRetStatus(send_ret >= 0 ? polaris::kCallRetOk : polaris::kCallRetError); + if ((ret_code = consumer_->UpdateServiceCallResult(result)) != polaris::kReturnOk) { + std::cout << "update call result for instance with error:" + << " msg:" << polaris::ReturnCodeToMsg(ret_code).c_str() << std::endl; + } + + if (send_ret) { + response = + "send msg to " + instance.GetHost() + ":" + std::to_string(instance.GetPort()) + " failed"; + } + std::cout << response << std::endl; + return response; +} + +int ConsumerServer::Send(const std::string& host, int port, const std::string& request, + std::string& response) { + // create a socket + int sock_fd = socket(AF_INET, SOCK_STREAM, 0); + if (sock_fd < 0) { + std::cout << "create socket failed: " << errno << std::endl; + return -1; + } + + sockaddr_in server_addr; + server_addr.sin_family = AF_INET; + inet_pton(AF_INET, host.c_str(), &server_addr.sin_addr); + server_addr.sin_port = htons(port); + + if (connect(sock_fd, (sockaddr*)&server_addr, sizeof(server_addr)) < 0) { + std::cerr << "connection establish failed: " << errno << std::endl; + close(sock_fd); + return -2; + } + + // send the message + int bytes_send = send(sock_fd, request.data(), request.length(), 0); + if (bytes_send < 0) { + std::cerr << "send message failed: " << errno << std::endl; + close(sock_fd); + return -3; + } + + char buffer[4096]; + int bytes_recv = recv(sock_fd, &buffer, sizeof(buffer), 0); + if (bytes_recv <= 0) { + std::cerr << "receive message failed: " << errno << std::endl; + close(sock_fd); + return -4; + } + + close(sock_fd); + response = std::string(buffer); + return 0; +} + +void ConsumerServer::Stop() { + stop_ = true; + if (accept_thread_) { + accept_thread_->join(); + } +} \ No newline at end of file diff --git a/examples/quickstart/provider.cpp b/examples/quickstart/provider.cpp new file mode 100644 index 0000000..f91ec3b --- /dev/null +++ b/examples/quickstart/provider.cpp @@ -0,0 +1,252 @@ +// Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. +// +// Licensed under the BSD 3-Clause License (the "License"); you may not use this file +// except in compliance with the License. You may obtain a copy of the License at +// +// https://opensource.org/licenses/BSD-3-Clause +// +// 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 +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "polaris/provider.h" + +class ProviderServer { +public: + ProviderServer(const std::string& service_namespace, const std::string& service_name, + const std::string& service_token, const std::string& host, int port); + + ~ProviderServer(); + + // 启动服务 + int Start(); + + // 注册服务实例 + int Register(); + + // 反注册服务实例 + void Deregister(); + + // 停止服务 + void Stop(); + +private: + std::string service_namespace_; + std::string service_name_; + std::string service_token_; + std::string host_; + int port_; + std::string instance_id_; + + std::atomic stop_; + std::unique_ptr accept_thread_; + + std::unique_ptr provider_; + std::unique_ptr heartbeat_thread_; +}; + +bool signal_received = false; +void SignalHandler(int signum) { + std::cout << "Interrupt signal (" << signum << ") received." << std::endl; + signal_received = true; +} + +constexpr auto kHeartbeatTtl = 5; + +int main(int argc, char** argv) { + if (argc < 6) { + std::cout << "usage: " << argv[0] << " service_namespace service_name service_token host port" + << std::endl; + return -1; + } + // 注册信号 + signal(SIGINT, SignalHandler); + + ProviderServer server(argv[1], argv[2], argv[3], argv[4], atoi(argv[5])); + + // 先启动服务 + if (server.Start() != 0) { + return -2; + } + + // 启动服务成功以后 再注册服务实例, 并开启心跳上报 + if (server.Register() != 0) { + return -3; + } + + // 循环等待退出信号 + while (!signal_received) { + sleep(1); + } + + // 先反注册实例 + server.Deregister(); + + // 反注册完成以后再停止服务 + server.Stop(); + + return 0; +} + +ProviderServer::ProviderServer(const std::string& service_namespace, + const std::string& service_name, const std::string& service_token, + const std::string& host, int port) + : service_namespace_(service_namespace), service_name_(service_name), + service_token_(service_token), host_(host), port_(port), stop_(false) {} + +ProviderServer::~ProviderServer() { Stop(); } + +int ProviderServer::Start() { + // create a socket + auto sock_listener = socket(AF_INET, SOCK_STREAM, 0); + if (sock_listener < 0) { + std::cerr << "create socket with error: " << errno << std::endl; + return -1; + } + + // address info to bind socket + sockaddr_in server_addr; + server_addr.sin_family = AF_INET; + inet_pton(AF_INET, host_.c_str(), &server_addr.sin_addr); + server_addr.sin_port = htons(port_); + + // bind socket + if (bind(sock_listener, (sockaddr*)&server_addr, sizeof(server_addr)) < 0) { + std::cerr << "bind to " << host_ << ":" << port_ << " failed with error: " << errno + << std::endl; + close(sock_listener); + return -2; + } + + // start listening + if (listen(sock_listener, SOMAXCONN) < 0) { + std::cerr << "listen to " << host_ << ":" << port_ << " failed with error: " << errno + << std::endl; + close(sock_listener); + return -3; + } + std::cout << "listen to " << host_ << ":" << port_ << " success" << std::endl; + + // create accept thread + accept_thread_ = std::unique_ptr(new std::thread([=] { + while (!stop_) { + fd_set set; + FD_ZERO(&set); + FD_SET(sock_listener, &set); + struct timeval timeout; + timeout.tv_sec = 2; + timeout.tv_usec = 0; + int ret = select(sock_listener + 1, &set, NULL, NULL, &timeout); + if (ret <= 0) { + continue; + } + sockaddr_in client_addr; + socklen_t client_addr_size = sizeof(client_addr); + int sock_client; + if ((sock_client = accept(sock_listener, (sockaddr*)&client_addr, &client_addr_size)) < 0) { + std::cerr << "accept connection failed with error:" << errno << std::endl; + continue; + } + + // 处理客户端连接 + std::async(std::launch::async, [=] { + char buffer[1024]; + auto bytes = recv(sock_client, buffer, sizeof(buffer), 0); + if (bytes <= 0) { + std::cerr << "received message failed: " << errno << std::endl; + close(sock_client); + return; + } + + std::string response = + "response form " + host_ + ":" + std::to_string(port_) + " echo " + buffer; + + bytes = send(sock_client, response.data(), response.size(), 0); + close(sock_client); + + if (bytes < 0) { + std::cerr << "send response failed: " << errno << std::endl; + } + }); + } + close(sock_listener); + })); + + return 0; +} + +int ProviderServer::Register() { + provider_ = std::unique_ptr(polaris::ProviderApi::CreateWithDefaultFile()); + if (provider_ == nullptr) { + return -1; + } + polaris::InstanceRegisterRequest register_req(service_namespace_, service_name_, service_token_, + host_, port_); + // 开启健康检查 + register_req.SetHealthCheckFlag(true); + register_req.SetHealthCheckType(polaris::kHeartbeatHealthCheck); + register_req.SetTtl(kHeartbeatTtl); + + // 注册实例 + auto ret_code = provider_->Register(register_req, instance_id_); + if (ret_code != polaris::kReturnOk && ret_code != polaris::kReturnExistedResource) { + std::cout << "register instance with error:" << polaris::ReturnCodeToMsg(ret_code).c_str() + << std::endl; + return ret_code; + } + + // 启动心跳上报线程 + heartbeat_thread_ = std::unique_ptr(new std::thread([=] { + while (!signal_received) { // 循环上报心跳 + polaris::InstanceHeartbeatRequest heartbeat_req(service_token_, instance_id_); + auto ret_code = provider_->Heartbeat(heartbeat_req); + if (ret_code != polaris::kReturnOk) { + std::cout << "instance heartbeat with error:" << polaris::ReturnCodeToMsg(ret_code).c_str() + << std::endl; + sleep(1); + continue; + } + sleep(kHeartbeatTtl); + } + })); + return 0; +} + +void ProviderServer::Deregister() { + if (heartbeat_thread_) { + heartbeat_thread_->join(); + } + // 反注册实例 + polaris::InstanceDeregisterRequest deregister_req(service_token_, instance_id_); + auto ret_code = provider_->Deregister(deregister_req); + if (ret_code != polaris::kReturnOk) { + std::cout << "instance deregister with error:" << polaris::ReturnCodeToMsg(ret_code).c_str() + << std::endl; + } +} + +void ProviderServer::Stop() { + stop_ = true; + if (accept_thread_) { + accept_thread_->join(); + accept_thread_ = nullptr; + } +} From 128aba0397fcf5847da81d85974428d5c5b5e04a Mon Sep 17 00:00:00 2001 From: springliao Date: Thu, 24 Feb 2022 19:48:48 +0800 Subject: [PATCH 2/4] =?UTF-8?q?feat:=20=E6=94=AF=E6=8C=81=E5=9F=9F?= =?UTF-8?q?=E5=90=8D=E8=A7=A3=E6=9E=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- polaris/grpc/http2.cpp | 45 +++++++++++++++++++++++++++++----- test/grpc/grpc_client_test.cpp | 4 +-- 2 files changed, 41 insertions(+), 8 deletions(-) diff --git a/polaris/grpc/http2.cpp b/polaris/grpc/http2.cpp index 12bf7cf..cc207cb 100644 --- a/polaris/grpc/http2.cpp +++ b/polaris/grpc/http2.cpp @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -347,6 +348,34 @@ Http2Client::~Http2Client() { } } +// TryLookup 尝试进行 host 解析 +// step 1. 判断当前的 host 是否是域名 +// step 2. 不是域名,则直接返回 +// step 3. 是域名,进行一次域名解析,然后从返回的IPList中随机选取一个IP进行链接 +static std::string TryLookup(const std::string& address) { + POLARIS_LOG(LOG_INFO, "try lookup address=[%s]", address.c_str()); + struct hostent* host = gethostbyname(address.c_str()); + if (!host) { + POLARIS_LOG(LOG_ERROR, "try lookup address=[%s] error, maybe address is ip", address.c_str()); + return address; + } + + POLARIS_LOG(LOG_TRACE, "address=[%s] type: [%s]", address.c_str(), + (host->h_addrtype == AF_INET) ? "AF_INET" : "AF_INET6"); + + int total = sizeof(host->h_addr_list); + if (total < 1) { + return address; + } + + std::string target_address = inet_ntoa(*(struct in_addr*)host->h_addr_list[0]); + + POLARIS_LOG(LOG_TRACE, "address=[%s] select one by random [%s]", address.c_str(), + target_address.c_str()); + + return target_address; +} + // 向指定地址发起非阻塞连接 static int TryConnectTo(const std::string& host, int port, int& fd) { if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { @@ -368,6 +397,7 @@ static int TryConnectTo(const std::string& host, int port, int& fd) { bzero(static_cast(&addr), sizeof(struct sockaddr_in)); addr.sin_family = AF_INET; addr.sin_port = htons(port); + if (inet_pton(AF_INET, host.c_str(), &addr.sin_addr) != 1) { return -1; } @@ -375,23 +405,26 @@ static int TryConnectTo(const std::string& host, int port, int& fd) { } bool Http2Client::ConnectTo(const std::string& host, int port) { + std::string server_ip = TryLookup(host); + POLARIS_ASSERT(state_ == kConnectionInit); - GRPC_LOG(LOG_INFO, "try to nonblocking connect to server[%s:%d]", host.c_str(), port); + GRPC_LOG(LOG_INFO, "try to nonblocking connect to server[%s:%d]", server_ip.c_str(), port); int retcode = TryConnectTo(host, port, fd_); if (retcode == 0) { // 异步连接立即成功了,一般本地连接才有可能发生。 - GRPC_LOG(LOG_TRACE, "nonblocking connect to service[%s:%d] success immediately", host.c_str(), - port); + GRPC_LOG(LOG_TRACE, "nonblocking connect to service[%s:%d] success immediately", + server_ip.c_str(), port); state_ = kConnectionConnecting; // 即使立刻连接成功了也放在epoll写事件中去更新状态 } else if (errno == EINPROGRESS) { // tcp connect return -1 state_ = kConnectionConnecting; GRPC_LOG(LOG_TRACE, "nonblocking connect to server[%s:%d] with connection in progress", - host.c_str(), port); + server_ip.c_str(), port); retcode = 0; } else { state_ = kConnectionDisconnected; - GRPC_LOG(LOG_ERROR, "nonblocking connect to %s:%d with error: %d", host.c_str(), port, errno); + GRPC_LOG(LOG_ERROR, "nonblocking connect to %s:%d with error: %d", server_ip.c_str(), port, + errno); } - current_server_ = host + ":" + StringUtils::TypeToStr(port); + current_server_ = server_ip + ":" + StringUtils::TypeToStr(port); return retcode == 0; } diff --git a/test/grpc/grpc_client_test.cpp b/test/grpc/grpc_client_test.cpp index fc7ab29..038530a 100644 --- a/test/grpc/grpc_client_test.cpp +++ b/test/grpc/grpc_client_test.cpp @@ -15,9 +15,9 @@ // language governing permissions and limitations under the License. // -#include "grpc/client.h" - #include +#include "grpc/client.h" +#include "grpc/http2.cpp" #include "mock/fake_net_server.h" #include "reactor/reactor.h" From e3711aae6d81b6b23a240da403c63c563f534789 Mon Sep 17 00:00:00 2001 From: springliao Date: Thu, 24 Feb 2022 19:51:38 +0800 Subject: [PATCH 3/4] =?UTF-8?q?refactor:=20=E8=B0=83=E6=95=B4TryLookup?= =?UTF-8?q?=E6=97=A5=E5=BF=97=E7=AD=89=E7=BA=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- polaris/grpc/http2.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/polaris/grpc/http2.cpp b/polaris/grpc/http2.cpp index cc207cb..47515b1 100644 --- a/polaris/grpc/http2.cpp +++ b/polaris/grpc/http2.cpp @@ -353,15 +353,15 @@ Http2Client::~Http2Client() { // step 2. 不是域名,则直接返回 // step 3. 是域名,进行一次域名解析,然后从返回的IPList中随机选取一个IP进行链接 static std::string TryLookup(const std::string& address) { - POLARIS_LOG(LOG_INFO, "try lookup address=[%s]", address.c_str()); + GRPC_LOG(LOG_DEBUG, "try lookup address=[%s]", address.c_str()); struct hostent* host = gethostbyname(address.c_str()); if (!host) { - POLARIS_LOG(LOG_ERROR, "try lookup address=[%s] error, maybe address is ip", address.c_str()); + GRPC_LOG(LOG_ERROR, "try lookup address=[%s] error, maybe address is ip", address.c_str()); return address; } - POLARIS_LOG(LOG_TRACE, "address=[%s] type: [%s]", address.c_str(), - (host->h_addrtype == AF_INET) ? "AF_INET" : "AF_INET6"); + GRPC_LOG(LOG_DEBUG, "address=[%s] type: [%s]", address.c_str(), + (host->h_addrtype == AF_INET) ? "AF_INET" : "AF_INET6"); int total = sizeof(host->h_addr_list); if (total < 1) { @@ -370,8 +370,8 @@ static std::string TryLookup(const std::string& address) { std::string target_address = inet_ntoa(*(struct in_addr*)host->h_addr_list[0]); - POLARIS_LOG(LOG_TRACE, "address=[%s] select one by random [%s]", address.c_str(), - target_address.c_str()); + GRPC_LOG(LOG_TRACE, "address=[%s] select one by random [%s]", address.c_str(), + target_address.c_str()); return target_address; } From 2e54e9516dee7f1aaf590fb575eed343c59d9068 Mon Sep 17 00:00:00 2001 From: springliao Date: Thu, 10 Mar 2022 19:29:33 +0800 Subject: [PATCH 4/4] =?UTF-8?q?feat:=20=E6=94=AF=E6=8C=81=E6=AD=A3?= =?UTF-8?q?=E5=88=99=E8=A1=A8=E8=BE=BE=E5=BC=8F=E5=88=A4=E6=96=AD=E6=98=AF?= =?UTF-8?q?=E5=90=A6=E6=98=AF=E5=9F=9F=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- polaris/grpc/http2.cpp | 12 ++++++++++ test/grpc/domain_test.cpp | 49 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+) create mode 100644 test/grpc/domain_test.cpp diff --git a/polaris/grpc/http2.cpp b/polaris/grpc/http2.cpp index 47515b1..1388807 100644 --- a/polaris/grpc/http2.cpp +++ b/polaris/grpc/http2.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -354,6 +355,17 @@ Http2Client::~Http2Client() { // step 3. 是域名,进行一次域名解析,然后从返回的IPList中随机选取一个IP进行链接 static std::string TryLookup(const std::string& address) { GRPC_LOG(LOG_DEBUG, "try lookup address=[%s]", address.c_str()); + + std::string domain_reg = + "^[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+\\.?$"; + re2::RE2 domain(domain_reg.c_str()); + bool is_domain = domain.ok() && re2::RE2::PartialMatch(address.c_str(), domain); + + // 使用正则表达式判断是否是域名, 不是域名,直接返回 address + if (!is_domain) { + return address; + } + struct hostent* host = gethostbyname(address.c_str()); if (!host) { GRPC_LOG(LOG_ERROR, "try lookup address=[%s] error, maybe address is ip", address.c_str()); diff --git a/test/grpc/domain_test.cpp b/test/grpc/domain_test.cpp new file mode 100644 index 0000000..2fd0632 --- /dev/null +++ b/test/grpc/domain_test.cpp @@ -0,0 +1,49 @@ +// Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. +// +// Licensed under the BSD 3-Clause License (the "License"); you may not use +// this file +// except in compliance with the License. You may obtain a copy of the License +// at +// +// https://opensource.org/licenses/BSD-3-Clause +// +// 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 "grpc/buffer.h" + +#include +#include +#include +#include + +namespace polaris { +namespace grpc { + +class GrpcDomainTest : public ::testing::Test { +protected: + virtual void SetUp() {} + + virtual void TearDown() {} + +protected: +}; + +TEST_F(GrpcDomainTest, DomainJudge) { + std::string domain_reg = "^[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+\\.?$"; + re2::RE2 regex_(domain_reg.c_str()); + ASSERT_TRUE((regex_).ok()); + std::string str_1 = "baidu.com"; + ASSERT_TRUE(re2::RE2::PartialMatch(str_1.c_str(), regex_)); + + std::string str_2 = "polaris.default.svc.local"; + ASSERT_TRUE(re2::RE2::PartialMatch(str_2.c_str(), regex_)); +} + +} // namespace grpc +} // namespace polaris \ No newline at end of file