2626namespace brpc {
2727namespace policy {
2828
29- static bool server_compare (const WeightedRandomizedLoadBalancer::Server& lhs, const WeightedRandomizedLoadBalancer::Server& rhs) {
30- return (lhs.current_weight_sum < rhs.current_weight_sum );
29+ static bool server_compare (const WeightedRandomizedLoadBalancer::Server& lhs,
30+ const WeightedRandomizedLoadBalancer::Server& rhs) {
31+ return lhs.current_weight_sum < rhs.current_weight_sum ;
3132}
3233
3334bool WeightedRandomizedLoadBalancer::Add (Servers& bg, const ServerId& id) {
@@ -38,15 +39,16 @@ bool WeightedRandomizedLoadBalancer::Add(Servers& bg, const ServerId& id) {
3839 if (!butil::StringToUint (id.tag , &weight) || weight <= 0 ) {
3940 if (FLAGS_default_weight_of_wlb > 0 ) {
4041 LOG (WARNING) << " Invalid weight is set: " << id.tag
41- << " . Now, 'weight' has been set to 'FLAGS_default_weight_of_wlb' by default." ;
42+ << " . Now, 'weight' has been set to "
43+ " FLAGS_default_weight_of_wlb by default." ;
4244 weight = FLAGS_default_weight_of_wlb;
4345 } else {
4446 LOG (ERROR) << " Invalid weight is set: " << id.tag ;
4547 return false ;
4648 }
4749 }
4850 bool insert_server =
49- bg.server_map .emplace (id.id , bg.server_list .size ()).second ;
51+ bg.server_map .emplace (id.id , bg.server_list .size ()).second ;
5052 if (insert_server) {
5153 uint64_t current_weight_sum = bg.weight_sum + weight;
5254 bg.server_list .emplace_back (id.id , weight, current_weight_sum);
@@ -114,6 +116,10 @@ size_t WeightedRandomizedLoadBalancer::RemoveServersInBatch(
114116 return _db_servers.Modify (BatchRemove, servers);
115117}
116118
119+ bool WeightedRandomizedLoadBalancer::IsServerAvailable (SocketId id, SocketUniquePtr* out) {
120+ return Socket::Address (id, out) == 0 && (*out)->IsAvailable ();
121+ }
122+
117123int WeightedRandomizedLoadBalancer::SelectServer (const SelectIn& in, SelectOut* out) {
118124 butil::DoublyBufferedData<Servers>::ScopedPtr s;
119125 if (_db_servers.Read (&s) != 0 ) {
@@ -123,22 +129,49 @@ int WeightedRandomizedLoadBalancer::SelectServer(const SelectIn& in, SelectOut*
123129 if (n == 0 ) {
124130 return ENODATA;
125131 }
132+
133+ butil::FlatSet<SocketId> random_traversed;
126134 uint64_t weight_sum = s->weight_sum ;
127135 for (size_t i = 0 ; i < n; ++i) {
128136 uint64_t random_weight = butil::fast_rand_less_than (weight_sum);
129137 const Server random_server (0 , 0 , random_weight);
130- const auto & server = std::lower_bound (s->server_list .begin (), s->server_list .end (), random_server, server_compare);
138+ const auto & server =
139+ std::lower_bound (s->server_list .begin (), s->server_list .end (),
140+ random_server, server_compare);
131141 const SocketId id = server->id ;
132- if (((i + 1 ) == n // always take last chance
133- || !ExcludedServers::IsExcluded (in.excluded , id))
134- && Socket::Address (id, out->ptr ) == 0
135- && (*out->ptr )->IsAvailable ()) {
136- // We found an available server
142+ random_traversed.insert (id);
143+ if (0 != IsServerAvailable (id, out->ptr )) {
144+ continue ;
145+ }
146+ if (!ExcludedServers::IsExcluded (in.excluded , id)) {
147+ // An available server is found.
137148 return 0 ;
138149 }
139150 }
140- // After we traversed the whole server list, there is still no
141- // available server
151+
152+ if (random_traversed.size () == n) {
153+ // Try to traverse the remaining servers to find an available server.
154+ uint32_t offset = butil::fast_rand_less_than (n);
155+ uint32_t stride = GenRandomStride ();
156+ for (size_t i = 0 ; i < n; ++i) {
157+ offset = (offset + stride) % n;
158+ SocketId id = s->server_list [offset].id ;
159+ if (NULL != random_traversed.seek (id)) {
160+ continue ;
161+ }
162+ if (IsServerAvailable (id, out->ptr )) {
163+ // An available server is found.
164+ return 0 ;
165+ }
166+ }
167+ }
168+
169+ if (NULL != out->ptr ) {
170+ // Use the excluded but available server.
171+ return 0 ;
172+ }
173+
174+ // After traversing the whole server list, no available server is found.
142175 return EHOSTDOWN;
143176}
144177
0 commit comments