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