* released 1.2.1-pre1
* send an EMERG log when no server is available for a given proxy * added the '-c' command line option to syntactically check the configuration file without starting the service.
This commit is contained in:
parent
8a86dbf30e
commit
dd07e97447
|
@ -1,6 +1,11 @@
|
||||||
ChangeLog :
|
ChangeLog :
|
||||||
===========
|
===========
|
||||||
|
|
||||||
|
2004/04/18 : 1.2.1 (1.1.28)
|
||||||
|
- send an EMERG log when no server is available for a given proxy
|
||||||
|
- added the '-c' command line option to syntactically check the
|
||||||
|
configuration file without starting the service.
|
||||||
|
|
||||||
2003/11/09 : 1.2.0
|
2003/11/09 : 1.2.0
|
||||||
- the same as 1.1.27 + IPv6 support on the client side
|
- the same as 1.1.27 + IPv6 support on the client side
|
||||||
|
|
||||||
|
|
36
TODO
36
TODO
|
@ -80,17 +80,25 @@ ok>
|
||||||
5) implémenter "balance source" pour faire un hash sur la source.
|
5) implémenter "balance source" pour faire un hash sur la source.
|
||||||
permettre de spécifier un masque sur lequel s'applique le hachage,
|
permettre de spécifier un masque sur lequel s'applique le hachage,
|
||||||
ainsi qu'une option pour hacher en fonction de l'adresse dans le
|
ainsi qu'une option pour hacher en fonction de l'adresse dans le
|
||||||
champ "x-forwarded-for".
|
champ "x-forwarded-for". Problème pour le support des pannes: ce
|
||||||
|
type de hash est utile là où la persistence par cookie ne peut pas
|
||||||
|
s'appliquer, donc comment faire pour assurer un maximum de persistence
|
||||||
|
en cas de panne ?
|
||||||
|
|
||||||
6) possibilité d'un process séparé par listen :
|
6) possibilité d'un process séparé par listen :
|
||||||
listen XXX
|
listen XXX
|
||||||
fork [ group_id ]
|
fork [ group_id ]
|
||||||
|
|
||||||
le fait de spécifier group_id fera que toutes les instances utilisant le même
|
le fait de spécifier group_id fera que toutes les instances utilisant le
|
||||||
identifiant de groupe seront gérées par un même processus.
|
même identifiant de groupe seront gérées par un même processus.
|
||||||
|
|
||||||
-> plus souple et plus compréhensible de faire des sections par processus,
|
-> plus souple et plus compréhensible de faire des sections par processus,
|
||||||
ce qui résoud également le cas ci-dessous
|
ce qui résoud également le cas ci-dessous. Ex:
|
||||||
|
process_group X
|
||||||
|
nbproc X
|
||||||
|
uid X
|
||||||
|
chroot X
|
||||||
|
listen ...
|
||||||
|
|
||||||
7) gérer un chroot/uid/gid différents par process :
|
7) gérer un chroot/uid/gid différents par process :
|
||||||
listen XXX
|
listen XXX
|
||||||
|
@ -111,3 +119,23 @@ ok> de forcer la m
|
||||||
ok> ex: option httpchk -> OPTIONS / HTTP/1.0
|
ok> ex: option httpchk -> OPTIONS / HTTP/1.0
|
||||||
ok> option httpchk /test -> OPTIONS /test HTTP/1.0
|
ok> option httpchk /test -> OPTIONS /test HTTP/1.0
|
||||||
ok> option httpchk HEAD / HTTP/1.0\nHost:\ www -> tel quel
|
ok> option httpchk HEAD / HTTP/1.0\nHost:\ www -> tel quel
|
||||||
|
|
||||||
|
Todo for 1.1
|
||||||
|
============
|
||||||
|
* "no more server" alert
|
||||||
|
* config check
|
||||||
|
- anti-flapping
|
||||||
|
|
||||||
|
Todo for 1.2
|
||||||
|
============
|
||||||
|
- direct <server> <regex> <match>
|
||||||
|
- new config syntax allowing braces to be able to shorten lines
|
||||||
|
- insert/learn/check/log unique request ID, and add the ability
|
||||||
|
to block bad responses.
|
||||||
|
- IPv6 :
|
||||||
|
* listen [ip4.ip4.ip4.ip4]:port[-port]
|
||||||
|
* listen [ip6::...ip6]/port[-port]
|
||||||
|
- server xxx ipv4 | ipv4: | ipv4:port[-port] | ipv6/ | ipv6/port[-port]
|
||||||
|
|
||||||
|
- weighted round robin
|
||||||
|
|
||||||
|
|
67
haproxy.c
67
haproxy.c
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* HA-Proxy : High Availability-enabled HTTP/TCP proxy
|
* HA-Proxy : High Availability-enabled HTTP/TCP proxy
|
||||||
* 2000-2003 - Willy Tarreau - willy AT meta-x DOT org.
|
* 2000-2004 - Willy Tarreau - willy AT meta-x DOT org.
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License
|
* modify it under the terms of the GNU General Public License
|
||||||
|
@ -53,8 +53,8 @@
|
||||||
#include <linux/netfilter_ipv4.h>
|
#include <linux/netfilter_ipv4.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define HAPROXY_VERSION "1.1.27-ipv6"
|
#define HAPROXY_VERSION "1.2.1"
|
||||||
#define HAPROXY_DATE "2003/11/09"
|
#define HAPROXY_DATE "2004/04/18"
|
||||||
|
|
||||||
/* this is for libc5 for example */
|
/* this is for libc5 for example */
|
||||||
#ifndef TCP_NODELAY
|
#ifndef TCP_NODELAY
|
||||||
|
@ -293,6 +293,7 @@ int strlcpy2(char *dst, const char *src, int size) {
|
||||||
#define MODE_LOG 4
|
#define MODE_LOG 4
|
||||||
#define MODE_DAEMON 8
|
#define MODE_DAEMON 8
|
||||||
#define MODE_QUIET 16
|
#define MODE_QUIET 16
|
||||||
|
#define MODE_CHECK 32
|
||||||
|
|
||||||
/* server flags */
|
/* server flags */
|
||||||
#define SRV_RUNNING 1 /* the server is UP */
|
#define SRV_RUNNING 1 /* the server is UP */
|
||||||
|
@ -537,6 +538,9 @@ static regmatch_t pmatch[MAX_MATCH]; /* rm_so, rm_eo for regular expressions */
|
||||||
/* this is used to drain data, and as a temporary buffer for sprintf()... */
|
/* this is used to drain data, and as a temporary buffer for sprintf()... */
|
||||||
static char trash[BUFSIZE];
|
static char trash[BUFSIZE];
|
||||||
|
|
||||||
|
const int zero = 0;
|
||||||
|
const int one = 1;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Syslog facilities and levels. Conforming to RFC3164.
|
* Syslog facilities and levels. Conforming to RFC3164.
|
||||||
*/
|
*/
|
||||||
|
@ -665,7 +669,7 @@ int process_session(struct task *t);
|
||||||
|
|
||||||
void display_version() {
|
void display_version() {
|
||||||
printf("HA-Proxy version " HAPROXY_VERSION " " HAPROXY_DATE"\n");
|
printf("HA-Proxy version " HAPROXY_VERSION " " HAPROXY_DATE"\n");
|
||||||
printf("Copyright 2000-2003 Willy Tarreau <willy AT meta-x DOT org>\n\n");
|
printf("Copyright 2000-2004 Willy Tarreau <w@w.ods.org>\n\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -687,6 +691,7 @@ void usage(char *name) {
|
||||||
#endif
|
#endif
|
||||||
" -D goes daemon ; implies -q\n"
|
" -D goes daemon ; implies -q\n"
|
||||||
" -q quiet mode : don't display messages\n"
|
" -q quiet mode : don't display messages\n"
|
||||||
|
" -c check mode : only check config file and exit\n"
|
||||||
" -n sets the maximum total # of connections (%d)\n"
|
" -n sets the maximum total # of connections (%d)\n"
|
||||||
" -N sets the default, per-proxy maximum # of connections (%d)\n"
|
" -N sets the default, per-proxy maximum # of connections (%d)\n"
|
||||||
" -p writes pids of all children to this file\n\n",
|
" -p writes pids of all children to this file\n\n",
|
||||||
|
@ -1446,7 +1451,6 @@ static inline struct server *find_server(struct proxy *px) {
|
||||||
* it's OK, -1 if it's impossible.
|
* it's OK, -1 if it's impossible.
|
||||||
*/
|
*/
|
||||||
int connect_server(struct session *s) {
|
int connect_server(struct session *s) {
|
||||||
int one = 1;
|
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
// fprintf(stderr,"connect_server : s=%p\n",s);
|
// fprintf(stderr,"connect_server : s=%p\n",s);
|
||||||
|
@ -2033,7 +2037,6 @@ int event_accept(int fd) {
|
||||||
struct session *s;
|
struct session *s;
|
||||||
struct task *t;
|
struct task *t;
|
||||||
int cfd;
|
int cfd;
|
||||||
int one = 1;
|
|
||||||
|
|
||||||
while (p->nbconn < p->maxconn) {
|
while (p->nbconn < p->maxconn) {
|
||||||
struct sockaddr_storage addr;
|
struct sockaddr_storage addr;
|
||||||
|
@ -3833,7 +3836,6 @@ int process_chk(struct task *t) {
|
||||||
struct server *s = t->context;
|
struct server *s = t->context;
|
||||||
struct sockaddr_in sa;
|
struct sockaddr_in sa;
|
||||||
int fd = s->curfd;
|
int fd = s->curfd;
|
||||||
int one = 1;
|
|
||||||
|
|
||||||
//fprintf(stderr, "process_chk: task=%p\n", t);
|
//fprintf(stderr, "process_chk: task=%p\n", t);
|
||||||
|
|
||||||
|
@ -3899,15 +3901,17 @@ int process_chk(struct task *t) {
|
||||||
if (s->health > s->rise)
|
if (s->health > s->rise)
|
||||||
s->health--; /* still good */
|
s->health--; /* still good */
|
||||||
else {
|
else {
|
||||||
if (s->health == s->rise) {
|
|
||||||
if (!(global.mode & MODE_QUIET))
|
|
||||||
Warning("server %s/%s DOWN.\n", s->proxy->id, s->id);
|
|
||||||
|
|
||||||
send_log(s->proxy, LOG_ALERT, "Server %s/%s is DOWN.\n", s->proxy->id, s->id);
|
|
||||||
}
|
|
||||||
|
|
||||||
s->health = 0; /* failure */
|
|
||||||
s->state &= ~SRV_RUNNING;
|
s->state &= ~SRV_RUNNING;
|
||||||
|
if (s->health == s->rise) {
|
||||||
|
Warning("Server %s/%s DOWN.\n", s->proxy->id, s->id);
|
||||||
|
send_log(s->proxy, LOG_ALERT, "Server %s/%s is DOWN.\n", s->proxy->id, s->id);
|
||||||
|
|
||||||
|
if (find_server(s->proxy) == NULL) {
|
||||||
|
Alert("Proxy %s has no server available !\n", s->proxy->id);
|
||||||
|
send_log(s->proxy, LOG_EMERG, "Proxy %s has no server available !\n", s->proxy->id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s->health = 0; /* failure */
|
||||||
}
|
}
|
||||||
|
|
||||||
//fprintf(stderr, "process_chk: 7\n");
|
//fprintf(stderr, "process_chk: 7\n");
|
||||||
|
@ -3922,8 +3926,7 @@ int process_chk(struct task *t) {
|
||||||
s->health++; /* was bad, stays for a while */
|
s->health++; /* was bad, stays for a while */
|
||||||
if (s->health >= s->rise) {
|
if (s->health >= s->rise) {
|
||||||
if (s->health == s->rise) {
|
if (s->health == s->rise) {
|
||||||
if (!(global.mode & MODE_QUIET))
|
Warning("server %s/%s UP.\n", s->proxy->id, s->id);
|
||||||
Warning("server %s/%s UP.\n", s->proxy->id, s->id);
|
|
||||||
send_log(s->proxy, LOG_NOTICE, "Server %s/%s is UP.\n", s->proxy->id, s->id);
|
send_log(s->proxy, LOG_NOTICE, "Server %s/%s is UP.\n", s->proxy->id, s->id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3941,15 +3944,19 @@ int process_chk(struct task *t) {
|
||||||
if (s->health > s->rise)
|
if (s->health > s->rise)
|
||||||
s->health--; /* still good */
|
s->health--; /* still good */
|
||||||
else {
|
else {
|
||||||
if (s->health == s->rise) {
|
s->state &= ~SRV_RUNNING;
|
||||||
if (!(global.mode & MODE_QUIET))
|
|
||||||
Warning("server %s/%s DOWN.\n", s->proxy->id, s->id);
|
|
||||||
|
|
||||||
|
if (s->health == s->rise) {
|
||||||
|
Warning("Server %s/%s DOWN.\n", s->proxy->id, s->id);
|
||||||
send_log(s->proxy, LOG_ALERT, "Server %s/%s is DOWN.\n", s->proxy->id, s->id);
|
send_log(s->proxy, LOG_ALERT, "Server %s/%s is DOWN.\n", s->proxy->id, s->id);
|
||||||
|
|
||||||
|
if (find_server(s->proxy) == NULL) {
|
||||||
|
Alert("Proxy %s has no server available !\n", s->proxy->id);
|
||||||
|
send_log(s->proxy, LOG_EMERG, "Proxy %s has no server available !\n", s->proxy->id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
s->health = 0; /* failure */
|
s->health = 0; /* failure */
|
||||||
s->state &= ~SRV_RUNNING;
|
|
||||||
}
|
}
|
||||||
s->curfd = -1;
|
s->curfd = -1;
|
||||||
//FD_CLR(fd, StaticWriteEvent);
|
//FD_CLR(fd, StaticWriteEvent);
|
||||||
|
@ -4280,6 +4287,12 @@ void sig_dump_state(int sig) {
|
||||||
}
|
}
|
||||||
s = s->next;
|
s = s->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (find_server(p) == NULL) {
|
||||||
|
Warning("SIGHUP: proxy %s has no server available !\n", p);
|
||||||
|
send_log(p, LOG_NOTICE, "SIGHUP: proxy %s has no server available !\n", p);
|
||||||
|
}
|
||||||
|
|
||||||
p = p->next;
|
p = p->next;
|
||||||
}
|
}
|
||||||
signal(sig, sig_dump_state);
|
signal(sig, sig_dump_state);
|
||||||
|
@ -5691,7 +5704,7 @@ void init(int argc, char **argv) {
|
||||||
int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
|
int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
|
||||||
|
|
||||||
if (1<<INTBITS != sizeof(int)*8) {
|
if (1<<INTBITS != sizeof(int)*8) {
|
||||||
qfprintf(stderr,
|
fprintf(stderr,
|
||||||
"Error: wrong architecture. Recompile so that sizeof(int)=%d\n",
|
"Error: wrong architecture. Recompile so that sizeof(int)=%d\n",
|
||||||
sizeof(int)*8);
|
sizeof(int)*8);
|
||||||
exit(1);
|
exit(1);
|
||||||
|
@ -5716,6 +5729,8 @@ void init(int argc, char **argv) {
|
||||||
}
|
}
|
||||||
else if (*flag == 'd')
|
else if (*flag == 'd')
|
||||||
arg_mode |= MODE_DEBUG;
|
arg_mode |= MODE_DEBUG;
|
||||||
|
else if (*flag == 'c')
|
||||||
|
arg_mode |= MODE_CHECK;
|
||||||
else if (*flag == 'D')
|
else if (*flag == 'D')
|
||||||
arg_mode |= MODE_DAEMON | MODE_QUIET;
|
arg_mode |= MODE_DAEMON | MODE_QUIET;
|
||||||
else if (*flag == 'q')
|
else if (*flag == 'q')
|
||||||
|
@ -5745,6 +5760,8 @@ void init(int argc, char **argv) {
|
||||||
argv++; argc--;
|
argv++; argc--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
global.mode = (arg_mode & (MODE_DAEMON | MODE_QUIET | MODE_DEBUG));
|
||||||
|
|
||||||
if (!cfg_cfgfile)
|
if (!cfg_cfgfile)
|
||||||
usage(old_argv);
|
usage(old_argv);
|
||||||
|
|
||||||
|
@ -5755,6 +5772,11 @@ void init(int argc, char **argv) {
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (arg_mode & MODE_CHECK) {
|
||||||
|
qfprintf(stdout, "Configuration file is valid : %s\n", cfg_cfgfile);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
if (cfg_maxconn > 0)
|
if (cfg_maxconn > 0)
|
||||||
global.maxconn = cfg_maxconn;
|
global.maxconn = cfg_maxconn;
|
||||||
|
|
||||||
|
@ -5814,7 +5836,6 @@ void init(int argc, char **argv) {
|
||||||
int start_proxies() {
|
int start_proxies() {
|
||||||
struct proxy *curproxy;
|
struct proxy *curproxy;
|
||||||
struct listener *listener;
|
struct listener *listener;
|
||||||
int one = 1;
|
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
|
for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
|
||||||
|
|
Loading…
Reference in New Issue