boost::system::error_code ec;
auto results = resolver.resolve(res_ep.host, "", ec);
if (!ec && !results.empty()) {
+ std::string port_str = std::to_string(res_ep.port);
+ std::string host_port_prefix = res_ep.host + ":" + port_str + ":";
+
for (const auto& entry : results) {
auto ip_str = entry.endpoint().address().to_string();
res_ep.ips.push_back(ip_str);
- ldout(cct, 1) << "endpoint_url=" << ep_url << " resolved to ip=" << ip_str << dendl;
+ res_ep.connect_to_strings.emplace_back(host_port_prefix + ip_str + ":" + port_str);
+ ldout(cct, 2) << "endpoint_url=" << ep_url << " resolved to ip=" << ip_str << dendl;
}
- ldout(cct, 1) << "endpoint=" << ep_url << " resolved to "
+ ldout(cct, 2) << "endpoint=" << ep_url << " resolved to "
<< res_ep.ips.size() << " IP addresses" << dendl;
} else {
ldout(cct, 0) << "WARNING: RGWRESTConn no IP addresses found for endpoint=" << ep_url
<< (ec ? " err=" + ec.message() : "") << dendl;
}
- resolved_endpoints.push_back(std::move(res_ep));
+ resolved_endpoints.emplace(ep_url, std::move(res_ep));
}
}
return *this;
}
+void RGWRESTConn::get_connect_to_mapping_for_url(RGWEndpoint& endpoint)
+{
+ if (!cct->_conf->rgw_rest_conn_connect_to_resolved_ips) {
+ return;
+ }
+
+ std::string connect_to;
+
+ auto it = resolved_endpoints.find(endpoint.get_url());
+ if (it != resolved_endpoints.end() && !it->second.connect_to_strings.empty()) {
+ auto& res_ep = it->second;
+ size_t idx = res_ep.rr_index++;
+ connect_to = res_ep.connect_to_strings[idx % res_ep.connect_to_strings.size()];
+ }
+
+ endpoint.set_connect_to(connect_to);
+}
+
int RGWRESTConn::get_endpoint(RGWEndpoint& endpoint)
{
if (endpoints.empty()) {
ldout(cct, 5) << "ERROR: no valid endpoint" << dendl;
return -EINVAL;
}
- ldout(cct, 20) << "get_endpoint picked url=" << endpoint.get_url()
+
+ get_connect_to_mapping_for_url(endpoint);
+ ldout(cct, 20) << "get_endpoint picked endpoint url=" << endpoint.get_url()
<< " connect_to=" << endpoint.get_connect_to() << dendl;
return 0;
std::string host; // e.g., "s3.abc.com"
int port = -1; // e.g., 443
std::vector<std::string> ips; // the IPs the endpoint resolves to
+ std::vector<std::string> connect_to_strings; // Pre-computed full connect_to strings for each IP
size_t rr_index = 0; // round-robin index for IPs
};
CephContext *cct;
std::vector<std::string> endpoints;
- std::vector<ResolvedEndpoint> resolved_endpoints;
+ std::unordered_map<std::string, ResolvedEndpoint> resolved_endpoints;
endpoint_status_map endpoints_status;
RGWAccessKey key;
std::string self_zone_group;
int get_endpoint(RGWEndpoint& endpoint);
RGWEndpoint get_endpoint();
- const std::vector<ResolvedEndpoint>& get_resolved_endpoints() const { return resolved_endpoints; }
+ const std::unordered_map<std::string, ResolvedEndpoint>& get_resolved_endpoints() const { return resolved_endpoints; }
void set_endpoint_unconnectable(const RGWEndpoint& endpoint);
const std::string& get_self_zonegroup() {
return self_zone_group;
RGWRESTStreamS3PutObj *req, std::string& etag,
ceph::real_time *mtime, optional_yield y);
+ /* pick an IP to 'connect-to' given the endpoint url */
+ void get_connect_to_mapping_for_url(RGWEndpoint& endpoint);
+
struct get_obj_params {
const rgw_owner *uid{nullptr};
const rgw_user *perm_check_uid{nullptr};