diff --git a/src/shrpx_worker.cc b/src/shrpx_worker.cc index b04d19c8..2226bf43 100644 --- a/src/shrpx_worker.cc +++ b/src/shrpx_worker.cc @@ -360,6 +360,10 @@ void Worker::replace_downstream_config( addr.seq = seq++; } + util::shuffle(std::begin(shared_addr->addrs), + std::end(shared_addr->addrs), randgen_, + [](auto i, auto j) { std::swap((*i).seq, (*j).seq); }); + if (shared_addr->affinity.type == SessionAffinity::NONE) { std::map wgs; size_t num_wgs = 0; diff --git a/src/util.h b/src/util.h index bc271f43..f17154ec 100644 --- a/src/util.h +++ b/src/util.h @@ -879,6 +879,26 @@ void random_bytes(OutputIt first, OutputIt last, Generator &gen) { std::generate(first, last, [&dis, &gen]() { return dis(gen); }); } +// Shuffles the range [|first|, |last|] by calling swap function |fun| +// for each pair. |fun| takes 2 RandomIt iterators. If |fun| is +// noop, no modification is made. +template +void shuffle(RandomIt first, RandomIt last, Generator &&gen, SwapFun fun) { + auto len = std::distance(first, last); + if (len < 2) { + return; + } + + for (unsigned int i = 0; i < static_cast(len - 1); ++i) { + auto dis = std::uniform_int_distribution(i, len - 1); + auto j = dis(gen); + if (i == j) { + continue; + } + fun(first + i, first + j); + } +} + template OutputIterator copy_lit(OutputIterator it, CharT (&s)[N]) { return std::copy_n(s, N - 1, it);