comparison src/http/modules/ngx_http_upstream_ip_hash_module.c @ 260:0effe91f6083 NGINX_0_5_0

nginx 0.5.0 *) Change: the parameters in the "%name" form in the "log_format" directive are not supported anymore. *) Change: the "proxy_upstream_max_fails", "proxy_upstream_fail_timeout", "fastcgi_upstream_max_fails", "fastcgi_upstream_fail_timeout", "memcached_upstream_max_fails", and "memcached_upstream_fail_timeout" directives are not supported anymore. *) Feature: the "server" directive in the "upstream" context supports the "max_fails", "fail_timeout", and "down" parameters. *) Feature: the "ip_hash" directive inside the "upstream" block. *) Feature: the WAIT status in the "Auth-Status" header line of the IMAP/POP3 proxy authentication server response. *) Bugfix: nginx could not be built on 64-bit platforms; bug appeared in 0.4.14.
author Igor Sysoev <http://sysoev.ru>
date Mon, 04 Dec 2006 00:00:00 +0300
parents
children 052a7b1d40e5
comparison
equal deleted inserted replaced
259:c68f18041059 260:0effe91f6083
1
2 /*
3 * Copyright (C) Igor Sysoev
4 */
5
6
7 #include <ngx_config.h>
8 #include <ngx_core.h>
9 #include <ngx_http.h>
10
11
12 typedef struct {
13 /* the round robin data must be first */
14 ngx_http_upstream_rr_peer_data_t rrp;
15
16 ngx_uint_t hash;
17
18 /* AF_INET only */
19 u_char addr[3];
20
21 u_char tries;
22
23 ngx_event_get_peer_pt get_rr_peer;
24 } ngx_http_upstream_ip_hash_peer_data_t;
25
26
27 static ngx_int_t ngx_http_upstream_init_ip_hash_peer(ngx_http_request_t *r,
28 ngx_http_upstream_srv_conf_t *us);
29 static ngx_int_t ngx_http_upstream_get_ip_hash_peer(ngx_peer_connection_t *pc,
30 void *data);
31 static char *ngx_http_upstream_ip_hash(ngx_conf_t *cf, ngx_command_t *cmd,
32 void *conf);
33
34
35 static ngx_command_t ngx_http_upstream_ip_hash_commands[] = {
36
37 { ngx_string("ip_hash"),
38 NGX_HTTP_UPS_CONF|NGX_CONF_NOARGS,
39 ngx_http_upstream_ip_hash,
40 0,
41 0,
42 NULL },
43
44 ngx_null_command
45 };
46
47
48 static ngx_http_module_t ngx_http_upstream_ip_hash_module_ctx = {
49 NULL, /* preconfiguration */
50 NULL, /* postconfiguration */
51
52 NULL, /* create main configuration */
53 NULL, /* init main configuration */
54
55 NULL, /* create server configuration */
56 NULL, /* merge server configuration */
57
58 NULL, /* create location configuration */
59 NULL /* merge location configuration */
60 };
61
62
63 ngx_module_t ngx_http_upstream_ip_hash_module = {
64 NGX_MODULE_V1,
65 &ngx_http_upstream_ip_hash_module_ctx, /* module context */
66 ngx_http_upstream_ip_hash_commands, /* module directives */
67 NGX_HTTP_MODULE, /* module type */
68 NULL, /* init master */
69 NULL, /* init module */
70 NULL, /* init process */
71 NULL, /* init thread */
72 NULL, /* exit thread */
73 NULL, /* exit process */
74 NULL, /* exit master */
75 NGX_MODULE_V1_PADDING
76 };
77
78
79 ngx_int_t
80 ngx_http_upstream_init_ip_hash(ngx_conf_t *cf, ngx_http_upstream_srv_conf_t *us)
81 {
82 if (ngx_http_upstream_init_round_robin(cf, us) != NGX_OK) {
83 return NGX_ERROR;
84 }
85
86 us->peer.init = ngx_http_upstream_init_ip_hash_peer;
87
88 return NGX_OK;
89 }
90
91
92 static ngx_int_t
93 ngx_http_upstream_init_ip_hash_peer(ngx_http_request_t *r,
94 ngx_http_upstream_srv_conf_t *us)
95 {
96 struct sockaddr_in *sin;
97 ngx_http_upstream_ip_hash_peer_data_t *iphp;
98
99 iphp = ngx_palloc(r->pool, sizeof(ngx_http_upstream_ip_hash_peer_data_t));
100 if (iphp == NULL) {
101 return NGX_ERROR;
102 }
103
104 r->upstream->peer.data = &iphp->rrp;
105
106 if (ngx_http_upstream_init_round_robin_peer(r, us) != NGX_OK) {
107 return NGX_ERROR;
108 }
109
110 r->upstream->peer.get = ngx_http_upstream_get_ip_hash_peer;
111
112 /* AF_INET only */
113 sin = (struct sockaddr_in *) r->connection->sockaddr;
114 iphp->addr[0] = (u_char) ((sin->sin_addr.s_addr >> 24) & 0xff);
115 iphp->addr[1] = (u_char) ((sin->sin_addr.s_addr >> 16) & 0xff);
116 iphp->addr[2] = (u_char) ((sin->sin_addr.s_addr >> 8) & 0xff);
117
118 iphp->hash = 89;
119 iphp->tries = 0;
120 iphp->get_rr_peer = ngx_http_upstream_get_round_robin_peer;
121
122 return NGX_OK;
123 }
124
125
126 static ngx_int_t
127 ngx_http_upstream_get_ip_hash_peer(ngx_peer_connection_t *pc, void *data)
128 {
129 ngx_http_upstream_ip_hash_peer_data_t *iphp = data;
130
131 time_t now;
132 uintptr_t m;
133 ngx_uint_t i, n, p, hash;
134 ngx_http_upstream_rr_peer_t *peer;
135
136 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0,
137 "get ip hash peer, try: %ui", pc->tries);
138
139 /* TODO: cached */
140
141 if (iphp->tries > 20 || iphp->rrp.peers->number == 1) {
142 return iphp->get_rr_peer(pc, &iphp->rrp);
143 }
144
145 now = ngx_time();
146
147 pc->cached = 0;
148 pc->connection = NULL;
149
150 hash = iphp->hash;
151
152 for ( ;; ) {
153
154 for (i = 0; i < 3; i++) {
155 hash = (hash * 113 + iphp->addr[i]) % 6271;
156 }
157
158 p = hash % iphp->rrp.peers->number;
159
160 n = p / (8 * sizeof(uintptr_t));
161 m = 1 << p % (8 * sizeof(uintptr_t));
162
163 if (!(iphp->rrp.tried[n] & m)) {
164
165 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, pc->log, 0,
166 "get ip hash peer, hash: %ui %04XA", p, m);
167
168 peer = &iphp->rrp.peers->peer[p];
169
170 /* ngx_lock_mutex(iphp->rrp.peers->mutex); */
171
172 if (!peer->down) {
173
174 if (peer->max_fails == 0 || peer->fails < peer->max_fails) {
175 break;
176 }
177
178 if (now - peer->accessed > peer->fail_timeout) {
179 peer->fails = 0;
180 break;
181 }
182
183 } else {
184 iphp->rrp.tried[n] |= m;
185 }
186
187 /* ngx_unlock_mutex(iphp->rrp.peers->mutex); */
188
189 pc->tries--;
190 }
191
192 if (++iphp->tries >= 20) {
193 return iphp->get_rr_peer(pc, &iphp->rrp);
194 }
195 }
196
197 pc->sockaddr = peer->sockaddr;
198 pc->socklen = peer->socklen;
199 pc->name = &peer->name;
200 #if (NGX_SSL)
201 pc->ssl_session = peer->ssl_session;
202 #endif
203
204 /* ngx_unlock_mutex(iphp->rrp.peers->mutex); */
205
206 iphp->rrp.tried[n] |= m;
207 iphp->hash = hash;
208
209 return NGX_OK;
210 }
211
212
213 static char *
214 ngx_http_upstream_ip_hash(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
215 {
216 ngx_http_upstream_srv_conf_t *uscf;
217
218 uscf = ngx_http_conf_get_module_srv_conf(cf, ngx_http_upstream_module);
219
220 uscf->peer.init_upstream = ngx_http_upstream_init_ip_hash;
221
222 uscf->flags = NGX_HTTP_UPSTREAM_CREATE
223 |NGX_HTTP_UPSTREAM_MAX_FAILS
224 |NGX_HTTP_UPSTREAM_FAIL_TIMEOUT
225 |NGX_HTTP_UPSTREAM_DOWN;
226
227 return NGX_CONF_OK;
228 }