flomesh-io / pipy

Pipy is a programmable proxy for the cloud, edge and IoT.
https://flomesh.io/pipy
Other
743 stars 70 forks source link

support Option Configuration for LoadBalancer Object #149

Closed sixinyiyu closed 4 months ago

sixinyiyu commented 1 year ago

Discussion

for example:

_lb = new algo.RoundRobinLoadBalancer(["10.1.1.1:9001", "10.1.1.2:9000"])
_upstream = _lb .next()

$.connect(() => _upstream .id)

Improvement example:

_lb = new algo.RoundRobinLoadBalancer([{"id":"10.1.1.1:9001","weight":40,"options":{"retryCount":1,"retryDelay":1,"connectTimeout":2,"readTimeout":3,"writeTimeout ":2}},{"id":"10.1.1.2:9000","weight":60,"options":{"retryCount":1,"retryDelay":1,"connectTimeout":2,"readTimeout":3,"writeTimeout ":2}}])

_upstream = _lb .next()

$.connect(() => _upstream .id,
 {
      connectTimeout: _upstream.options?.connectTimeout ,
      readTimeout:_upstream.options?.readTimeout 
    }
)
the opiton is map , user can transparent transmission the additional options for next pipeline
the upstream has customized configurations ;
pajama-coder commented 1 year ago

I was actually thinking about the similar thing where "targets" in a LoadBalancer can be of any value type rather than just strings. That means you can have lb.next().id as an object containing whatever info you need for that target. Do I get your point correctly? @sixinyiyu

sixinyiyu commented 1 year ago

I was actually thinking about the similar thing where "targets" in a LoadBalancer can be of any value type rather than just strings. That means you can have lb.next().id as an object containing whatever info you need for that target. Do I get your point correctly

yes, containing whatever info you need for that target ,not just id。

pajama-coder commented 4 months ago

A complete overhaul of the LoadBalancer API has just been committed with 12e3384ea0d8512aef2458c12e56a8bc08347655, covering the requirement from this issue. The targets to the new LoadBalancer object is an array of values of any type. That means it can be as simple as a string like before, or an object defined by user. For each target, weight and capacity can be specified by using user provided callbacks that take in a target value and return the target's weight and capacity. The new API have added some new features as well, such as the capacity of each target limiting the maximum number of connections to a target.

Here's a sample using the new LoadBalancer API:

var lb = new algo.LoadBalancer(
  [
    { addr: 'localhost:8000', w: 0.5 },
    { addr: 'localhost:8001', w: 1.0 },
    { addr: 'localhost:8002', w: 1.0 },
  ], {
    algorithm: 'round-robin',
    weight: t => t.w,
  }
)

var $conn

pipy.listen(8080, $=>$
  .demuxHTTP().to($=>$
    .muxHTTP(() => $conn = lb.allocate()).to($=>$
      .connect(() => $conn.target.addr)
    )
    .onEnd(() => $conn.free())
  )
)

new Array(3).fill().forEach(
  function (_, i) {
    pipy.listen(8000 + i, $=>$
      .serveHTTP(
        new Message(`hi ${i}!\n`)
      )
    )
  }
)

Please feel free to give it a try and give us feedback @sixinyiyu