diff --git a/doc/close-options.txt b/doc/close-options.txt new file mode 100644 index 0000000000..7790937c94 --- /dev/null +++ b/doc/close-options.txt @@ -0,0 +1,46 @@ +2011/04/20 - List of keep-alive / close options with associated behaviours. + +PK="http-pretend-keepalive", HC="httpclose", SC="http-server-close", +FC = "forceclose". + +0 = option not set +1 = option is set +* = option doesn't matter + +Options can be split between frontend and backend, so some of them might have +a meaning only when combined by associating a frontend to a backend. Some forms +are not the normal ones and provide a behaviour compatible with another normal +form. Those are considered alternate forms and are markes "(alt)". + +FC SC HC PK Behaviour + 0 0 0 X tunnel mode + 0 0 1 0 passive close, only set headers then tunnel + 0 0 1 1 forced close with keep-alive announce (alt) + 0 1 0 0 server close + 0 1 0 1 server close with keep-alive announce + 0 1 1 0 forced close (alt) + 0 1 1 1 forced close with keep-alive announce (alt) + 1 * * 0 forced close + 1 * * 1 forced close with keep-alive announce + +At this point this results in 4 distinct effective modes for a request being +processed : + - tunnel mode : Connection header is left untouched and body is ignored + - passive close : Connection header is changed and body is ignored + - server close : Connection header set, body scanned, client-side keep-alive + is made possible regardless of server-side capabilities + - forced close : Connection header set, body scanned, connection closed. + +The "close" modes may be combined with a fake keep-alive announce to the server +in order to workaround buggy servers that disable chunked encoding and content +length announces when the client does not ask for keep-alive. + +Note: "http-pretend-keepalive" alone has no effect. However, if it is set in a + backend while a frontend is in "http-close" mode, then the combination of + both will result in a forced close with keep-alive announces for requests + passing through both. + +It is also worth noting that "option httpclose" alone has become useless since +1.4, because "option forceclose" does the right thing, while the former only +pretends to do the right thing. Both options might get merged in the future. + diff --git a/doc/cookie-options.txt b/doc/cookie-options.txt new file mode 100644 index 0000000000..8956a47652 --- /dev/null +++ b/doc/cookie-options.txt @@ -0,0 +1,25 @@ +2011/04/13 : List of possible cookie settings with associated behaviours. + +PSV="preserve", PFX="prefix", INS="insert", REW="rewrite", IND="indirect" +0 = option not set +1 = option is set +* = option doesn't matter + +PSV PFX INS REW IND Behaviour + 0 0 0 0 0 passive mode + 0 0 0 0 1 passive + indirect : remove response if not needed + 0 0 0 1 0 always rewrite response + 0 0 1 0 0 always insert or replace response + 0 0 1 0 1 insert + indirect : remove req and also resp if not needed + * * 1 1 * [ forbidden ] + 0 1 0 0 0 prefix + 0 1 0 0 1 !! prefix on request, remove reponse cookie if not needed + * 1 * 1 * [ forbidden ] + * 1 1 * * [ forbidden ] + * * * 1 1 [ forbidden ] + 1 * 0 * 0 [ forbidden ] + 1 0 0 0 1 passive mode (alternate form) + 1 0 1 0 0 insert only, and preserve server response cookie if any + 1 0 1 0 1 conditional insert only for new requests + 1 1 0 0 1 prefix on requests only (passive prefix) + diff --git a/doc/design-thoughts/rate-shaping.txt b/doc/design-thoughts/rate-shaping.txt new file mode 100644 index 0000000000..255ae4a7d7 --- /dev/null +++ b/doc/design-thoughts/rate-shaping.txt @@ -0,0 +1,90 @@ +2010/01/24 - Design of multi-criteria request rate shaping. + +We want to be able to rate-shape traffic on multiple cirteria. For instance, we +may want to support shaping of per-host header requests, as well as per source. + +In order to achieve this, we will use checkpoints, one per criterion. Each of +these checkpoints will consist in a test, a rate counter and a queue. + +A request reaches the checkpoint and checks the counter. If the counter is +below the limit, it is updated and the request continues. If the limit is +reached, the request attaches itself into the queue and sleeps. The sleep time +is computed from the queue status, and updates the queue status. + +A task is dedicated to each queue. Its sole purpose is to be woken up when the +next task may wake up, to check the frequency counter, wake as many requests as +possible and update the counter. All the woken up requests are detached from +the queue. Maybe the task dedicated to the queue can be avoided and replaced +with all queued tasks's sleep counters, though this looks tricky. Or maybe it's +just the first request in the queue that should be responsible for waking up +other tasks, and not to forget to pass on this responsibility to next tasks if +it leaves the queue. + +The woken up request then goes on evaluating other criteria and possibly sleeps +again on another one. In the end, the task will have waited the amount of time +required to pass all checkpoints, and all checkpoints will be able to maintain +a permanent load of exactly their limit if enough streams flow through them. + +Since a request can only sleep in one queue at a time, it makes sense to use a +linked list element in each session to attach it to any queue. It could very +well be shared with the pendconn hooks which could then be part of the session. + +This mechanism could be used to rate-shape sessions and requests per backend +and per server. + +When rate-shaping on dynamic criteria, such as the source IP address, we have +to first extract the data pattern, then look it up in a table very similar to +the stickiness tables, but with a frequency counter. At the checkpoint, the +pattern is looked up, the entry created or refreshed, and the frequency counter +updated and checked. Then the request either goes on or sleeps as described +above, but if it sleeps, it's still in the checkpoint's queue, but with a date +computed from the criterion's status. + +This means that we need 3 distinct features : + + - optional pattern extraction + - per-pattern or per-queue frequency counter + - time-ordered queue with a task + +Based on past experiences with frequency counters, it does not appear very easy +to exactly compute sleep delays in advance for multiple requests. So most +likely we'll have to run per-criterion queues too, with only the head of the +queue holding a wake-up timeout. + +This finally leads us to the following : + + - optional pattern extraction + - per-pattern or per-queue frequency counter + - per-frequency counter queue + - head of the queue serves as a global queue timer. + +This brings us to a very flexible architecture : + - 1 list of rule-based checkpoints per frontend + - 1 list of rule-based checkpoints per backend + - 1 list of rule-based checkpoints per server + +Each of these lists have a lot of rules conditionned by ACLs, just like the +use-backend rules, except that all rules are evaluated in turn. + +Since we might sometimes just want to enable that without setting any limit and +just for enabling control in ACLs (or logging ?), we should probably try to +find a flexible way of declaring just a counter without a queue. + +These checkpoints could be of two types : + - rate-limit (described here) + - concurrency-limit (very similar with the counter and no timer). This + feature would require to keep track of all accounted criteria in a + request so that they can be released upon request completion. + +It should be possible to define a max of requests in the queue, above which a +503 is returned. The same applies for the max delay in the queue. We could have +it per-task (currently it's the connection timeout) and abort tasks with a 503 +when the delay is exceeded. + +Per-server connection concurrency could be converted to use this mechanism +which is very similar. + +The construct should be flexible enough so that the counters may be checked +from ACLs. That would allow to reject connections or switch to an alternate +backend when some limits are reached. + diff --git a/doc/internals/entities.txt b/doc/internals/entities.txt new file mode 100644 index 0000000000..646f9eaa12 --- /dev/null +++ b/doc/internals/entities.txt @@ -0,0 +1,96 @@ +2011/02/25 - Description of the different entities in haproxy - w@1wt.eu + + +1) Definitions +-------------- + +Listener +-------- + +A listener is the entity which is part of a frontend and which accepts +connections. There are as many listeners as there are ip:port couples. +There is at least one listener instanciated for each "bind" entry, and +port ranges will lead to as many listeners as there are ports in the +range. A listener just has a listening file descriptor ready to accept +incoming connections and to dispatch them to upper layers. + + +Initiator +--------- + +An initiator is instanciated for each incoming connection on a listener. It may +also be instanciated by a task pretending to be a client. An initiator calls +the next stage's accept() callback to present it with the parameters of the +incoming connection. + + +Session +------- + +A session is the only entity located between an initiator and a connector. +This is the last stage which offers an accept() callback, and all of its +processing will continue with the next stage's connect() callback. It holds +the buffers needed to forward the protocol data between each side. This entity +sees the native protocol, and is able to call analysers on these buffers. As it +is used in both directions, it always has two buffers. + +When transformations are required, some of them may be done on the initiator +side and other ones on the connector side. If additional buffers are needed for +such transforms, those buffers cannot replace the session's buffers, but they +may complete them. + +A session only needs to be instanciated when forwarding of data is required +between two sides. Accepting and filtering on layer 4 information only does not +require a session. + +For instance, let's consider the case of a proxy which receives and decodes +HTTPS traffic, processes it as HTTP and recodes it as HTTPS before forwarding +it. We'd have 3 layers of buffers, where the middle ones are used for +forwarding of the protocol data (HTTP here) : + + <-- ssl dec --> <-forwarding-> <-- ssl enc --> + + ,->[||||]--. ,->[||||]--. ,->[||||]--. + client (|) (|) (|) (|) server + ^--[||||]<-' ^--[||||]<-' ^--[||||]<-' + + HTTPS HTTP HTTPS + +The session handling code is only responsible for monitoring the forwarding +buffers here. It may declare the end of the session once those buffers are +closed and no analyser wants to re-open them. The session is also the entity +which applies the load balancing algorithm and decides the server to use. + +The other sides are responsible for propagating the state up to the session +which takes decisions. + + +Connector +--------- + +A connector is the entity which permits to instanciate a connection to a known +destination. It presents a connect() callback, and as such appears on the right +side of diagrams. + + +Connection +---------- + +A connection is the entity instanciated by a connector. It may be composed of +multiple stages linked together. Generally it is the part of the stream +interface holding a file descriptor, but it can also be a processing block or a +transformation block terminated by a connection. A connection presents a +server-side interface. + + +2) Sequencing +------------- + +Upon startup, listeners are instanciated by the configuration. When an incoming +connection reaches a listening file descriptor, its read() callback calls the +corresponding listener's accept() function which instanciates an initiator and +in turn recursively calls upper layers' accept() callbacks until +accept_session() is called. accept_session() instanciates a new session which +starts protocol analysis via process_session(). When all protocol analysis is +done, process_session() calls the connect() callback of the connector in order +to get a connection.