@@ -116,6 +116,7 @@ struct HttpParams {
116116 std::string ca; // ca file
117117 std::string cert; // can be empty
118118 std::string key; // can be empty
119+ unsigned weight = 100 ;
119120
120121 struct Labour : hash_strmap<gold_hash_set<DcompactEtcdExec*> > {
121122 #if 0
@@ -154,6 +155,8 @@ struct HttpParams {
154155 if (!ca.empty () && !Slice (url).starts_with (" https://" )) {
155156 THROW_InvalidArgument (" {url,ca}.url must be https when ca is set" );
156157 }
158+ ROCKSDB_JSON_OPT_PROP (js, weight);
159+ weight = std::max (weight, 1u );
157160 }
158161 else {
159162 THROW_InvalidArgument (" json must be a string or object{url,ca}" );
@@ -184,12 +187,14 @@ struct HttpParams {
184187 }
185188 json ToJson () const {
186189 json js;
187- if (ca.empty ()) {
190+ if (ca.empty () && 100 == weight ) {
188191 js = url;
189192 }
190193 else {
191194 ROCKSDB_JSON_SET_PROP (js, url);
192- ROCKSDB_JSON_SET_PROP (js, ca);
195+ if (!ca.empty ())
196+ ROCKSDB_JSON_SET_PROP (js, ca);
197+ ROCKSDB_JSON_SET_PROP (js, weight);
193198 }
194199 return js;
195200 }
@@ -435,6 +440,8 @@ struct DcompactFeeReport {
435440 }
436441};
437442
443+ ROCKSDB_ENUM_CLASS (LoadBalanceType, int , kRoundRobin , kWeight );
444+
438445class DcompactEtcdExecFactory final : public CompactExecFactoryCommon {
439446 public:
440447 Env* m_env = Env::Default();
@@ -456,6 +463,10 @@ class DcompactEtcdExecFactory final : public CompactExecFactoryCommon {
456463 int overall_timeout = 5 ; // in seconds
457464 int retry_sleep_time = 1 ; // in seconds
458465 std::shared_ptr<DcompactFeeConfig> fee_conf;
466+ valvec<unsigned > m_weight_vec;
467+ mutable std::mt19937_64 m_rand_gen;
468+ unsigned m_weight_sum = 0 ;
469+ LoadBalanceType load_balance = LoadBalanceType::kRoundRobin ;
459470
460471#ifdef TOPLING_DCOMPACT_USE_ETCD
461472 etcd::Client* m_etcd = nullptr ;
@@ -504,7 +515,15 @@ class DcompactEtcdExecFactory final : public CompactExecFactoryCommon {
504515 else {
505516 http_workers.clear (); // if has defined in template, overwrite it
506517 HttpParams::ParseJsonToVec (js[" http_workers" ], &http_workers);
518+ m_weight_vec.reserve (http_workers.size ());
519+ unsigned sum = 0 ;
520+ for (auto & x : http_workers) {
521+ sum += x->weight ;
522+ m_weight_vec.push_back (sum);
523+ }
524+ m_weight_sum = sum;
507525 }
526+ ROCKSDB_JSON_OPT_ENUM (js, load_balance);
508527 ROCKSDB_JSON_OPT_PROP (js, nfs_type);
509528 ROCKSDB_JSON_OPT_PROP (js, nfs_mnt_src);
510529 ROCKSDB_JSON_OPT_PROP (js, nfs_mnt_opt);
@@ -533,14 +552,27 @@ class DcompactEtcdExecFactory final : public CompactExecFactoryCommon {
533552 }
534553 // m_round_robin_idx - start at a random idx
535554 auto seed = std::chrono::system_clock::now ().time_since_epoch ().count ();
536- auto rand = std::mt19937_64 (seed)( );
537- m_round_robin_idx = rand % http_workers.size ();
555+ m_rand_gen = std::mt19937_64 (seed);
556+ m_round_robin_idx = m_rand_gen () % http_workers.size ();
538557 }
539558 ~DcompactEtcdExecFactory () override {
540559#ifdef TOPLING_DCOMPACT_USE_ETCD
541560 delete m_etcd;
542561#endif
543562 }
563+ size_t PickWorker () const {
564+ if (LoadBalanceType::kRoundRobin == load_balance) {
565+ return as_atomic (m_round_robin_idx)
566+ .fetch_add (1 , std::memory_order_relaxed)
567+ % http_workers.size ();
568+ } else {
569+ assert (LoadBalanceType::kWeight == load_balance);
570+ m_stat_map.m_mtx .lock ();
571+ auto rand = m_rand_gen ();
572+ m_stat_map.m_mtx .unlock ();
573+ return lower_bound_a (m_weight_vec, rand % m_weight_sum);
574+ }
575+ }
544576 CompactionExecutor* NewExecutor (const Compaction*) const final ;
545577 const char * Name () const final { return " DcompactEtcd" ; }
546578 void ToJson (const json& dump_options, json& djs, const SidePluginRepo& repo) const final {
745777 meta.estimate_time_us = estimate_time_us;
746778 std::string meta_jstr = meta.ToJsonStr ();
747779 auto t2 = m_env->NowMicros ();
748- size_t nth_http = as_atomic (f->m_round_robin_idx )
749- .fetch_add (1 , std::memory_order_relaxed)
750- % f->http_workers .size ();
751-
780+ size_t nth_http = f->PickWorker ();
752781 m_start_ts = t1;
753782 const HttpParams* worker = f->http_workers [nth_http].get ();
754783 const std::string old_labour_id = m_labour_id;
0 commit comments