Mercurial > hg > nginx
annotate src/http/modules/ngx_http_upstream_ip_hash_module.c @ 6795:1a917932db96
Cache: prefix-based temporary files.
On Linux, the rename syscall can be slow due to a global file system lock,
acquired for the entire rename operation, unless both old and new files are
in the same directory. To address this temporary files are now created
in the same directory as the expected resulting cache file when using the
"use_temp_path=off" parameter.
This change mostly reverts 99639bfdfa2a and 3281de8142f5, restoring the
behaviour as of a9138c35120d (with minor changes).
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Thu, 03 Nov 2016 17:10:29 +0300 |
parents | 29bf0dbc0a77 |
children | ed599ea6c1f1 |
rev | line source |
---|---|
884 | 1 |
2 /* | |
3 * Copyright (C) Igor Sysoev | |
4412 | 4 * Copyright (C) Nginx, Inc. |
884 | 5 */ |
6 | |
7 | |
8 #include <ngx_config.h> | |
9 #include <ngx_core.h> | |
10 #include <ngx_http.h> | |
11 | |
12 | |
13 typedef struct { | |
14 /* the round robin data must be first */ | |
15 ngx_http_upstream_rr_peer_data_t rrp; | |
16 | |
17 ngx_uint_t hash; | |
18 | |
4695
441b2941a506
Added IPv6 support to ip_hash.
Ruslan Ermilov <ru@nginx.com>
parents:
4655
diff
changeset
|
19 u_char addrlen; |
441b2941a506
Added IPv6 support to ip_hash.
Ruslan Ermilov <ru@nginx.com>
parents:
4655
diff
changeset
|
20 u_char *addr; |
884 | 21 |
22 u_char tries; | |
23 | |
24 ngx_event_get_peer_pt get_rr_peer; | |
25 } ngx_http_upstream_ip_hash_peer_data_t; | |
26 | |
27 | |
28 static ngx_int_t ngx_http_upstream_init_ip_hash_peer(ngx_http_request_t *r, | |
29 ngx_http_upstream_srv_conf_t *us); | |
30 static ngx_int_t ngx_http_upstream_get_ip_hash_peer(ngx_peer_connection_t *pc, | |
31 void *data); | |
32 static char *ngx_http_upstream_ip_hash(ngx_conf_t *cf, ngx_command_t *cmd, | |
33 void *conf); | |
34 | |
35 | |
36 static ngx_command_t ngx_http_upstream_ip_hash_commands[] = { | |
37 | |
38 { ngx_string("ip_hash"), | |
39 NGX_HTTP_UPS_CONF|NGX_CONF_NOARGS, | |
40 ngx_http_upstream_ip_hash, | |
41 0, | |
42 0, | |
43 NULL }, | |
44 | |
45 ngx_null_command | |
46 }; | |
47 | |
48 | |
49 static ngx_http_module_t ngx_http_upstream_ip_hash_module_ctx = { | |
50 NULL, /* preconfiguration */ | |
51 NULL, /* postconfiguration */ | |
52 | |
53 NULL, /* create main configuration */ | |
54 NULL, /* init main configuration */ | |
55 | |
56 NULL, /* create server configuration */ | |
57 NULL, /* merge server configuration */ | |
58 | |
59 NULL, /* create location configuration */ | |
60 NULL /* merge location configuration */ | |
61 }; | |
62 | |
63 | |
64 ngx_module_t ngx_http_upstream_ip_hash_module = { | |
65 NGX_MODULE_V1, | |
66 &ngx_http_upstream_ip_hash_module_ctx, /* module context */ | |
67 ngx_http_upstream_ip_hash_commands, /* module directives */ | |
68 NGX_HTTP_MODULE, /* module type */ | |
69 NULL, /* init master */ | |
70 NULL, /* init module */ | |
71 NULL, /* init process */ | |
72 NULL, /* init thread */ | |
73 NULL, /* exit thread */ | |
74 NULL, /* exit process */ | |
75 NULL, /* exit master */ | |
76 NGX_MODULE_V1_PADDING | |
77 }; | |
78 | |
79 | |
4695
441b2941a506
Added IPv6 support to ip_hash.
Ruslan Ermilov <ru@nginx.com>
parents:
4655
diff
changeset
|
80 static u_char ngx_http_upstream_ip_hash_pseudo_addr[3]; |
441b2941a506
Added IPv6 support to ip_hash.
Ruslan Ermilov <ru@nginx.com>
parents:
4655
diff
changeset
|
81 |
441b2941a506
Added IPv6 support to ip_hash.
Ruslan Ermilov <ru@nginx.com>
parents:
4655
diff
changeset
|
82 |
441b2941a506
Added IPv6 support to ip_hash.
Ruslan Ermilov <ru@nginx.com>
parents:
4655
diff
changeset
|
83 static ngx_int_t |
884 | 84 ngx_http_upstream_init_ip_hash(ngx_conf_t *cf, ngx_http_upstream_srv_conf_t *us) |
85 { | |
86 if (ngx_http_upstream_init_round_robin(cf, us) != NGX_OK) { | |
87 return NGX_ERROR; | |
88 } | |
89 | |
90 us->peer.init = ngx_http_upstream_init_ip_hash_peer; | |
91 | |
92 return NGX_OK; | |
93 } | |
94 | |
95 | |
96 static ngx_int_t | |
97 ngx_http_upstream_init_ip_hash_peer(ngx_http_request_t *r, | |
98 ngx_http_upstream_srv_conf_t *us) | |
99 { | |
100 struct sockaddr_in *sin; | |
4695
441b2941a506
Added IPv6 support to ip_hash.
Ruslan Ermilov <ru@nginx.com>
parents:
4655
diff
changeset
|
101 #if (NGX_HAVE_INET6) |
441b2941a506
Added IPv6 support to ip_hash.
Ruslan Ermilov <ru@nginx.com>
parents:
4655
diff
changeset
|
102 struct sockaddr_in6 *sin6; |
441b2941a506
Added IPv6 support to ip_hash.
Ruslan Ermilov <ru@nginx.com>
parents:
4655
diff
changeset
|
103 #endif |
884 | 104 ngx_http_upstream_ip_hash_peer_data_t *iphp; |
105 | |
106 iphp = ngx_palloc(r->pool, sizeof(ngx_http_upstream_ip_hash_peer_data_t)); | |
107 if (iphp == NULL) { | |
108 return NGX_ERROR; | |
109 } | |
110 | |
111 r->upstream->peer.data = &iphp->rrp; | |
112 | |
113 if (ngx_http_upstream_init_round_robin_peer(r, us) != NGX_OK) { | |
114 return NGX_ERROR; | |
115 } | |
116 | |
117 r->upstream->peer.get = ngx_http_upstream_get_ip_hash_peer; | |
118 | |
4695
441b2941a506
Added IPv6 support to ip_hash.
Ruslan Ermilov <ru@nginx.com>
parents:
4655
diff
changeset
|
119 switch (r->connection->sockaddr->sa_family) { |
2512
2e91aecb9e57
a prelimiary IPv6 support, HTTP listen
Igor Sysoev <igor@sysoev.ru>
parents:
1418
diff
changeset
|
120 |
4695
441b2941a506
Added IPv6 support to ip_hash.
Ruslan Ermilov <ru@nginx.com>
parents:
4655
diff
changeset
|
121 case AF_INET: |
2512
2e91aecb9e57
a prelimiary IPv6 support, HTTP listen
Igor Sysoev <igor@sysoev.ru>
parents:
1418
diff
changeset
|
122 sin = (struct sockaddr_in *) r->connection->sockaddr; |
4695
441b2941a506
Added IPv6 support to ip_hash.
Ruslan Ermilov <ru@nginx.com>
parents:
4655
diff
changeset
|
123 iphp->addr = (u_char *) &sin->sin_addr.s_addr; |
441b2941a506
Added IPv6 support to ip_hash.
Ruslan Ermilov <ru@nginx.com>
parents:
4655
diff
changeset
|
124 iphp->addrlen = 3; |
441b2941a506
Added IPv6 support to ip_hash.
Ruslan Ermilov <ru@nginx.com>
parents:
4655
diff
changeset
|
125 break; |
2512
2e91aecb9e57
a prelimiary IPv6 support, HTTP listen
Igor Sysoev <igor@sysoev.ru>
parents:
1418
diff
changeset
|
126 |
4695
441b2941a506
Added IPv6 support to ip_hash.
Ruslan Ermilov <ru@nginx.com>
parents:
4655
diff
changeset
|
127 #if (NGX_HAVE_INET6) |
441b2941a506
Added IPv6 support to ip_hash.
Ruslan Ermilov <ru@nginx.com>
parents:
4655
diff
changeset
|
128 case AF_INET6: |
441b2941a506
Added IPv6 support to ip_hash.
Ruslan Ermilov <ru@nginx.com>
parents:
4655
diff
changeset
|
129 sin6 = (struct sockaddr_in6 *) r->connection->sockaddr; |
441b2941a506
Added IPv6 support to ip_hash.
Ruslan Ermilov <ru@nginx.com>
parents:
4655
diff
changeset
|
130 iphp->addr = (u_char *) &sin6->sin6_addr.s6_addr; |
441b2941a506
Added IPv6 support to ip_hash.
Ruslan Ermilov <ru@nginx.com>
parents:
4655
diff
changeset
|
131 iphp->addrlen = 16; |
441b2941a506
Added IPv6 support to ip_hash.
Ruslan Ermilov <ru@nginx.com>
parents:
4655
diff
changeset
|
132 break; |
441b2941a506
Added IPv6 support to ip_hash.
Ruslan Ermilov <ru@nginx.com>
parents:
4655
diff
changeset
|
133 #endif |
441b2941a506
Added IPv6 support to ip_hash.
Ruslan Ermilov <ru@nginx.com>
parents:
4655
diff
changeset
|
134 |
441b2941a506
Added IPv6 support to ip_hash.
Ruslan Ermilov <ru@nginx.com>
parents:
4655
diff
changeset
|
135 default: |
441b2941a506
Added IPv6 support to ip_hash.
Ruslan Ermilov <ru@nginx.com>
parents:
4655
diff
changeset
|
136 iphp->addr = ngx_http_upstream_ip_hash_pseudo_addr; |
441b2941a506
Added IPv6 support to ip_hash.
Ruslan Ermilov <ru@nginx.com>
parents:
4655
diff
changeset
|
137 iphp->addrlen = 3; |
2512
2e91aecb9e57
a prelimiary IPv6 support, HTTP listen
Igor Sysoev <igor@sysoev.ru>
parents:
1418
diff
changeset
|
138 } |
884 | 139 |
140 iphp->hash = 89; | |
141 iphp->tries = 0; | |
142 iphp->get_rr_peer = ngx_http_upstream_get_round_robin_peer; | |
143 | |
144 return NGX_OK; | |
145 } | |
146 | |
147 | |
148 static ngx_int_t | |
149 ngx_http_upstream_get_ip_hash_peer(ngx_peer_connection_t *pc, void *data) | |
150 { | |
151 ngx_http_upstream_ip_hash_peer_data_t *iphp = data; | |
152 | |
153 time_t now; | |
4655
382c523d253a
Upstream: weights support in ip_hash balancer.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4412
diff
changeset
|
154 ngx_int_t w; |
884 | 155 uintptr_t m; |
156 ngx_uint_t i, n, p, hash; | |
157 ngx_http_upstream_rr_peer_t *peer; | |
158 | |
159 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0, | |
160 "get ip hash peer, try: %ui", pc->tries); | |
161 | |
162 /* TODO: cached */ | |
163 | |
6102 | 164 ngx_http_upstream_rr_peers_wlock(iphp->rrp.peers); |
165 | |
1418
acb1f441e7b2
update ip_hash to "backup" option
Igor Sysoev <igor@sysoev.ru>
parents:
1417
diff
changeset
|
166 if (iphp->tries > 20 || iphp->rrp.peers->single) { |
6102 | 167 ngx_http_upstream_rr_peers_unlock(iphp->rrp.peers); |
884 | 168 return iphp->get_rr_peer(pc, &iphp->rrp); |
169 } | |
170 | |
171 now = ngx_time(); | |
172 | |
173 pc->cached = 0; | |
174 pc->connection = NULL; | |
175 | |
176 hash = iphp->hash; | |
177 | |
178 for ( ;; ) { | |
179 | |
5359
2fda9065d0f4
Win32: Borland C compatibility fixes.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5173
diff
changeset
|
180 for (i = 0; i < (ngx_uint_t) iphp->addrlen; i++) { |
884 | 181 hash = (hash * 113 + iphp->addr[i]) % 6271; |
182 } | |
183 | |
6121
b6047abf5f30
Upstream: simplified ip_hash and hash peer selection code.
Ruslan Ermilov <ru@nginx.com>
parents:
6108
diff
changeset
|
184 w = hash % iphp->rrp.peers->total_weight; |
b6047abf5f30
Upstream: simplified ip_hash and hash peer selection code.
Ruslan Ermilov <ru@nginx.com>
parents:
6108
diff
changeset
|
185 peer = iphp->rrp.peers->peer; |
b6047abf5f30
Upstream: simplified ip_hash and hash peer selection code.
Ruslan Ermilov <ru@nginx.com>
parents:
6108
diff
changeset
|
186 p = 0; |
4655
382c523d253a
Upstream: weights support in ip_hash balancer.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4412
diff
changeset
|
187 |
6121
b6047abf5f30
Upstream: simplified ip_hash and hash peer selection code.
Ruslan Ermilov <ru@nginx.com>
parents:
6108
diff
changeset
|
188 while (w >= peer->weight) { |
b6047abf5f30
Upstream: simplified ip_hash and hash peer selection code.
Ruslan Ermilov <ru@nginx.com>
parents:
6108
diff
changeset
|
189 w -= peer->weight; |
b6047abf5f30
Upstream: simplified ip_hash and hash peer selection code.
Ruslan Ermilov <ru@nginx.com>
parents:
6108
diff
changeset
|
190 peer = peer->next; |
b6047abf5f30
Upstream: simplified ip_hash and hash peer selection code.
Ruslan Ermilov <ru@nginx.com>
parents:
6108
diff
changeset
|
191 p++; |
4655
382c523d253a
Upstream: weights support in ip_hash balancer.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4412
diff
changeset
|
192 } |
884 | 193 |
194 n = p / (8 * sizeof(uintptr_t)); | |
1416
ad2311c943a3
fix ip_hash on 64-bit platform
Igor Sysoev <igor@sysoev.ru>
parents:
1284
diff
changeset
|
195 m = (uintptr_t) 1 << p % (8 * sizeof(uintptr_t)); |
884 | 196 |
5486
741aa3fde496
Upstream: simplified peer selection loop in the "ip_hash" module.
Vladimir Homutov <vl@nginx.com>
parents:
5359
diff
changeset
|
197 if (iphp->rrp.tried[n] & m) { |
741aa3fde496
Upstream: simplified peer selection loop in the "ip_hash" module.
Vladimir Homutov <vl@nginx.com>
parents:
5359
diff
changeset
|
198 goto next; |
741aa3fde496
Upstream: simplified peer selection loop in the "ip_hash" module.
Vladimir Homutov <vl@nginx.com>
parents:
5359
diff
changeset
|
199 } |
884 | 200 |
5486
741aa3fde496
Upstream: simplified peer selection loop in the "ip_hash" module.
Vladimir Homutov <vl@nginx.com>
parents:
5359
diff
changeset
|
201 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, pc->log, 0, |
6480 | 202 "get ip hash peer, hash: %ui %04XL", p, (uint64_t) m); |
884 | 203 |
5486
741aa3fde496
Upstream: simplified peer selection loop in the "ip_hash" module.
Vladimir Homutov <vl@nginx.com>
parents:
5359
diff
changeset
|
204 if (peer->down) { |
6108
55dc5f7eb921
Upstream: get rid of questionable micro-optimization in ip_hash.
Ruslan Ermilov <ru@nginx.com>
parents:
6102
diff
changeset
|
205 goto next; |
5486
741aa3fde496
Upstream: simplified peer selection loop in the "ip_hash" module.
Vladimir Homutov <vl@nginx.com>
parents:
5359
diff
changeset
|
206 } |
884 | 207 |
5486
741aa3fde496
Upstream: simplified peer selection loop in the "ip_hash" module.
Vladimir Homutov <vl@nginx.com>
parents:
5359
diff
changeset
|
208 if (peer->max_fails |
741aa3fde496
Upstream: simplified peer selection loop in the "ip_hash" module.
Vladimir Homutov <vl@nginx.com>
parents:
5359
diff
changeset
|
209 && peer->fails >= peer->max_fails |
741aa3fde496
Upstream: simplified peer selection loop in the "ip_hash" module.
Vladimir Homutov <vl@nginx.com>
parents:
5359
diff
changeset
|
210 && now - peer->checked <= peer->fail_timeout) |
741aa3fde496
Upstream: simplified peer selection loop in the "ip_hash" module.
Vladimir Homutov <vl@nginx.com>
parents:
5359
diff
changeset
|
211 { |
6108
55dc5f7eb921
Upstream: get rid of questionable micro-optimization in ip_hash.
Ruslan Ermilov <ru@nginx.com>
parents:
6102
diff
changeset
|
212 goto next; |
5486
741aa3fde496
Upstream: simplified peer selection loop in the "ip_hash" module.
Vladimir Homutov <vl@nginx.com>
parents:
5359
diff
changeset
|
213 } |
741aa3fde496
Upstream: simplified peer selection loop in the "ip_hash" module.
Vladimir Homutov <vl@nginx.com>
parents:
5359
diff
changeset
|
214 |
6705 | 215 if (peer->max_conns && peer->conns >= peer->max_conns) { |
216 goto next; | |
217 } | |
218 | |
5486
741aa3fde496
Upstream: simplified peer selection loop in the "ip_hash" module.
Vladimir Homutov <vl@nginx.com>
parents:
5359
diff
changeset
|
219 break; |
884 | 220 |
5486
741aa3fde496
Upstream: simplified peer selection loop in the "ip_hash" module.
Vladimir Homutov <vl@nginx.com>
parents:
5359
diff
changeset
|
221 next: |
884 | 222 |
5706
a2bf26774cd3
Upstream: fix tries check in ip_hash.
Roman Arutyunyan <arut@nginx.com>
parents:
5486
diff
changeset
|
223 if (++iphp->tries > 20) { |
6102 | 224 ngx_http_upstream_rr_peers_unlock(iphp->rrp.peers); |
884 | 225 return iphp->get_rr_peer(pc, &iphp->rrp); |
226 } | |
227 } | |
228 | |
6100
c44459611d91
Upstream: store peers as a linked list.
Ruslan Ermilov <ru@nginx.com>
parents:
6099
diff
changeset
|
229 iphp->rrp.current = peer; |
1417
b23a80f9a7b8
set current peer to use it in ngx_http_upstream_free_round_robin_peer()
Igor Sysoev <igor@sysoev.ru>
parents:
1416
diff
changeset
|
230 |
884 | 231 pc->sockaddr = peer->sockaddr; |
232 pc->socklen = peer->socklen; | |
233 pc->name = &peer->name; | |
234 | |
6099
6ff0ebd6fbf4
Upstream: track the number of active connections to upstreams.
Ruslan Ermilov <ru@nginx.com>
parents:
5706
diff
changeset
|
235 peer->conns++; |
6ff0ebd6fbf4
Upstream: track the number of active connections to upstreams.
Ruslan Ermilov <ru@nginx.com>
parents:
5706
diff
changeset
|
236 |
5486
741aa3fde496
Upstream: simplified peer selection loop in the "ip_hash" module.
Vladimir Homutov <vl@nginx.com>
parents:
5359
diff
changeset
|
237 if (now - peer->checked > peer->fail_timeout) { |
741aa3fde496
Upstream: simplified peer selection loop in the "ip_hash" module.
Vladimir Homutov <vl@nginx.com>
parents:
5359
diff
changeset
|
238 peer->checked = now; |
741aa3fde496
Upstream: simplified peer selection loop in the "ip_hash" module.
Vladimir Homutov <vl@nginx.com>
parents:
5359
diff
changeset
|
239 } |
741aa3fde496
Upstream: simplified peer selection loop in the "ip_hash" module.
Vladimir Homutov <vl@nginx.com>
parents:
5359
diff
changeset
|
240 |
6102 | 241 ngx_http_upstream_rr_peers_unlock(iphp->rrp.peers); |
884 | 242 |
243 iphp->rrp.tried[n] |= m; | |
244 iphp->hash = hash; | |
245 | |
246 return NGX_OK; | |
247 } | |
248 | |
249 | |
250 static char * | |
251 ngx_http_upstream_ip_hash(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | |
252 { | |
253 ngx_http_upstream_srv_conf_t *uscf; | |
254 | |
255 uscf = ngx_http_conf_get_module_srv_conf(cf, ngx_http_upstream_module); | |
256 | |
5173
5373be93c0be
Upstream: warn if multiple non-stackable balancers are installed.
Ruslan Ermilov <ru@nginx.com>
parents:
4695
diff
changeset
|
257 if (uscf->peer.init_upstream) { |
5373be93c0be
Upstream: warn if multiple non-stackable balancers are installed.
Ruslan Ermilov <ru@nginx.com>
parents:
4695
diff
changeset
|
258 ngx_conf_log_error(NGX_LOG_WARN, cf, 0, |
5373be93c0be
Upstream: warn if multiple non-stackable balancers are installed.
Ruslan Ermilov <ru@nginx.com>
parents:
4695
diff
changeset
|
259 "load balancing method redefined"); |
5373be93c0be
Upstream: warn if multiple non-stackable balancers are installed.
Ruslan Ermilov <ru@nginx.com>
parents:
4695
diff
changeset
|
260 } |
5373be93c0be
Upstream: warn if multiple non-stackable balancers are installed.
Ruslan Ermilov <ru@nginx.com>
parents:
4695
diff
changeset
|
261 |
884 | 262 uscf->peer.init_upstream = ngx_http_upstream_init_ip_hash; |
263 | |
264 uscf->flags = NGX_HTTP_UPSTREAM_CREATE | |
4655
382c523d253a
Upstream: weights support in ip_hash balancer.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4412
diff
changeset
|
265 |NGX_HTTP_UPSTREAM_WEIGHT |
6705 | 266 |NGX_HTTP_UPSTREAM_MAX_CONNS |
884 | 267 |NGX_HTTP_UPSTREAM_MAX_FAILS |
268 |NGX_HTTP_UPSTREAM_FAIL_TIMEOUT | |
269 |NGX_HTTP_UPSTREAM_DOWN; | |
270 | |
271 return NGX_CONF_OK; | |
272 } |