cloudflare / pingora

A library for building fast, reliable and evolvable network services.
Apache License 2.0
20.21k stars 1.1k forks source link

BackendSelection improvements for least connections #269

Open Object905 opened 3 weeks ago

Object905 commented 3 weeks ago

Hi. I wanted to implement my own backend selection (basically least connections), but faced some inconvenience and issues.

To address Inconvenience: Moved BackendIter bound into BackendSelection::Iter. It was only used with this bound everywhere anyway, even docs says that Iter should be BackendIter. Can't see any reason why it's like that. Tested against rust 1.72 to verify that it satisfies msrv. It doesn't break any existing code, just makes bound S::Iter: BackendIter redundant.

Issues:

  1. selector field in LoadBalancer is private, but I needed to access it to share some handle that will be used to notify selector of pending upstream requests. It's possible to achieve this by other means (either global state, but then it's hard to share code, or more api churn and changing public interfaces, which I don't want to do here).

  2. When backends are updated new instance of BackendSelection is created and replaced, but to keep handle from previous selector I had to resort to global state. So I added previous: Option<Arc<Self>> argument that will be passed in LoadBalancer::update, so it's possible to keep provided handle or some other state. This is somewhat breaking change.

Related Issue: https://github.com/cloudflare/pingora/issues/144 Maybe later after my experiments will make a PR for least connections.