Mercurial > hg > nginx-quic
annotate src/stream/ngx_stream_upstream_round_robin.c @ 8867:5119c8150478
Fixed runtime handling of systems without EPOLLRDHUP support.
In 7583:efd71d49bde0 (nginx 1.17.5) along with introduction of the
ioctl(FIONREAD) support proper handling of systems without EPOLLRDHUP
support in the kernel (but with EPOLLRDHUP in headers) was broken.
Before the change, rev->available was never set to 0 unless
ngx_use_epoll_rdhup was also set (that is, runtime test for EPOLLRDHUP
introduced in 6536:f7849bfb6d21 succeeded). After the change,
rev->available might reach 0 on systems without runtime EPOLLRDHUP
support, stopping further reading in ngx_readv_chain() and ngx_unix_recv().
And, if EOF happened to be already reported along with the last event,
it is not reported again by epoll_wait(), leading to connection hangs
and timeouts on such systems.
This affects Linux kernels before 2.6.17 if nginx was compiled
with newer headers, and, more importantly, emulation layers, such as
DigitalOcean's App Platform's / gVisor's epoll emulation layer.
Fix is to explicitly check ngx_use_epoll_rdhup before the corresponding
rev->pending_eof tests in ngx_readv_chain() and ngx_unix_recv().
author | Marcus Ball <marcus.ball@live.com> |
---|---|
date | Mon, 30 May 2022 02:38:07 +0300 |
parents | 90cc7194e993 |
children |
rev | line source |
---|---|
6115 | 1 |
2 /* | |
3 * Copyright (C) Igor Sysoev | |
4 * Copyright (C) Nginx, Inc. | |
5 */ | |
6 | |
7 | |
8 #include <ngx_config.h> | |
9 #include <ngx_core.h> | |
10 #include <ngx_stream.h> | |
11 | |
12 | |
8249
90cc7194e993
Upstream: excluded down servers from the next_upstream tries.
Ruslan Ermilov <ru@nginx.com>
parents:
7509
diff
changeset
|
13 #define ngx_stream_upstream_tries(p) ((p)->tries \ |
90cc7194e993
Upstream: excluded down servers from the next_upstream tries.
Ruslan Ermilov <ru@nginx.com>
parents:
7509
diff
changeset
|
14 + ((p)->next ? (p)->next->tries : 0)) |
6115 | 15 |
16 | |
17 static ngx_stream_upstream_rr_peer_t *ngx_stream_upstream_get_peer( | |
18 ngx_stream_upstream_rr_peer_data_t *rrp); | |
6863
54cf51c4f07a
Stream: speed up TCP peer recovery.
Roman Arutyunyan <arut@nginx.com>
parents:
6785
diff
changeset
|
19 static void ngx_stream_upstream_notify_round_robin_peer( |
54cf51c4f07a
Stream: speed up TCP peer recovery.
Roman Arutyunyan <arut@nginx.com>
parents:
6785
diff
changeset
|
20 ngx_peer_connection_t *pc, void *data, ngx_uint_t state); |
6115 | 21 |
22 #if (NGX_STREAM_SSL) | |
23 | |
24 static ngx_int_t ngx_stream_upstream_set_round_robin_peer_session( | |
25 ngx_peer_connection_t *pc, void *data); | |
26 static void ngx_stream_upstream_save_round_robin_peer_session( | |
27 ngx_peer_connection_t *pc, void *data); | |
6643
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
28 static ngx_int_t ngx_stream_upstream_empty_set_session( |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
29 ngx_peer_connection_t *pc, void *data); |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
30 static void ngx_stream_upstream_empty_save_session(ngx_peer_connection_t *pc, |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
31 void *data); |
6115 | 32 |
33 #endif | |
34 | |
35 | |
36 ngx_int_t | |
37 ngx_stream_upstream_init_round_robin(ngx_conf_t *cf, | |
38 ngx_stream_upstream_srv_conf_t *us) | |
39 { | |
40 ngx_url_t u; | |
8249
90cc7194e993
Upstream: excluded down servers from the next_upstream tries.
Ruslan Ermilov <ru@nginx.com>
parents:
7509
diff
changeset
|
41 ngx_uint_t i, j, n, w, t; |
6115 | 42 ngx_stream_upstream_server_t *server; |
43 ngx_stream_upstream_rr_peer_t *peer, **peerp; | |
44 ngx_stream_upstream_rr_peers_t *peers, *backup; | |
45 | |
46 us->peer.init = ngx_stream_upstream_init_round_robin_peer; | |
47 | |
48 if (us->servers) { | |
49 server = us->servers->elts; | |
50 | |
51 n = 0; | |
52 w = 0; | |
8249
90cc7194e993
Upstream: excluded down servers from the next_upstream tries.
Ruslan Ermilov <ru@nginx.com>
parents:
7509
diff
changeset
|
53 t = 0; |
6115 | 54 |
55 for (i = 0; i < us->servers->nelts; i++) { | |
56 if (server[i].backup) { | |
57 continue; | |
58 } | |
59 | |
60 n += server[i].naddrs; | |
61 w += server[i].naddrs * server[i].weight; | |
8249
90cc7194e993
Upstream: excluded down servers from the next_upstream tries.
Ruslan Ermilov <ru@nginx.com>
parents:
7509
diff
changeset
|
62 |
90cc7194e993
Upstream: excluded down servers from the next_upstream tries.
Ruslan Ermilov <ru@nginx.com>
parents:
7509
diff
changeset
|
63 if (!server[i].down) { |
90cc7194e993
Upstream: excluded down servers from the next_upstream tries.
Ruslan Ermilov <ru@nginx.com>
parents:
7509
diff
changeset
|
64 t += server[i].naddrs; |
90cc7194e993
Upstream: excluded down servers from the next_upstream tries.
Ruslan Ermilov <ru@nginx.com>
parents:
7509
diff
changeset
|
65 } |
6115 | 66 } |
67 | |
68 if (n == 0) { | |
69 ngx_log_error(NGX_LOG_EMERG, cf->log, 0, | |
70 "no servers in upstream \"%V\" in %s:%ui", | |
71 &us->host, us->file_name, us->line); | |
72 return NGX_ERROR; | |
73 } | |
74 | |
75 peers = ngx_pcalloc(cf->pool, sizeof(ngx_stream_upstream_rr_peers_t)); | |
76 if (peers == NULL) { | |
77 return NGX_ERROR; | |
78 } | |
79 | |
80 peer = ngx_pcalloc(cf->pool, sizeof(ngx_stream_upstream_rr_peer_t) * n); | |
81 if (peer == NULL) { | |
82 return NGX_ERROR; | |
83 } | |
84 | |
85 peers->single = (n == 1); | |
86 peers->number = n; | |
87 peers->weighted = (w != n); | |
88 peers->total_weight = w; | |
8249
90cc7194e993
Upstream: excluded down servers from the next_upstream tries.
Ruslan Ermilov <ru@nginx.com>
parents:
7509
diff
changeset
|
89 peers->tries = t; |
6115 | 90 peers->name = &us->host; |
91 | |
92 n = 0; | |
93 peerp = &peers->peer; | |
94 | |
95 for (i = 0; i < us->servers->nelts; i++) { | |
96 if (server[i].backup) { | |
97 continue; | |
98 } | |
99 | |
100 for (j = 0; j < server[i].naddrs; j++) { | |
101 peer[n].sockaddr = server[i].addrs[j].sockaddr; | |
102 peer[n].socklen = server[i].addrs[j].socklen; | |
103 peer[n].name = server[i].addrs[j].name; | |
104 peer[n].weight = server[i].weight; | |
105 peer[n].effective_weight = server[i].weight; | |
106 peer[n].current_weight = 0; | |
6705 | 107 peer[n].max_conns = server[i].max_conns; |
6115 | 108 peer[n].max_fails = server[i].max_fails; |
109 peer[n].fail_timeout = server[i].fail_timeout; | |
110 peer[n].down = server[i].down; | |
111 peer[n].server = server[i].name; | |
112 | |
113 *peerp = &peer[n]; | |
114 peerp = &peer[n].next; | |
115 n++; | |
116 } | |
117 } | |
118 | |
119 us->peer.data = peers; | |
120 | |
121 /* backup servers */ | |
122 | |
123 n = 0; | |
124 w = 0; | |
8249
90cc7194e993
Upstream: excluded down servers from the next_upstream tries.
Ruslan Ermilov <ru@nginx.com>
parents:
7509
diff
changeset
|
125 t = 0; |
6115 | 126 |
127 for (i = 0; i < us->servers->nelts; i++) { | |
128 if (!server[i].backup) { | |
129 continue; | |
130 } | |
131 | |
132 n += server[i].naddrs; | |
133 w += server[i].naddrs * server[i].weight; | |
8249
90cc7194e993
Upstream: excluded down servers from the next_upstream tries.
Ruslan Ermilov <ru@nginx.com>
parents:
7509
diff
changeset
|
134 |
90cc7194e993
Upstream: excluded down servers from the next_upstream tries.
Ruslan Ermilov <ru@nginx.com>
parents:
7509
diff
changeset
|
135 if (!server[i].down) { |
90cc7194e993
Upstream: excluded down servers from the next_upstream tries.
Ruslan Ermilov <ru@nginx.com>
parents:
7509
diff
changeset
|
136 t += server[i].naddrs; |
90cc7194e993
Upstream: excluded down servers from the next_upstream tries.
Ruslan Ermilov <ru@nginx.com>
parents:
7509
diff
changeset
|
137 } |
6115 | 138 } |
139 | |
140 if (n == 0) { | |
141 return NGX_OK; | |
142 } | |
143 | |
144 backup = ngx_pcalloc(cf->pool, sizeof(ngx_stream_upstream_rr_peers_t)); | |
145 if (backup == NULL) { | |
146 return NGX_ERROR; | |
147 } | |
148 | |
149 peer = ngx_pcalloc(cf->pool, sizeof(ngx_stream_upstream_rr_peer_t) * n); | |
150 if (peer == NULL) { | |
151 return NGX_ERROR; | |
152 } | |
153 | |
154 peers->single = 0; | |
155 backup->single = 0; | |
156 backup->number = n; | |
157 backup->weighted = (w != n); | |
158 backup->total_weight = w; | |
8249
90cc7194e993
Upstream: excluded down servers from the next_upstream tries.
Ruslan Ermilov <ru@nginx.com>
parents:
7509
diff
changeset
|
159 backup->tries = t; |
6115 | 160 backup->name = &us->host; |
161 | |
162 n = 0; | |
163 peerp = &backup->peer; | |
164 | |
165 for (i = 0; i < us->servers->nelts; i++) { | |
166 if (!server[i].backup) { | |
167 continue; | |
168 } | |
169 | |
170 for (j = 0; j < server[i].naddrs; j++) { | |
171 peer[n].sockaddr = server[i].addrs[j].sockaddr; | |
172 peer[n].socklen = server[i].addrs[j].socklen; | |
173 peer[n].name = server[i].addrs[j].name; | |
174 peer[n].weight = server[i].weight; | |
175 peer[n].effective_weight = server[i].weight; | |
176 peer[n].current_weight = 0; | |
6705 | 177 peer[n].max_conns = server[i].max_conns; |
6115 | 178 peer[n].max_fails = server[i].max_fails; |
179 peer[n].fail_timeout = server[i].fail_timeout; | |
180 peer[n].down = server[i].down; | |
181 peer[n].server = server[i].name; | |
182 | |
183 *peerp = &peer[n]; | |
184 peerp = &peer[n].next; | |
185 n++; | |
186 } | |
187 } | |
188 | |
189 peers->next = backup; | |
190 | |
191 return NGX_OK; | |
192 } | |
193 | |
194 | |
195 /* an upstream implicitly defined by proxy_pass, etc. */ | |
196 | |
197 if (us->port == 0) { | |
198 ngx_log_error(NGX_LOG_EMERG, cf->log, 0, | |
199 "no port in upstream \"%V\" in %s:%ui", | |
200 &us->host, us->file_name, us->line); | |
201 return NGX_ERROR; | |
202 } | |
203 | |
204 ngx_memzero(&u, sizeof(ngx_url_t)); | |
205 | |
206 u.host = us->host; | |
207 u.port = us->port; | |
208 | |
209 if (ngx_inet_resolve_host(cf->pool, &u) != NGX_OK) { | |
210 if (u.err) { | |
211 ngx_log_error(NGX_LOG_EMERG, cf->log, 0, | |
212 "%s in upstream \"%V\" in %s:%ui", | |
213 u.err, &us->host, us->file_name, us->line); | |
214 } | |
215 | |
216 return NGX_ERROR; | |
217 } | |
218 | |
219 n = u.naddrs; | |
220 | |
221 peers = ngx_pcalloc(cf->pool, sizeof(ngx_stream_upstream_rr_peers_t)); | |
222 if (peers == NULL) { | |
223 return NGX_ERROR; | |
224 } | |
225 | |
226 peer = ngx_pcalloc(cf->pool, sizeof(ngx_stream_upstream_rr_peer_t) * n); | |
227 if (peer == NULL) { | |
228 return NGX_ERROR; | |
229 } | |
230 | |
231 peers->single = (n == 1); | |
232 peers->number = n; | |
233 peers->weighted = 0; | |
234 peers->total_weight = n; | |
8249
90cc7194e993
Upstream: excluded down servers from the next_upstream tries.
Ruslan Ermilov <ru@nginx.com>
parents:
7509
diff
changeset
|
235 peers->tries = n; |
6115 | 236 peers->name = &us->host; |
237 | |
238 peerp = &peers->peer; | |
239 | |
240 for (i = 0; i < u.naddrs; i++) { | |
241 peer[i].sockaddr = u.addrs[i].sockaddr; | |
242 peer[i].socklen = u.addrs[i].socklen; | |
243 peer[i].name = u.addrs[i].name; | |
244 peer[i].weight = 1; | |
245 peer[i].effective_weight = 1; | |
246 peer[i].current_weight = 0; | |
6705 | 247 peer[i].max_conns = 0; |
6115 | 248 peer[i].max_fails = 1; |
249 peer[i].fail_timeout = 10; | |
250 *peerp = &peer[i]; | |
251 peerp = &peer[i].next; | |
252 } | |
253 | |
254 us->peer.data = peers; | |
255 | |
256 /* implicitly defined upstream has no backup servers */ | |
257 | |
258 return NGX_OK; | |
259 } | |
260 | |
261 | |
262 ngx_int_t | |
263 ngx_stream_upstream_init_round_robin_peer(ngx_stream_session_t *s, | |
264 ngx_stream_upstream_srv_conf_t *us) | |
265 { | |
266 ngx_uint_t n; | |
267 ngx_stream_upstream_rr_peer_data_t *rrp; | |
268 | |
269 rrp = s->upstream->peer.data; | |
270 | |
271 if (rrp == NULL) { | |
272 rrp = ngx_palloc(s->connection->pool, | |
273 sizeof(ngx_stream_upstream_rr_peer_data_t)); | |
274 if (rrp == NULL) { | |
275 return NGX_ERROR; | |
276 } | |
277 | |
278 s->upstream->peer.data = rrp; | |
279 } | |
280 | |
281 rrp->peers = us->peer.data; | |
282 rrp->current = NULL; | |
6712
fd5c2781460b
Modules compatibility: upstream config field.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6706
diff
changeset
|
283 rrp->config = 0; |
6115 | 284 |
285 n = rrp->peers->number; | |
286 | |
287 if (rrp->peers->next && rrp->peers->next->number > n) { | |
288 n = rrp->peers->next->number; | |
289 } | |
290 | |
291 if (n <= 8 * sizeof(uintptr_t)) { | |
292 rrp->tried = &rrp->data; | |
293 rrp->data = 0; | |
294 | |
295 } else { | |
296 n = (n + (8 * sizeof(uintptr_t) - 1)) / (8 * sizeof(uintptr_t)); | |
297 | |
298 rrp->tried = ngx_pcalloc(s->connection->pool, n * sizeof(uintptr_t)); | |
299 if (rrp->tried == NULL) { | |
300 return NGX_ERROR; | |
301 } | |
302 } | |
303 | |
304 s->upstream->peer.get = ngx_stream_upstream_get_round_robin_peer; | |
305 s->upstream->peer.free = ngx_stream_upstream_free_round_robin_peer; | |
6863
54cf51c4f07a
Stream: speed up TCP peer recovery.
Roman Arutyunyan <arut@nginx.com>
parents:
6785
diff
changeset
|
306 s->upstream->peer.notify = ngx_stream_upstream_notify_round_robin_peer; |
6115 | 307 s->upstream->peer.tries = ngx_stream_upstream_tries(rrp->peers); |
308 #if (NGX_STREAM_SSL) | |
309 s->upstream->peer.set_session = | |
310 ngx_stream_upstream_set_round_robin_peer_session; | |
311 s->upstream->peer.save_session = | |
312 ngx_stream_upstream_save_round_robin_peer_session; | |
313 #endif | |
314 | |
315 return NGX_OK; | |
316 } | |
317 | |
318 | |
319 ngx_int_t | |
6643
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
320 ngx_stream_upstream_create_round_robin_peer(ngx_stream_session_t *s, |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
321 ngx_stream_upstream_resolved_t *ur) |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
322 { |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
323 u_char *p; |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
324 size_t len; |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
325 socklen_t socklen; |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
326 ngx_uint_t i, n; |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
327 struct sockaddr *sockaddr; |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
328 ngx_stream_upstream_rr_peer_t *peer, **peerp; |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
329 ngx_stream_upstream_rr_peers_t *peers; |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
330 ngx_stream_upstream_rr_peer_data_t *rrp; |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
331 |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
332 rrp = s->upstream->peer.data; |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
333 |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
334 if (rrp == NULL) { |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
335 rrp = ngx_palloc(s->connection->pool, |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
336 sizeof(ngx_stream_upstream_rr_peer_data_t)); |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
337 if (rrp == NULL) { |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
338 return NGX_ERROR; |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
339 } |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
340 |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
341 s->upstream->peer.data = rrp; |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
342 } |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
343 |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
344 peers = ngx_pcalloc(s->connection->pool, |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
345 sizeof(ngx_stream_upstream_rr_peers_t)); |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
346 if (peers == NULL) { |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
347 return NGX_ERROR; |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
348 } |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
349 |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
350 peer = ngx_pcalloc(s->connection->pool, |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
351 sizeof(ngx_stream_upstream_rr_peer_t) * ur->naddrs); |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
352 if (peer == NULL) { |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
353 return NGX_ERROR; |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
354 } |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
355 |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
356 peers->single = (ur->naddrs == 1); |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
357 peers->number = ur->naddrs; |
8249
90cc7194e993
Upstream: excluded down servers from the next_upstream tries.
Ruslan Ermilov <ru@nginx.com>
parents:
7509
diff
changeset
|
358 peers->tries = ur->naddrs; |
6643
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
359 peers->name = &ur->host; |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
360 |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
361 if (ur->sockaddr) { |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
362 peer[0].sockaddr = ur->sockaddr; |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
363 peer[0].socklen = ur->socklen; |
6785
d1d0dd69a419
Upstream: added the ngx_http_upstream_resolved_t.name field.
Ruslan Ermilov <ru@nginx.com>
parents:
6712
diff
changeset
|
364 peer[0].name = ur->name; |
6643
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
365 peer[0].weight = 1; |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
366 peer[0].effective_weight = 1; |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
367 peer[0].current_weight = 0; |
6706 | 368 peer[0].max_conns = 0; |
6643
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
369 peer[0].max_fails = 1; |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
370 peer[0].fail_timeout = 10; |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
371 peers->peer = peer; |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
372 |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
373 } else { |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
374 peerp = &peers->peer; |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
375 |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
376 for (i = 0; i < ur->naddrs; i++) { |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
377 |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
378 socklen = ur->addrs[i].socklen; |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
379 |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
380 sockaddr = ngx_palloc(s->connection->pool, socklen); |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
381 if (sockaddr == NULL) { |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
382 return NGX_ERROR; |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
383 } |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
384 |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
385 ngx_memcpy(sockaddr, ur->addrs[i].sockaddr, socklen); |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
386 ngx_inet_set_port(sockaddr, ur->port); |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
387 |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
388 p = ngx_pnalloc(s->connection->pool, NGX_SOCKADDR_STRLEN); |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
389 if (p == NULL) { |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
390 return NGX_ERROR; |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
391 } |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
392 |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
393 len = ngx_sock_ntop(sockaddr, socklen, p, NGX_SOCKADDR_STRLEN, 1); |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
394 |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
395 peer[i].sockaddr = sockaddr; |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
396 peer[i].socklen = socklen; |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
397 peer[i].name.len = len; |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
398 peer[i].name.data = p; |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
399 peer[i].weight = 1; |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
400 peer[i].effective_weight = 1; |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
401 peer[i].current_weight = 0; |
6706 | 402 peer[i].max_conns = 0; |
6643
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
403 peer[i].max_fails = 1; |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
404 peer[i].fail_timeout = 10; |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
405 *peerp = &peer[i]; |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
406 peerp = &peer[i].next; |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
407 } |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
408 } |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
409 |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
410 rrp->peers = peers; |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
411 rrp->current = NULL; |
6712
fd5c2781460b
Modules compatibility: upstream config field.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6706
diff
changeset
|
412 rrp->config = 0; |
6643
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
413 |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
414 if (rrp->peers->number <= 8 * sizeof(uintptr_t)) { |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
415 rrp->tried = &rrp->data; |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
416 rrp->data = 0; |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
417 |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
418 } else { |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
419 n = (rrp->peers->number + (8 * sizeof(uintptr_t) - 1)) |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
420 / (8 * sizeof(uintptr_t)); |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
421 |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
422 rrp->tried = ngx_pcalloc(s->connection->pool, n * sizeof(uintptr_t)); |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
423 if (rrp->tried == NULL) { |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
424 return NGX_ERROR; |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
425 } |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
426 } |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
427 |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
428 s->upstream->peer.get = ngx_stream_upstream_get_round_robin_peer; |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
429 s->upstream->peer.free = ngx_stream_upstream_free_round_robin_peer; |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
430 s->upstream->peer.tries = ngx_stream_upstream_tries(rrp->peers); |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
431 #if (NGX_STREAM_SSL) |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
432 s->upstream->peer.set_session = ngx_stream_upstream_empty_set_session; |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
433 s->upstream->peer.save_session = ngx_stream_upstream_empty_save_session; |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
434 #endif |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
435 |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
436 return NGX_OK; |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
437 } |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
438 |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
439 |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
440 ngx_int_t |
6115 | 441 ngx_stream_upstream_get_round_robin_peer(ngx_peer_connection_t *pc, void *data) |
442 { | |
443 ngx_stream_upstream_rr_peer_data_t *rrp = data; | |
444 | |
445 ngx_int_t rc; | |
446 ngx_uint_t i, n; | |
447 ngx_stream_upstream_rr_peer_t *peer; | |
448 ngx_stream_upstream_rr_peers_t *peers; | |
449 | |
450 ngx_log_debug1(NGX_LOG_DEBUG_STREAM, pc->log, 0, | |
451 "get rr peer, try: %ui", pc->tries); | |
452 | |
453 pc->connection = NULL; | |
454 | |
455 peers = rrp->peers; | |
456 ngx_stream_upstream_rr_peers_wlock(peers); | |
457 | |
458 if (peers->single) { | |
459 peer = peers->peer; | |
460 | |
461 if (peer->down) { | |
462 goto failed; | |
463 } | |
464 | |
6705 | 465 if (peer->max_conns && peer->conns >= peer->max_conns) { |
466 goto failed; | |
467 } | |
468 | |
6115 | 469 rrp->current = peer; |
470 | |
471 } else { | |
472 | |
473 /* there are several peers */ | |
474 | |
475 peer = ngx_stream_upstream_get_peer(rrp); | |
476 | |
477 if (peer == NULL) { | |
478 goto failed; | |
479 } | |
480 | |
481 ngx_log_debug2(NGX_LOG_DEBUG_STREAM, pc->log, 0, | |
482 "get rr peer, current: %p %i", | |
483 peer, peer->current_weight); | |
484 } | |
485 | |
486 pc->sockaddr = peer->sockaddr; | |
487 pc->socklen = peer->socklen; | |
488 pc->name = &peer->name; | |
489 | |
490 peer->conns++; | |
491 | |
492 ngx_stream_upstream_rr_peers_unlock(peers); | |
493 | |
494 return NGX_OK; | |
495 | |
496 failed: | |
497 | |
498 if (peers->next) { | |
499 | |
500 ngx_log_debug0(NGX_LOG_DEBUG_STREAM, pc->log, 0, "backup servers"); | |
501 | |
502 rrp->peers = peers->next; | |
503 | |
504 n = (rrp->peers->number + (8 * sizeof(uintptr_t) - 1)) | |
505 / (8 * sizeof(uintptr_t)); | |
506 | |
507 for (i = 0; i < n; i++) { | |
6474 | 508 rrp->tried[i] = 0; |
6115 | 509 } |
510 | |
511 ngx_stream_upstream_rr_peers_unlock(peers); | |
512 | |
513 rc = ngx_stream_upstream_get_round_robin_peer(pc, rrp); | |
514 | |
515 if (rc != NGX_BUSY) { | |
516 return rc; | |
517 } | |
518 | |
519 ngx_stream_upstream_rr_peers_wlock(peers); | |
520 } | |
521 | |
522 ngx_stream_upstream_rr_peers_unlock(peers); | |
523 | |
524 pc->name = peers->name; | |
525 | |
526 return NGX_BUSY; | |
527 } | |
528 | |
529 | |
530 static ngx_stream_upstream_rr_peer_t * | |
531 ngx_stream_upstream_get_peer(ngx_stream_upstream_rr_peer_data_t *rrp) | |
532 { | |
533 time_t now; | |
534 uintptr_t m; | |
535 ngx_int_t total; | |
536 ngx_uint_t i, n, p; | |
537 ngx_stream_upstream_rr_peer_t *peer, *best; | |
538 | |
539 now = ngx_time(); | |
540 | |
541 best = NULL; | |
542 total = 0; | |
543 | |
544 #if (NGX_SUPPRESS_WARN) | |
545 p = 0; | |
546 #endif | |
547 | |
548 for (peer = rrp->peers->peer, i = 0; | |
549 peer; | |
550 peer = peer->next, i++) | |
551 { | |
552 n = i / (8 * sizeof(uintptr_t)); | |
553 m = (uintptr_t) 1 << i % (8 * sizeof(uintptr_t)); | |
554 | |
555 if (rrp->tried[n] & m) { | |
556 continue; | |
557 } | |
558 | |
559 if (peer->down) { | |
560 continue; | |
561 } | |
562 | |
563 if (peer->max_fails | |
564 && peer->fails >= peer->max_fails | |
565 && now - peer->checked <= peer->fail_timeout) | |
566 { | |
567 continue; | |
568 } | |
569 | |
6705 | 570 if (peer->max_conns && peer->conns >= peer->max_conns) { |
571 continue; | |
572 } | |
573 | |
6115 | 574 peer->current_weight += peer->effective_weight; |
575 total += peer->effective_weight; | |
576 | |
577 if (peer->effective_weight < peer->weight) { | |
578 peer->effective_weight++; | |
579 } | |
580 | |
581 if (best == NULL || peer->current_weight > best->current_weight) { | |
582 best = peer; | |
583 p = i; | |
584 } | |
585 } | |
586 | |
587 if (best == NULL) { | |
588 return NULL; | |
589 } | |
590 | |
591 rrp->current = best; | |
592 | |
593 n = p / (8 * sizeof(uintptr_t)); | |
594 m = (uintptr_t) 1 << p % (8 * sizeof(uintptr_t)); | |
595 | |
596 rrp->tried[n] |= m; | |
597 | |
598 best->current_weight -= total; | |
599 | |
600 if (now - best->checked > best->fail_timeout) { | |
601 best->checked = now; | |
602 } | |
603 | |
604 return best; | |
605 } | |
606 | |
607 | |
608 void | |
609 ngx_stream_upstream_free_round_robin_peer(ngx_peer_connection_t *pc, void *data, | |
610 ngx_uint_t state) | |
611 { | |
612 ngx_stream_upstream_rr_peer_data_t *rrp = data; | |
613 | |
614 time_t now; | |
615 ngx_stream_upstream_rr_peer_t *peer; | |
616 | |
617 ngx_log_debug2(NGX_LOG_DEBUG_STREAM, pc->log, 0, | |
618 "free rr peer %ui %ui", pc->tries, state); | |
619 | |
620 peer = rrp->current; | |
621 | |
622 ngx_stream_upstream_rr_peers_rlock(rrp->peers); | |
623 ngx_stream_upstream_rr_peer_lock(rrp->peers, peer); | |
624 | |
625 if (rrp->peers->single) { | |
626 peer->conns--; | |
627 | |
628 ngx_stream_upstream_rr_peer_unlock(rrp->peers, peer); | |
629 ngx_stream_upstream_rr_peers_unlock(rrp->peers); | |
630 | |
631 pc->tries = 0; | |
632 return; | |
633 } | |
634 | |
635 if (state & NGX_PEER_FAILED) { | |
636 now = ngx_time(); | |
637 | |
638 peer->fails++; | |
639 peer->accessed = now; | |
640 peer->checked = now; | |
641 | |
642 if (peer->max_fails) { | |
643 peer->effective_weight -= peer->weight / peer->max_fails; | |
6154
cca856715722
Upstream: report to error_log when max_fails is reached.
Ruslan Ermilov <ru@nginx.com>
parents:
6115
diff
changeset
|
644 |
cca856715722
Upstream: report to error_log when max_fails is reached.
Ruslan Ermilov <ru@nginx.com>
parents:
6115
diff
changeset
|
645 if (peer->fails >= peer->max_fails) { |
cca856715722
Upstream: report to error_log when max_fails is reached.
Ruslan Ermilov <ru@nginx.com>
parents:
6115
diff
changeset
|
646 ngx_log_error(NGX_LOG_WARN, pc->log, 0, |
cca856715722
Upstream: report to error_log when max_fails is reached.
Ruslan Ermilov <ru@nginx.com>
parents:
6115
diff
changeset
|
647 "upstream server temporarily disabled"); |
cca856715722
Upstream: report to error_log when max_fails is reached.
Ruslan Ermilov <ru@nginx.com>
parents:
6115
diff
changeset
|
648 } |
6115 | 649 } |
650 | |
651 ngx_log_debug2(NGX_LOG_DEBUG_STREAM, pc->log, 0, | |
652 "free rr peer failed: %p %i", | |
653 peer, peer->effective_weight); | |
654 | |
655 if (peer->effective_weight < 0) { | |
656 peer->effective_weight = 0; | |
657 } | |
658 | |
659 } else { | |
660 | |
661 /* mark peer live if check passed */ | |
662 | |
663 if (peer->accessed < peer->checked) { | |
664 peer->fails = 0; | |
665 } | |
666 } | |
667 | |
668 peer->conns--; | |
669 | |
670 ngx_stream_upstream_rr_peer_unlock(rrp->peers, peer); | |
671 ngx_stream_upstream_rr_peers_unlock(rrp->peers); | |
672 | |
673 if (pc->tries) { | |
674 pc->tries--; | |
675 } | |
676 } | |
677 | |
678 | |
6863
54cf51c4f07a
Stream: speed up TCP peer recovery.
Roman Arutyunyan <arut@nginx.com>
parents:
6785
diff
changeset
|
679 static void |
54cf51c4f07a
Stream: speed up TCP peer recovery.
Roman Arutyunyan <arut@nginx.com>
parents:
6785
diff
changeset
|
680 ngx_stream_upstream_notify_round_robin_peer(ngx_peer_connection_t *pc, |
54cf51c4f07a
Stream: speed up TCP peer recovery.
Roman Arutyunyan <arut@nginx.com>
parents:
6785
diff
changeset
|
681 void *data, ngx_uint_t type) |
54cf51c4f07a
Stream: speed up TCP peer recovery.
Roman Arutyunyan <arut@nginx.com>
parents:
6785
diff
changeset
|
682 { |
54cf51c4f07a
Stream: speed up TCP peer recovery.
Roman Arutyunyan <arut@nginx.com>
parents:
6785
diff
changeset
|
683 ngx_stream_upstream_rr_peer_data_t *rrp = data; |
54cf51c4f07a
Stream: speed up TCP peer recovery.
Roman Arutyunyan <arut@nginx.com>
parents:
6785
diff
changeset
|
684 |
54cf51c4f07a
Stream: speed up TCP peer recovery.
Roman Arutyunyan <arut@nginx.com>
parents:
6785
diff
changeset
|
685 ngx_stream_upstream_rr_peer_t *peer; |
54cf51c4f07a
Stream: speed up TCP peer recovery.
Roman Arutyunyan <arut@nginx.com>
parents:
6785
diff
changeset
|
686 |
54cf51c4f07a
Stream: speed up TCP peer recovery.
Roman Arutyunyan <arut@nginx.com>
parents:
6785
diff
changeset
|
687 peer = rrp->current; |
54cf51c4f07a
Stream: speed up TCP peer recovery.
Roman Arutyunyan <arut@nginx.com>
parents:
6785
diff
changeset
|
688 |
54cf51c4f07a
Stream: speed up TCP peer recovery.
Roman Arutyunyan <arut@nginx.com>
parents:
6785
diff
changeset
|
689 if (type == NGX_STREAM_UPSTREAM_NOTIFY_CONNECT |
54cf51c4f07a
Stream: speed up TCP peer recovery.
Roman Arutyunyan <arut@nginx.com>
parents:
6785
diff
changeset
|
690 && pc->connection->type == SOCK_STREAM) |
54cf51c4f07a
Stream: speed up TCP peer recovery.
Roman Arutyunyan <arut@nginx.com>
parents:
6785
diff
changeset
|
691 { |
54cf51c4f07a
Stream: speed up TCP peer recovery.
Roman Arutyunyan <arut@nginx.com>
parents:
6785
diff
changeset
|
692 ngx_stream_upstream_rr_peers_rlock(rrp->peers); |
54cf51c4f07a
Stream: speed up TCP peer recovery.
Roman Arutyunyan <arut@nginx.com>
parents:
6785
diff
changeset
|
693 ngx_stream_upstream_rr_peer_lock(rrp->peers, peer); |
54cf51c4f07a
Stream: speed up TCP peer recovery.
Roman Arutyunyan <arut@nginx.com>
parents:
6785
diff
changeset
|
694 |
54cf51c4f07a
Stream: speed up TCP peer recovery.
Roman Arutyunyan <arut@nginx.com>
parents:
6785
diff
changeset
|
695 if (peer->accessed < peer->checked) { |
54cf51c4f07a
Stream: speed up TCP peer recovery.
Roman Arutyunyan <arut@nginx.com>
parents:
6785
diff
changeset
|
696 peer->fails = 0; |
54cf51c4f07a
Stream: speed up TCP peer recovery.
Roman Arutyunyan <arut@nginx.com>
parents:
6785
diff
changeset
|
697 } |
54cf51c4f07a
Stream: speed up TCP peer recovery.
Roman Arutyunyan <arut@nginx.com>
parents:
6785
diff
changeset
|
698 |
54cf51c4f07a
Stream: speed up TCP peer recovery.
Roman Arutyunyan <arut@nginx.com>
parents:
6785
diff
changeset
|
699 ngx_stream_upstream_rr_peer_unlock(rrp->peers, peer); |
54cf51c4f07a
Stream: speed up TCP peer recovery.
Roman Arutyunyan <arut@nginx.com>
parents:
6785
diff
changeset
|
700 ngx_stream_upstream_rr_peers_unlock(rrp->peers); |
54cf51c4f07a
Stream: speed up TCP peer recovery.
Roman Arutyunyan <arut@nginx.com>
parents:
6785
diff
changeset
|
701 } |
54cf51c4f07a
Stream: speed up TCP peer recovery.
Roman Arutyunyan <arut@nginx.com>
parents:
6785
diff
changeset
|
702 } |
54cf51c4f07a
Stream: speed up TCP peer recovery.
Roman Arutyunyan <arut@nginx.com>
parents:
6785
diff
changeset
|
703 |
54cf51c4f07a
Stream: speed up TCP peer recovery.
Roman Arutyunyan <arut@nginx.com>
parents:
6785
diff
changeset
|
704 |
6115 | 705 #if (NGX_STREAM_SSL) |
706 | |
707 static ngx_int_t | |
708 ngx_stream_upstream_set_round_robin_peer_session(ngx_peer_connection_t *pc, | |
709 void *data) | |
710 { | |
711 ngx_stream_upstream_rr_peer_data_t *rrp = data; | |
712 | |
713 ngx_int_t rc; | |
714 ngx_ssl_session_t *ssl_session; | |
715 ngx_stream_upstream_rr_peer_t *peer; | |
716 #if (NGX_STREAM_UPSTREAM_ZONE) | |
717 int len; | |
7509
b99cbafd51da
SSL: removed OpenSSL 0.9.7 compatibility.
Sergey Kandaurov <pluknet@nginx.com>
parents:
7320
diff
changeset
|
718 const u_char *p; |
6115 | 719 ngx_stream_upstream_rr_peers_t *peers; |
720 u_char buf[NGX_SSL_MAX_SESSION_SIZE]; | |
721 #endif | |
722 | |
723 peer = rrp->current; | |
724 | |
725 #if (NGX_STREAM_UPSTREAM_ZONE) | |
726 peers = rrp->peers; | |
727 | |
728 if (peers->shpool) { | |
729 ngx_stream_upstream_rr_peers_rlock(peers); | |
730 ngx_stream_upstream_rr_peer_lock(peers, peer); | |
731 | |
732 if (peer->ssl_session == NULL) { | |
733 ngx_stream_upstream_rr_peer_unlock(peers, peer); | |
734 ngx_stream_upstream_rr_peers_unlock(peers); | |
735 return NGX_OK; | |
736 } | |
737 | |
738 len = peer->ssl_session_len; | |
739 | |
740 ngx_memcpy(buf, peer->ssl_session, len); | |
741 | |
742 ngx_stream_upstream_rr_peer_unlock(peers, peer); | |
743 ngx_stream_upstream_rr_peers_unlock(peers); | |
744 | |
745 p = buf; | |
746 ssl_session = d2i_SSL_SESSION(NULL, &p, len); | |
747 | |
748 rc = ngx_ssl_set_session(pc->connection, ssl_session); | |
749 | |
750 ngx_log_debug1(NGX_LOG_DEBUG_STREAM, pc->log, 0, | |
751 "set session: %p", ssl_session); | |
752 | |
753 ngx_ssl_free_session(ssl_session); | |
754 | |
755 return rc; | |
756 } | |
757 #endif | |
758 | |
759 ssl_session = peer->ssl_session; | |
760 | |
761 rc = ngx_ssl_set_session(pc->connection, ssl_session); | |
762 | |
763 ngx_log_debug1(NGX_LOG_DEBUG_STREAM, pc->log, 0, | |
764 "set session: %p", ssl_session); | |
765 | |
766 return rc; | |
767 } | |
768 | |
769 | |
770 static void | |
771 ngx_stream_upstream_save_round_robin_peer_session(ngx_peer_connection_t *pc, | |
772 void *data) | |
773 { | |
774 ngx_stream_upstream_rr_peer_data_t *rrp = data; | |
775 | |
776 ngx_ssl_session_t *old_ssl_session, *ssl_session; | |
777 ngx_stream_upstream_rr_peer_t *peer; | |
778 #if (NGX_STREAM_UPSTREAM_ZONE) | |
779 int len; | |
780 u_char *p; | |
781 ngx_stream_upstream_rr_peers_t *peers; | |
782 u_char buf[NGX_SSL_MAX_SESSION_SIZE]; | |
783 #endif | |
784 | |
785 #if (NGX_STREAM_UPSTREAM_ZONE) | |
786 peers = rrp->peers; | |
787 | |
788 if (peers->shpool) { | |
789 | |
7320
696df3ac27ac
SSL: save sessions for upstream peers using a callback function.
Sergey Kandaurov <pluknet@nginx.com>
parents:
6863
diff
changeset
|
790 ssl_session = ngx_ssl_get0_session(pc->connection); |
6115 | 791 |
792 if (ssl_session == NULL) { | |
793 return; | |
794 } | |
795 | |
796 ngx_log_debug1(NGX_LOG_DEBUG_STREAM, pc->log, 0, | |
797 "save session: %p", ssl_session); | |
798 | |
799 len = i2d_SSL_SESSION(ssl_session, NULL); | |
800 | |
801 /* do not cache too big session */ | |
802 | |
803 if (len > NGX_SSL_MAX_SESSION_SIZE) { | |
804 return; | |
805 } | |
806 | |
807 p = buf; | |
808 (void) i2d_SSL_SESSION(ssl_session, &p); | |
809 | |
810 peer = rrp->current; | |
811 | |
812 ngx_stream_upstream_rr_peers_rlock(peers); | |
813 ngx_stream_upstream_rr_peer_lock(peers, peer); | |
814 | |
815 if (len > peer->ssl_session_len) { | |
816 ngx_shmtx_lock(&peers->shpool->mutex); | |
817 | |
818 if (peer->ssl_session) { | |
819 ngx_slab_free_locked(peers->shpool, peer->ssl_session); | |
820 } | |
821 | |
822 peer->ssl_session = ngx_slab_alloc_locked(peers->shpool, len); | |
823 | |
824 ngx_shmtx_unlock(&peers->shpool->mutex); | |
825 | |
826 if (peer->ssl_session == NULL) { | |
827 peer->ssl_session_len = 0; | |
828 | |
829 ngx_stream_upstream_rr_peer_unlock(peers, peer); | |
830 ngx_stream_upstream_rr_peers_unlock(peers); | |
831 return; | |
832 } | |
833 | |
834 peer->ssl_session_len = len; | |
835 } | |
836 | |
837 ngx_memcpy(peer->ssl_session, buf, len); | |
838 | |
839 ngx_stream_upstream_rr_peer_unlock(peers, peer); | |
840 ngx_stream_upstream_rr_peers_unlock(peers); | |
841 | |
842 return; | |
843 } | |
844 #endif | |
845 | |
846 ssl_session = ngx_ssl_get_session(pc->connection); | |
847 | |
848 if (ssl_session == NULL) { | |
849 return; | |
850 } | |
851 | |
852 ngx_log_debug1(NGX_LOG_DEBUG_STREAM, pc->log, 0, | |
853 "save session: %p", ssl_session); | |
854 | |
855 peer = rrp->current; | |
856 | |
857 old_ssl_session = peer->ssl_session; | |
858 peer->ssl_session = ssl_session; | |
859 | |
860 if (old_ssl_session) { | |
861 | |
862 ngx_log_debug1(NGX_LOG_DEBUG_STREAM, pc->log, 0, | |
863 "old session: %p", old_ssl_session); | |
864 | |
865 /* TODO: may block */ | |
866 | |
867 ngx_ssl_free_session(old_ssl_session); | |
868 } | |
869 } | |
870 | |
6643
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
871 |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
872 static ngx_int_t |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
873 ngx_stream_upstream_empty_set_session(ngx_peer_connection_t *pc, void *data) |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
874 { |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
875 return NGX_OK; |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
876 } |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
877 |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
878 |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
879 static void |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
880 ngx_stream_upstream_empty_save_session(ngx_peer_connection_t *pc, void *data) |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
881 { |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
882 return; |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
883 } |
9757cffc1e2f
Stream: variables in proxy_pass and proxy_ssl_name.
Vladimir Homutov <vl@nginx.com>
parents:
6474
diff
changeset
|
884 |
6115 | 885 #endif |