A few comments (mainly on the proposal to piggy-back the load info header in 
the responses) :
*) The mechanism may not work in certain setups of the SLB (e.g DSR)*) For TLS, 
I presume this proposal assumes that the connections are terminated at the SLB 
layer?*) How does the proposal apply to newer protocols like SPDY, HTTP/2? (or) 
the request/responses are streams within a connection, and AFAIK, headers like 
Connection/Keep-Alive are no longer valid with SPDY (and perhaps, even with 
HTTP/2)
Thanks,
Sudheer 


     On Saturday, May 2, 2015 2:28 PM, Leif Hedstrom <zw...@apache.org> wrote:
   

 I’m Cc: this to d...@trafficserver.apache.org, since I think this is something 
some of our dev would be interested in. There are a few other replies to this 
thread already, which can be seen on the archives.

As has been mentioned in another reply, I think the header name ought to be 
something ^X- (see RFC 6648). Backend-Info or Backend-Capacity-Info or some 
such?

Cheers,

— leif



> On Apr 29, 2015, at 10:54 PM, Jim Riggs <apache-li...@riggs.me> wrote:
> 
> [ Long message and proposal follows. Bear with me. There are a lot of words, 
> but that is because we need a lot of help/input! ;-) ]
> 
> So, this has come up in the past several times, and we discussed it again 
> this year at ApacheCon: How do we get the load balancer to make smarter, more 
> informed decisions about where to send traffic?
> 
> The different LB methods provide some different attempts at balancing 
> traffic, but ultimately none of them is "smart" about its decision. Other 
> than a member being in error state, the balancer makes its decision solely 
> based on configuration (LB set, factor, etc.) and its own knowledge of the 
> member (e.g. requests, bytes). What we have often discussed is a way to get 
> some type of health/load/capacity information from the backend to make 
> informed balancing decisions.
> 
> One method is to use health checks (a la haproxy, AWS ELBs, etc.) that 
> request one or more URLs and the response code/time indicates whether or not 
> the service is up and available, allowing more proactive decisions. While 
> this is better than our current state of reactively marking members in error 
> state based on failed requests, it still provides a limited view of the 
> health/state of the backend.
> 
> We have also discussed implementing a way for backends to communicate a 
> magical "load" number to the front end to take into account as it balances 
> traffic. This would give a much better view into the backend's state, but 
> requires some way to come up with this calculation that each backend 
> system/server/service/app must provide. This then has to be implemented in 
> all the various backends (e.g. httpd, tomcat, php-fpm, unicorn, mongrel, 
> etc., etc.), probably a hard sell to all of those projects. And, the front 
> end would have limited control over what that number means or how to use it.
> 
> During JimJag's balancer talk at ApacheCon this year, he brought up this 
> issue of "better, more informed" decision making again. I put some thought 
> into it that night and came up with some ideas. Jim, Covener, Trawick, 
> Ruggeri, and I then spent some time over the next couple of days talking it 
> through and fleshing out some of the details.
> 
> Based on all of that, below is what I am proposing. I have some initial code 
> that I am working on to implement the different pieces of this, and I will 
> put them up in bugz or somewhere when they're a little less rudimentary.
> 
> --
> 
> Our hope is to create a general standard that can be used by various 
> projects, products, proxies, servers, etc., to have a more consistent way for 
> a load balancer to request and receive useful internal state information from 
> its backend nodes. This information can then be used by the *frontend* 
> software/admin (this is the main change from what we have discussed before) 
> to calculate a load factor appropriate for each backend node.
> 
> This communication uses a new, standard HTTP header, "X-Backend-Info", that 
> takes this form in RFC2616 BNF:
> 
>    backend-info  = "version" "=" numeric-entry
>                    [
>                      *LWS "," *LWS
>                      #( numeric-entry | string-entry )
>                    ]
> 
>    numeric-entry = numeric-field "=" ( float | <"> float <"> )
>                    ; that is, numbers may optionally be enclosed in
>                    ; quotation marks
> 
>    float        = 1*DIGIT [ "." 1*DIGIT ]
> 
>    numeric-field = "workers-max"
>                    ; maximum number of workers the backend supports
>                  | "workers-used"
>                    ; current number of used/busy workers
>                  | "workers-allocated"
>                    ; current number of allocated/ready workers
>                  | "workers-free"
>                    ; current number of workers available for use
>                    ; (generally the difference between workers-max and
>                    ; workers-used, though some implementations may have
>                    ; a different notion)
>                  | "uptime"
>                    ; number of seconds the backend has been running
>                  | "requests"
>                    ; number of requests the backend has processed
>                  | "memory-max"
>                    ; total amount of memory available in bytes
>                  | "memory-used"
>                    ; amount of used memory in bytes
>                  | "memory-allocated"
>                    ; amount of allocated/committed memory in bytes
>                  | "memory-free"
>                    ; amount of memory available for use (generally
>                    ; the difference between memory-max and memory-used,
>                    ; though some implementations may have a different
>                    ; notion)
>                  | "load-current"
>                    ; the (subjective) current load for the backend
>                  | "load-5"
>                    ; the (subjective) 5-minute load for the backend
>                  | "load-15"
>                    ; the (subjective) 15-minute load for the backend
> 
>    string-entry  = string-field "=" ( token | quoted-string )
> 
>    string-field  = "provider"
>                    ; informational description of backend information
>                    ; provider (module, container, subsystem, app, etc.)
> 
> 
> As used here, "worker" is an overloaded term whose precise meaning is 
> backend-dependent. It might refer to processes, threads, pipelines, or 
> whatever the backend system/server/service/app uses to measure or limit its 
> number of active, processing connections.
> 
> The process-flow looks like this:
> 
> 1. The frontend (periodically based on time or requests, or on demand) as 
> part of either (1) a normal proxied request or (2) a dedicated health check 
> adds an "X-Backend-Info" request header to a backend request, informing the 
> backend that it wants node state information. I.e.:
> 
>    X-Backend-Info: version=1.0
> 
> 2. The backend node receives a request with an "X-Backend-Info" header 
> specifying a version it supports.
> 
> 3. A supporting backend node SHOULD insert one or more "X-Backend-Info" 
> response headers with any subset of the backend-info fields that it supports, 
> including the required "version" field. The version of information provided 
> MUST be less than or equal to the version requested. (The fields are 
> standardized so that various frontends know what to expect, rather than each 
> backend system/server/service/app creating its own fields/values.) E.g.:
> 
>    X-Backend-Info: version=1.0, provider="Backend X", workers-max=1000,
>                    workers-used=517, workers-free=483, uptime=19234,
>                    requests=85939
> 
> 4. The backend MUST add the "X-Backend-Info" token to the "Connection" 
> response header, making it a hop-by-hop field that is removed by the frontend 
> from the downstream response (RFC2616 14.10 and RFC7230 6.1). [Note there 
> appears to be an httpd bug here that I intend to submit and that needs to be 
> addressed.]
> 
>    Connection: X-Backend-Info
> 
> 5. The frontend parses the backend-info entries in the received 
> "X-Backend-Info" response header. The values are then used as part of either 
> an internal or an administrator-specified calculation to determine the load 
> factor or weight of that node for subsequent requests.
> 
> 6. The frontend MUST remove the "X-Backend-Info" hop-to-hop response header 
> per RFCs.
> 
> --
> 
> As for httpd implementation, this has two pieces. The first is when httpd is 
> used as a backend node behind a load balancer and must provide X-Backend-Info 
> response data. For this, I have created a module tentatively named 
> mod_proxy_backend_info that does nothing except insert an output filter to 
> populate the response header with version, provider, workers-*, request, 
> uptime, and load-* values when the request header is present. Here is an 
> example request-response:
> 
> % curl -v -H 'X-Backend-Info: version=1.0' http://localhost/
> *  Trying 127.0.0.1...
> * Connected to localhost (127.0.0.1) port 80 (#0)
>> GET / HTTP/1.1
>> User-Agent: curl/7.41.0
>> Host: localhost
>> Accept: */*
>> X-Backend-Info: version=1.0
>> 
> < HTTP/1.1 200 OK
> < Date: Thu, 30 Apr 2015 04:32:08 GMT
> < Server: Apache/2.4.9 (Unix) PHP/5.5.14
> < Last-Modified: Wed, 15 Apr 2015 14:04:54 GMT
> < ETag: "2d-513c3d4d78d80"
> < Accept-Ranges: bytes
> < Content-Length: 45
> < X-Backend-Info: version=1.0, provider="mod_proxy_backend_info [Apache/2.4.9 
> (Unix) PHP/5.5.14]", workers-max=256, workers-busy=1, workers-ready=4, 
> workers-free=255, uptime=1448, requests=3, load-current=1.737305, 
> load-5=1.733887, load-15=1.668457
> < Connection: X-Backend-Info
> < Content-Type: text/html
> <
> <html><body><h1>It works!</h1></body></html>
> 
> 
> The second piece is when httpd is used as the load balancer. For this, I have 
> created a module tentatively named mod_lbmethod_bybackendinfo that will:
> 
> 1. Periodically (based on elapsed time, number of requests, or both since 
> last update) insert the X-Backend-Info request header into a proxied request.
> 
> 2. Parse and remove the X-Backend-Info response header.
> 
> 3. Calculate the member's "informed" load factor based on a formula specified 
> by the user/admin in the configuration. I hope to just use the existing 
> lbfactor field to store this calculated value. Then we can use existing logic 
> to balance based on lbset and lbfactor for subsequent requests.
> 
> 4. Store the current time and request count in the member's data structure so 
> the lbmethod knows when it needs to be updated again.
> 
> 
> What I need from all of you:
> 
> - Input/commentary on the proposed idea, approach, and implementation. 
> Renaming things, additional fields that might be useful, etc., are all up for 
> discussion.
> 
> - Help with handling the configuration formula mentioned in #3 above. Can we 
> just add some math operators to the expression parser to handle this? What 
> all operations/functions might we need (+-*/? max? min? ternary if-then-else? 
> ...)? A simple-ish example (something like this maybe?):
> 
> <Proxy "balancer://...">
>  BalancerMember ...
>  ...
>  ProxySet \
>    lbmethod=bybackendinfo \
>    backendupdateseconds=30 \
>    backendupdaterequests=100 \
>    backendformula="%{BACKEND:uptime} -lt 120 ? 1 : %{BACKEND:workers-free} / 
>%{BACKEND:workers-max} * 100"
> </Proxy>
> 
> - [Near-long-term] Help adding X-Backend-Info backend support and 
> documentation to various projects. Tomcat, php-fpm, others(?) should be 
> fairly easy to implement and submit patches. This work does us no good if 
> none of our backends support it.
> 
> - [Long-term] Help adding X-Backend-Info frontend support and documentation 
> to various projects to help this become an "accepted ad-hoc standard"...or 
> something like that. Nginx, haproxy, and many others would be targets.
> 
> 
> Warn out from writing all of this and hopeful that someone other than me 
> actually cares, I wish you all well today/tonight!
> 
> - Jim
> 


  

Reply via email to