]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
* released 1.1.16 v1.1.16
authorwilly tarreau <willy@wtap.(none)>
Sat, 17 Dec 2005 12:32:07 +0000 (13:32 +0100)
committerwilly tarreau <willy@wtap.(none)>
Sat, 17 Dec 2005 12:32:07 +0000 (13:32 +0100)
* implement HTTP health checks when option "httpchk" is specified.
* put the changelog into a new CHANGELOG file
* updated the Formilux init script

CHANGELOG [new file with mode: 0644]
TODO
doc/haproxy.txt
examples/examples.cfg
examples/haproxy.cfg
haproxy.c
init.d/haproxy

diff --git a/CHANGELOG b/CHANGELOG
new file mode 100644 (file)
index 0000000..e7d93a8
--- /dev/null
+++ b/CHANGELOG
@@ -0,0 +1,130 @@
+ * ChangeLog :
+ *
+ * 2002/09/01 : 1.1.16
+ *   - implement HTTP health checks when option "httpchk" is specified.
+ * 2002/08/07 : 1.1.15
+ *   - replaced setpgid()/setpgrp() with setsid() for better portability, because
+ *     setpgrp() doesn't have the same meaning under Solaris, Linux, and OpenBSD.
+ * 2002/07/20 : 1.1.14
+ *   - added "postonly" cookie mode
+ * 2002/07/15 : 1.1.13
+ *   - tv_diff used inverted parameters which led to negative times !
+ * 2002/07/13 : 1.1.12
+ *   - fixed stats monitoring, and optimized some tv_* for most common cases.
+ *   - replaced temporary 'newhdr' with 'trash' to reduce stack size
+ *   - made HTTP errors more HTML-fiendly.
+ *   - renamed strlcpy() to strlcpy2() because of a slightly difference between
+ *     their behaviour (return value), to avoid confusion.
+ *   - restricted HTTP messages to HTTP proxies only
+ *   - added a 502 message when the connection has been refused by the server,
+ *     to prevent clients from believing this is a zero-byte HTTP 0.9 reply.
+ *   - changed 'Cache-control:' from 'no-cache="set-cookie"' to 'private' when
+ *     inserting a cookie, because some caches (apache) don't understand it.
+ *   - fixed processing of server headers when client is in SHUTR state
+ * 2002/07/04 :
+ *   - automatically close fd's 0,1 and 2 when going daemon ; setpgrp() after
+ *     setpgid()
+ * 2002/06/04 : 1.1.11
+ *   - fixed multi-cookie handling in client request to allow clean deletion
+ *     in insert+indirect mode. Now, only the server cookie is deleted and not
+ *     all the header. Should now be compliant to RFC2109.
+ *   - added a "nocache" option to "cookie" to specify that we explicitly want
+ *     to add a "cache-control" header when we add a cookie.
+ *     It is also possible to add an "Expires: <old-date>" to keep compatibility
+ *     with old/broken caches.
+ * 2002/05/10 : 1.1.10
+ *   - if a cookie is used in insert+indirect mode, it's desirable that the
+ *     the servers don't see it. It was not possible to remove it correctly
+ *     with regexps, so now it's removed automatically.
+ * 2002/04/19 : 1.1.9
+ *   - don't use snprintf()'s return value as an end of message since it may
+ *     be larger. This caused bus errors and segfaults in internal libc's
+ *     getenv() during localtime() in send_log().
+ *   - removed dead insecure send_syslog() function and all references to it.
+ *   - fixed warnings on Solaris due to buggy implementation of isXXXX().
+ * 2002/04/18 : 1.1.8
+ *   - option "dontlognull"
+ *   - fixed "double space" bug in config parser
+ *   - fixed an uninitialized server field in case of dispatch
+ *     with no existing server which could cause a segfault during
+ *     logging.
+ *   - the pid logged was always the father's, which was wrong for daemons.
+ *   - fixed wrong level "LOG_INFO" for message "proxy started".
+ * 2002/04/13 :
+ *   - http logging is now complete :
+ *     - ip:port, date, proxy, server
+ *     - req_time, conn_time, hdr_time, tot_time
+ *     - status, size, request
+ *   - source address
+ * 2002/04/12 : 1.1.7
+ *   - added option forwardfor
+ *   - added reqirep, reqidel, reqiallow, reqideny, rspirep, rspidel
+ *   - added "log global" in "listen" section.
+ * 2002/04/09 :
+ *   - added a new "global" section :
+ *     - logs
+ *     - debug, quiet, daemon modes
+ *     - uid, gid, chroot, nbproc, maxconn
+ * 2002/04/08 : 1.1.6
+ *   - regex are now chained and not limited anymore.
+ *   - unavailable server now returns HTTP/502.
+ *   - increased per-line args limit to 40
+ *   - added reqallow/reqdeny to block some request on matches
+ *   - added HTTP 400/403 responses
+ * 2002/04/03 : 1.1.5
+ *   - connection logging displayed incorrect source address.
+ *   - added proxy start/stop and server up/down log events.
+ *   - replaced log message short buffers with larger trash.
+ *   - enlarged buffer to 8 kB and replace buffer to 4 kB.
+ * 2002/03/25 : 1.1.4
+ *   - made rise/fall/interval time configurable
+ * 2002/03/22 : 1.1.3
+ *   - fixed a bug : cr_expire and cw_expire were inverted in CL_STSHUT[WR]
+ *     which could lead to loops.
+ * 2002/03/21 : 1.1.2
+ *   - fixed a bug in buffer management where we could have a loop
+ *     between event_read() and process_{cli|srv} if R==BUFSIZE-MAXREWRITE.
+ *     => implemented an adjustable buffer limit.
+ *   - fixed a bug : expiration of tasks in wait queue timeout is used again,
+ *     and running tasks are skipped.
+ *   - added some debug lines for accept events.
+ *   - send warnings for servers up/down.
+ * 2002/03/12 : 1.1.1
+ *   - fixed a bug in total failure handling
+ *   - fixed a bug in timestamp comparison within same second (tv_cmp_ms)
+ * 2002/03/10 : 1.1.0
+ *   - fixed a few timeout bugs
+ *   - rearranged the task scheduler subsystem to improve performance,
+ *     add new tasks, and make it easier to later port to librt ;
+ *   - allow multiple accept() for one select() wake up ;
+ *   - implemented internal load balancing with basic health-check ;
+ *   - cookie insertion and header add/replace/delete, with better strings
+ *     support.
+ * 2002/03/08
+ *   - reworked buffer handling to fix a few rewrite bugs, and
+ *     improve overall performance.
+ *   - implement the "purge" option to delete server cookies in direct mode.
+ * 2002/03/07
+ *   - fixed some error cases where the maxfd was not decreased.
+ * 2002/02/26
+ *   - now supports transparent proxying, at least on linux 2.4.
+ * 2002/02/12
+ *   - soft stop works again (fixed select timeout computation).
+ *   - it seems that TCP proxies sometimes cannot timeout.
+ *   - added a "quiet" mode.
+ *   - enforce file descriptor limitation on socket() and accept().
+ * 2001/12/30 : release of version 1.0.2 : fixed a bug in header processing
+ * 2001/12/19 : release of version 1.0.1 : no MSG_NOSIGNAL on solaris
+ * 2001/12/16 : release of version 1.0.0.
+ * 2001/12/16 : added syslog capability for each accepted connection.
+ * 2001/11/19 : corrected premature end of files and occasional SIGPIPE.
+ * 2001/10/31 : added health-check type servers (mode health) which replies OK then closes.
+ * 2001/10/30 : added the ability to support standard TCP proxies and HTTP proxies
+ *             with or without cookies (use keyword http for this).
+ * 2001/09/01 : added client/server header replacing with regexps.
+ *             eg:
+ *                     cliexp ^(Host:\ [^:]*).* Host:\ \1:80
+ *                     srvexp ^Server:\ .* Server:\ Apache
+ * 2000/11/29 : first fully working release with complete FSMs and timeouts.
+ * 2000/11/28 : major rewrite
+ * 2000/11/26 : first write
diff --git a/TODO b/TODO
index 97236802d63ec5e62c21bd84f09c9fbd3ea80a77..7d8ef742f339c534f7111567308406ba5504545b 100644 (file)
--- a/TODO
+++ b/TODO
@@ -22,7 +22,7 @@
   matchée dans la "session" pour accélérer les regex.
 - gestion keep-alive
 
-- handle parametrable HTTP health-checks replies
++ handle parametrable HTTP health-checks replies
 - differentiate http headers and http uris
 - support environment variables in config file
 - support keep-alive
index b9b0aee26bd5ffc71ea5d89a9d08d7c41f29f587..06ed2f9f023a1439cf25eae72b4348cf07464308 100644 (file)
@@ -1,9 +1,9 @@
 
                             H A - P r o x y
                             ---------------
-                             version 1.1.14
+                             version 1.1.16
                              willy tarreau
-                              2002/07/20
+                              2002/09/01
 
 ================
 | Introduction |
@@ -556,10 +556,9 @@ Exemple : m
 
 3.1) Surveillance des serveurs
 ------------------------------
-A cette date, l'état des serveurs n'est testé que par établissement de connexion
-TCP toutes les 2 secondes, avec 3 essais pour déclarer un serveur en panne, 2
-pour le déclarer utilisable. Un serveur hors d'usage ne sera pas utilisé dans le
-processus de répartition de charge interne. Pour activer la surveillance,
+Il est possible de tester l'état des serveurs par établissement de connexion TCP
+ou par envoi d'une requête HTTP. Un serveur hors d'usage ne sera pas utilisé
+dans leprocessus de répartition de charge interne. Pour activer la surveillance,
 ajouter le mot clé 'check' à la fin de la déclaration du serveur. Il est
 possible de spécifier l'intervalle (en millisecondes) séparant deux tests du
 serveur par le paramètre "inter", le nombre d'échecs acceptés par le paramètre
@@ -569,13 +568,32 @@ param
  - rise  : 2
  - fall  : 3
 
+Le mode par défaut consiste à établir des connexions TCP uniquement. Dans
+certains cas de pannes, des serveurs peuvent continuer à accepter les connexions
+sans les traiter. Depuis la version 1.1.16, haproxy est en mesure d'envoyer des
+requêtes HTTP courtes et très peu coûteuses : "OPTIONS / HTTP/1.0". Elles
+présentent l'avantage d'être facilement extractibles des logs, et de ne pas
+induire d'accès aux fichiers côté serveur. Seules les réponses 2xx et 3xx sont
+considérées valides, les autres (y compris non-réponses) aboutissent à un échec.
+Le temps maximal imparti pour une réponse est égal à l'intervalle entre deux
+tests (paramètre "inter"). Pour activer ce mode, spécifier l'option "httpchk".
+
 Exemples :
 ----------
-# même que précédemment avec surveillance
+# même que précédemment avec surveillance TCP
+    listen http_proxy 0.0.0.0:80
+       mode http
+       cookie SERVERID
+       balance roundrobin
+       server web1 192.168.1.1:80 cookie server01 check
+       server web2 192.168.1.2:80 cookie server02 check inter 500 rise 1 fall 2
+
+# même que précédemment avec surveillance HTTP
     listen http_proxy 0.0.0.0:80
        mode http
        cookie SERVERID
        balance roundrobin
+       option httpchk
        server web1 192.168.1.1:80 cookie server01 check
        server web2 192.168.1.2:80 cookie server02 check inter 500 rise 1 fall 2
 
index b3bff69de9d98efb8a3fdf9548700e4a0cf23936..8bec8288feda2cfda2391ceb1da4063d2e62701e 100644 (file)
@@ -23,7 +23,9 @@ listen proxy1 0.0.0.0:8000
        #dispatch 127.0.0.1:31300
        #dispatch 127.0.0.1:80
        #dispatch 127.0.0.1:22
-       server nc 127.0.0.1:8080 cookie cookie1 check
+       option httpchk
+       server test 10.1.1.2:80 cookie cookie1 check inter 300
+#      server nc 127.0.0.1:8080 cookie cookie1 check inter 300
 #      server tuxlocal0 10.101.23.9:80 cookie cookie1 check
 #      server tuxlocal1 127.0.0.1:80 cookie cookie1 check
 #      server tuxlocal2 127.0.0.1:80 cookie cookie2 check
index 4e8b4342e4588297e5e502f6ed6b57296678d746..97ef70bdfb534109794c9cad407711e897311ead 100644 (file)
@@ -31,6 +31,7 @@ listen        appli2-insert 0.0.0.0:10002
        mode    http
        option  httplog
        option  dontlognull
+       option  httpchk
        balance roundrobin
        cookie  SERVERID insert indirect nocache
        server  inst1 192.168.114.56:80 cookie server01 check inter 2000 fall 3
index d51ea2d24f3763808c1516b87f37dfa638bc2e2d..0dfa46e4e72d002f44602e88b4a1a054fd14f435 100644 (file)
--- a/haproxy.c
+++ b/haproxy.c
@@ -18,6 +18,8 @@
  *
  * ChangeLog :
  *
+ * 2002/09/01 : 1.1.16
+ *   - implement HTTP health checks when option "httpchk" is specified.
  * 2002/08/07 : 1.1.15
  *   - replaced setpgid()/setpgrp() with setsid() for better portability, because
  *     setpgrp() doesn't have the same meaning under Solaris, Linux, and OpenBSD.
  *
  * TODO:
  *   - handle properly intermediate incomplete server headers. Done ?
- *   - log proxies start/stop
  *   - handle hot-reconfiguration
  *
  */
 #include <linux/netfilter_ipv4.h>
 #endif
 
-#define HAPROXY_VERSION "1.1.15"
-#define HAPROXY_DATE   "2002/08/07"
+#define HAPROXY_VERSION "1.1.16"
+#define HAPROXY_DATE   "2002/09/01"
 
 /* this is for libc5 for example */
 #ifndef TCP_NODELAY
@@ -342,6 +343,7 @@ int strlcpy2(char *dst, const char *src, int size) {
 #define PR_O_NULLNOLOG 512     /* a connect without request will not be logged */
 #define PR_O_COOK_NOC  1024    /* add a 'Cache-control' header with the cookie */
 #define PR_O_COOK_POST 2048    /* don't insert cookies for requests other than a POST */
+#define PR_O_HTTP_CHK  4096    /* use HTTP 'OPTIONS' method to check server health */
 
 
 /* various session flags */
@@ -2061,10 +2063,11 @@ int event_accept(int fd) {
 
 /*
  * This function is used only for server health-checks. It handles
- * the connection acknowledgement and returns 1 if the socket is OK,
+ * the connection acknowledgement. If the proxy requires HTTP health-checks,
+ * it sends the request. In other cases, it returns 1 if the socket is OK,
  * or -1 if an error occured.
  */
-int event_srv_hck(int fd) {
+int event_srv_chk_w(int fd) {
     struct task *t = fdtab[fd].owner;
     struct server *s = t->context;
 
@@ -2073,9 +2076,64 @@ int event_srv_hck(int fd) {
     getsockopt(fd, SOL_SOCKET, SO_ERROR, &skerr, &lskerr);
     if (skerr)
        s->result = -1;
-    else
-       s->result = 1;
+    else {
+       if (s->proxy->options & PR_O_HTTP_CHK) {
+           int ret;
+           /* we want to check if this host replies to "OPTIONS / HTTP/1.0"
+            * so we'll send the request, and won't wake the checker up now.
+            */
+#ifndef MSG_NOSIGNAL
+           ret = send(fd, "OPTIONS / HTTP/1.0\r\n\r\n", 22, MSG_DONTWAIT);
+#else
+           ret = send(fd, "OPTIONS / HTTP/1.0\r\n\r\n", 22, MSG_DONTWAIT | MSG_NOSIGNAL);
+#endif
+           if (ret == 22) {
+               FD_SET(fd, StaticReadEvent);   /* prepare for reading reply */
+               FD_CLR(fd, StaticWriteEvent);  /* nothing more to write */
+               return 0;
+           }
+           else
+               s->result = -1;
+       }
+       else {
+           /* good TCP connection is enough */
+           s->result = 1;
+       }
+    }
+
+    task_wakeup(&rq, t);
+    return 0;
+}
+
 
+/*
+ * This function is used only for server health-checks. It handles
+ * the server's reply to an HTTP request. It returns 1 if the server replies
+ * 2xx or 3xx (valid responses), or -1 in other cases.
+ */
+int event_srv_chk_r(int fd) {
+    char reply[64];
+    int len;
+    struct task *t = fdtab[fd].owner;
+    struct server *s = t->context;
+
+    int skerr, lskerr;
+    lskerr = sizeof(skerr);
+    getsockopt(fd, SOL_SOCKET, SO_ERROR, &skerr, &lskerr);
+    s->result = -1;
+    if (!skerr) {
+#ifndef MSG_NOSIGNAL
+       len = recv(fd, reply, sizeof(reply), 0);
+#else
+       len = recv(fd, reply, sizeof(reply), MSG_NOSIGNAL);
+#endif
+       if ((len >= sizeof("HTTP/1.0 000")) &&
+           !memcmp(reply, "HTTP/1.", 7) &&
+           (reply[9] == '2' || reply[9] == '3')) /* 2xx or 3xx */
+               s->result = 1;
+    }
+
+    FD_CLR(fd, StaticReadEvent);
     task_wakeup(&rq, t);
     return 0;
 }
@@ -3277,8 +3335,8 @@ int process_chk(struct task *t) {
 
                    s->curfd = fd; /* that's how we know a test is in progress ;-) */
                    fdtab[fd].owner = t;
-                   fdtab[fd].read  = NULL;
-                   fdtab[fd].write = &event_srv_hck;
+                   fdtab[fd].read  = &event_srv_chk_r;
+                   fdtab[fd].write = &event_srv_chk_w;
                    fdtab[fd].state = FD_STCONN; /* connection in progress */
                    FD_SET(fd, StaticWriteEvent);  /* for connect status */
                    fd_insert(fd);
@@ -3981,6 +4039,10 @@ int cfg_parse_listen(char *file, int linenum, char **args) {
            /* don't log empty requests */
            curproxy->options |= PR_O_NULLNOLOG;
        }
+       else if (!strcmp(args[1], "httpchk")) {
+           /* use HTTP request to check servers' health */
+           curproxy->options |= PR_O_HTTP_CHK;
+       }
        else {
            Alert("parsing [%s:%d] : unknown option <%s>.\n", file, linenum, args[1]);
            return -1;
index 3849d701aedb5a4522e8d906204fea7fa0d5f5bf..89e3b833823f46cf48707ab2a396a37921015a2f 100644 (file)
@@ -31,7 +31,7 @@ ulimit -n $maxfd
 # ulimit -c unlimited
 
 # soft stop
-function dostop {
+function do_stop {
    pids=`pidof -o $$ -- $PNAME`
    if [ ! -z "$pids" ]; then
       echo "Asking $PNAME to terminate gracefully..."