Skip to content

Commit 571c7b7

Browse files
authored
Use gRPC naming scheme for name server address (#408)
* Use gRPC naming scheme for name server address * Pin bazel version to LTS 4.2.0
1 parent ab3fdf9 commit 571c7b7

17 files changed

+258
-97
lines changed

.bazelversion

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
4.2.0

example/rocketmq/ExampleProducer.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ int main(int argc, char* argv[]) {
5151
DefaultMQProducer producer("TestGroup");
5252

5353
const char* topic = "cpp_sdk_standard";
54-
const char* name_server = "121.43.42.193:80";
54+
const char* name_server = "mq-inst-1080056302921134-bxuibml7.mq.cn-hangzhou.aliyuncs.com:80";
5555

5656
producer.setNamesrvAddr(name_server);
5757
producer.compressBodyThreshold(256);

example/rocketmq/ExamplePushConsumer.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -49,11 +49,12 @@ int main(int argc, char* argv[]) {
4949
const char* group_id = "GID_cpp_sdk_standard";
5050
const char* topic = "cpp_sdk_standard";
5151
const char* resource_namespace = "MQ_INST_1080056302921134_BXuIbML7";
52+
const char* name_server = "mq-inst-1080056302921134-bxuibml7.mq.cn-hangzhou.aliyuncs.com:80";
5253

5354
DefaultMQPushConsumer push_consumer(group_id);
5455
push_consumer.setResourceNamespace(resource_namespace);
5556
push_consumer.setCredentialsProvider(std::make_shared<ConfigFileCredentialsProvider>());
56-
push_consumer.setNamesrvAddr("121.43.42.193:80");
57+
push_consumer.setNamesrvAddr(name_server);
5758
MessageListener* listener = new SampleMQMessageListener;
5859
push_consumer.setInstanceName("instance_0");
5960
push_consumer.subscribe(topic, "*");

src/main/cpp/client/ClientManagerImpl.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -590,7 +590,8 @@ void ClientManagerImpl::addClientObserver(std::weak_ptr<Client> client) {
590590
void ClientManagerImpl::resolveRoute(const std::string& target_host, const Metadata& metadata,
591591
const QueryRouteRequest& request, std::chrono::milliseconds timeout,
592592
const std::function<void(const std::error_code&, const TopicRouteDataPtr&)>& cb) {
593-
593+
SPDLOG_DEBUG("Name server connection URL: {}", target_host);
594+
SPDLOG_DEBUG("Query route request: {}", request.DebugString());
594595
RpcClientSharedPtr client = getRpcClient(target_host, false);
595596
if (!client) {
596597
SPDLOG_WARN("Failed to create RPC client for name server[host={}]", target_host);

src/main/cpp/rocketmq/ClientImpl.cpp

+21-11
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
#include "InvocationContext.h"
3939
#include "LoggerImpl.h"
4040
#include "MessageAccessor.h"
41+
#include "NamingScheme.h"
4142
#include "Signature.h"
4243
#include "rocketmq/MQMessageExt.h"
4344
#include "rocketmq/MessageListener.h"
@@ -160,7 +161,24 @@ void ClientImpl::getRouteFor(const std::string& topic,
160161
void ClientImpl::setAccessPoint(rmq::Endpoints* endpoints) {
161162
std::vector<std::pair<std::string, std::uint16_t>> pairs;
162163
{
163-
std::vector<std::string> name_server_list = name_server_resolver_->resolve();
164+
std::string naming_address = name_server_resolver_->resolve();
165+
absl::string_view host_port_csv;
166+
167+
if (absl::StartsWith(naming_address, NamingScheme::DnsPrefix)) {
168+
endpoints->set_scheme(rmq::AddressScheme::DOMAIN_NAME);
169+
host_port_csv = absl::StripPrefix(naming_address, NamingScheme::DnsPrefix);
170+
} else if (absl::StartsWith(naming_address, NamingScheme::IPv4Prefix)) {
171+
endpoints->set_scheme(rmq::AddressScheme::IPv4);
172+
host_port_csv = absl::StripPrefix(naming_address, NamingScheme::IPv4Prefix);
173+
} else if (absl::StartsWith(naming_address, NamingScheme::IPv6Prefix)) {
174+
endpoints->set_scheme(rmq::AddressScheme::IPv6);
175+
host_port_csv = absl::StripPrefix(naming_address, NamingScheme::IPv6Prefix);
176+
} else {
177+
SPDLOG_WARN("Unsupported naming scheme");
178+
}
179+
180+
std::vector<std::string> name_server_list = absl::StrSplit(host_port_csv, ',');
181+
164182
for (const auto& name_server_item : name_server_list) {
165183
std::string::size_type pos = name_server_item.rfind(':');
166184
if (std::string::npos == pos) {
@@ -179,20 +197,12 @@ void ClientImpl::setAccessPoint(rmq::Endpoints* endpoints) {
179197
address->set_host(host_port.first);
180198
endpoints->mutable_addresses()->AddAllocated(address);
181199
}
182-
183-
if (MixAll::isIPv4(pairs.begin()->first)) {
184-
endpoints->set_scheme(rmq::AddressScheme::IPv4);
185-
} else if (absl::StrContains(pairs.begin()->first, ':')) {
186-
endpoints->set_scheme(rmq::AddressScheme::IPv6);
187-
} else {
188-
endpoints->set_scheme(rmq::AddressScheme::DOMAIN_NAME);
189-
}
190200
}
191201
}
192202

193203
void ClientImpl::fetchRouteFor(const std::string& topic,
194204
const std::function<void(const std::error_code&, const TopicRouteDataPtr&)>& cb) {
195-
std::string name_server = name_server_resolver_->current();
205+
std::string name_server = name_server_resolver_->resolve();
196206
if (name_server.empty()) {
197207
SPDLOG_WARN("No name server available");
198208
return;
@@ -201,7 +211,7 @@ void ClientImpl::fetchRouteFor(const std::string& topic,
201211
auto callback = [this, topic, name_server, cb](const std::error_code& ec, const TopicRouteDataPtr& route) {
202212
if (ec) {
203213
SPDLOG_WARN("Failed to resolve route for topic={} from {}", topic, name_server);
204-
std::string name_server_changed = name_server_resolver_->next();
214+
std::string name_server_changed = name_server_resolver_->resolve();
205215
if (!name_server_changed.empty()) {
206216
SPDLOG_INFO("Change current name server from {} to {}", name_server, name_server_changed);
207217
}

src/main/cpp/rocketmq/DynamicNameServerResolver.cpp

+3-18
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@
2323
#include <memory>
2424

2525
#include "absl/strings/str_join.h"
26-
#include "spdlog/spdlog.h"
2726

27+
#include "LoggerImpl.h"
2828
#include "SchedulerImpl.h"
2929

3030
ROCKETMQ_NAMESPACE_BEGIN
@@ -69,7 +69,7 @@ DynamicNameServerResolver::DynamicNameServerResolver(absl::string_view endpoint,
6969
std::string(remains.data(), remains.length()));
7070
}
7171

72-
std::vector<std::string> DynamicNameServerResolver::resolve() {
72+
std::string DynamicNameServerResolver::resolve() {
7373
bool fetch_immediately = false;
7474
{
7575
absl::MutexLock lk(&name_server_list_mtx_);
@@ -84,7 +84,7 @@ std::vector<std::string> DynamicNameServerResolver::resolve() {
8484

8585
{
8686
absl::MutexLock lk(&name_server_list_mtx_);
87-
return name_server_list_;
87+
return naming_scheme_.buildAddress(name_server_list_);
8888
}
8989
}
9090

@@ -126,19 +126,4 @@ void DynamicNameServerResolver::shutdown() {
126126
scheduler_->shutdown();
127127
}
128128

129-
std::string DynamicNameServerResolver::current() {
130-
absl::MutexLock lk(&name_server_list_mtx_);
131-
if (name_server_list_.empty()) {
132-
return std::string();
133-
}
134-
135-
std::uint32_t index = index_.load(std::memory_order_relaxed) % name_server_list_.size();
136-
return name_server_list_[index];
137-
}
138-
139-
std::string DynamicNameServerResolver::next() {
140-
index_.fetch_add(1, std::memory_order_relaxed);
141-
return current();
142-
}
143-
144129
ROCKETMQ_NAMESPACE_END
+81
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
#include "NamingScheme.h"
18+
19+
#include <cstdint>
20+
21+
#include "absl/container/flat_hash_map.h"
22+
#include "absl/strings/numbers.h"
23+
#include "absl/strings/str_join.h"
24+
#include "absl/strings/str_split.h"
25+
26+
ROCKETMQ_NAMESPACE_BEGIN
27+
28+
const char* NamingScheme::DnsPrefix = "dns:";
29+
const char* NamingScheme::IPv4Prefix = "ipv4:";
30+
const char* NamingScheme::IPv6Prefix = "ipv6:";
31+
32+
const char* NamingScheme::IPv4Regex =
33+
"(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])";
34+
35+
const char* NamingScheme::IPv6Regex = "((([0-9a-fA-F]){1,4})\\:){7}([0-9a-fA-F]){1,4}";
36+
37+
NamingScheme::NamingScheme() : ipv4_pattern_(IPv4Regex), ipv6_pattern_(IPv6Regex) {
38+
}
39+
40+
std::string NamingScheme::buildAddress(const std::vector<std::string>& list) {
41+
absl::flat_hash_map<std::string, std::uint32_t> ipv4;
42+
absl::flat_hash_map<std::string, std::uint32_t> ipv6;
43+
44+
for (const auto& segment : list) {
45+
std::vector<std::string> host_port = absl::StrSplit(segment, ':');
46+
if (2 != host_port.size()) {
47+
continue;
48+
}
49+
50+
if (re2::RE2::FullMatch(host_port[0], ipv4_pattern_)) {
51+
std::uint32_t port;
52+
if (absl::SimpleAtoi(host_port[1], &port)) {
53+
ipv4.insert_or_assign(host_port[0], port);
54+
}
55+
continue;
56+
}
57+
58+
if (re2::RE2::FullMatch(host_port[0], ipv6_pattern_)) {
59+
std::uint32_t port;
60+
if (absl::SimpleAtoi(host_port[1], &port)) {
61+
ipv6.insert_or_assign(host_port[0], port);
62+
}
63+
continue;
64+
}
65+
66+
// Once we find a domain name record, use it as the final result.
67+
host_port.insert(host_port.begin(), "dns");
68+
return absl::StrJoin(host_port, ":");
69+
}
70+
71+
if (!ipv4.empty()) {
72+
return "ipv4:" + absl::StrJoin(ipv4, ",", absl::PairFormatter(":"));
73+
}
74+
75+
if (!ipv6.empty()) {
76+
return "ipv6:" + absl::StrJoin(ipv4, ",", absl::PairFormatter(":"));
77+
}
78+
return std::string();
79+
}
80+
81+
ROCKETMQ_NAMESPACE_END

src/main/cpp/rocketmq/StaticNameServerResolver.cpp

+11-16
Original file line numberDiff line numberDiff line change
@@ -17,27 +17,22 @@
1717
#include "StaticNameServerResolver.h"
1818

1919
#include "absl/strings/str_split.h"
20-
#include <atomic>
21-
#include <cstdint>
2220

23-
ROCKETMQ_NAMESPACE_BEGIN
24-
25-
StaticNameServerResolver::StaticNameServerResolver(absl::string_view name_server_list)
26-
: name_server_list_(absl::StrSplit(name_server_list, ';')) {
27-
}
21+
#include "LoggerImpl.h"
2822

29-
std::string StaticNameServerResolver::current() {
30-
std::uint32_t index = index_.load(std::memory_order_relaxed) % name_server_list_.size();
31-
return name_server_list_[index];
32-
}
23+
ROCKETMQ_NAMESPACE_BEGIN
3324

34-
std::string StaticNameServerResolver::next() {
35-
index_.fetch_add(1, std::memory_order_relaxed);
36-
return current();
25+
StaticNameServerResolver::StaticNameServerResolver(absl::string_view name_server_list) {
26+
std::vector<std::string> segments = absl::StrSplit(name_server_list, ';');
27+
name_server_address_ = naming_scheme_.buildAddress(segments);
28+
if (name_server_address_.empty()) {
29+
SPDLOG_WARN("Failed to create gRPC naming scheme compliant address from {}",
30+
std::string(name_server_list.data(), name_server_list.length()));
31+
}
3732
}
3833

39-
std::vector<std::string> StaticNameServerResolver::resolve() {
40-
return name_server_list_;
34+
std::string StaticNameServerResolver::resolve() {
35+
return name_server_address_;
4136
}
4237

4338
ROCKETMQ_NAMESPACE_END

src/main/cpp/rocketmq/include/DynamicNameServerResolver.h

+4-5
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include "absl/synchronization/mutex.h"
3131

3232
#include "NameServerResolver.h"
33+
#include "NamingScheme.h"
3334
#include "Scheduler.h"
3435
#include "TopAddressing.h"
3536

@@ -44,11 +45,7 @@ class DynamicNameServerResolver : public NameServerResolver,
4445

4546
void shutdown() override;
4647

47-
std::string current() override LOCKS_EXCLUDED(name_server_list_mtx_);
48-
49-
std::string next() override LOCKS_EXCLUDED(name_server_list_mtx_);
50-
51-
std::vector<std::string> resolve() override LOCKS_EXCLUDED(name_server_list_mtx_);
48+
std::string resolve() override LOCKS_EXCLUDED(name_server_list_mtx_);
5249

5350
void injectHttpClient(std::unique_ptr<HttpClient> http_client);
5451

@@ -69,6 +66,8 @@ class DynamicNameServerResolver : public NameServerResolver,
6966

7067
bool ssl_{false};
7168
std::unique_ptr<TopAddressing> top_addressing_;
69+
70+
NamingScheme naming_scheme_;
7271
};
7372

7473
ROCKETMQ_NAMESPACE_END

src/main/cpp/rocketmq/include/NameServerResolver.h

+1-5
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,7 @@ class NameServerResolver {
3131

3232
virtual void shutdown() = 0;
3333

34-
virtual std::string next() = 0;
35-
36-
virtual std::string current() = 0;
37-
38-
virtual std::vector<std::string> resolve() = 0;
34+
virtual std::string resolve() = 0;
3935
};
4036

4137
ROCKETMQ_NAMESPACE_END
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
#pragma once
18+
19+
#include <string>
20+
#include <vector>
21+
22+
#include "re2/re2.h"
23+
24+
#include "rocketmq/RocketMQ.h"
25+
26+
ROCKETMQ_NAMESPACE_BEGIN
27+
28+
class NamingScheme {
29+
public:
30+
NamingScheme();
31+
32+
std::string buildAddress(const std::vector<std::string>& list);
33+
34+
static const char* DnsPrefix;
35+
static const char* IPv4Prefix;
36+
static const char* IPv6Prefix;
37+
38+
private:
39+
static const char* IPv4Regex;
40+
static const char* IPv6Regex;
41+
42+
re2::RE2 ipv4_pattern_;
43+
re2::RE2 ipv6_pattern_;
44+
};
45+
46+
ROCKETMQ_NAMESPACE_END

0 commit comments

Comments
 (0)