blob: 2b4ce7aff2d1d2eaf88d6282eb285ead4d8ccfcb [file] [log] [blame]
Igor Sysoev3d2fd182006-12-04 16:46:13 +00001
2/*
3 * Copyright (C) Igor Sysoev
Maxim Konovalovf8d59e32012-01-18 15:07:43 +00004 * Copyright (C) Nginx, Inc.
Igor Sysoev3d2fd182006-12-04 16:46:13 +00005 */
6
7
8#include <ngx_config.h>
9#include <ngx_core.h>
10#include <ngx_http.h>
11
12
Maxim Dounin52327e02012-05-14 09:57:20 +000013static ngx_http_upstream_rr_peer_t *ngx_http_upstream_get_peer(
14 ngx_http_upstream_rr_peer_data_t *rrp);
Igor Sysoevd12a5712007-07-28 16:04:01 +000015
Igor Sysoev08b59752011-07-22 16:30:17 +000016#if (NGX_HTTP_SSL)
17
18static ngx_int_t ngx_http_upstream_empty_set_session(ngx_peer_connection_t *pc,
19 void *data);
20static void ngx_http_upstream_empty_save_session(ngx_peer_connection_t *pc,
21 void *data);
22
23#endif
24
Igor Sysoevd12a5712007-07-28 16:04:01 +000025
Igor Sysoev3d2fd182006-12-04 16:46:13 +000026ngx_int_t
27ngx_http_upstream_init_round_robin(ngx_conf_t *cf,
28 ngx_http_upstream_srv_conf_t *us)
29{
30 ngx_url_t u;
Maxim Dounin1ba6ecd2012-06-03 23:22:41 +000031 ngx_uint_t i, j, n, w;
Igor Sysoev3d2fd182006-12-04 16:46:13 +000032 ngx_http_upstream_server_t *server;
Igor Sysoev6876bcd2007-08-09 13:54:33 +000033 ngx_http_upstream_rr_peers_t *peers, *backup;
Igor Sysoev3d2fd182006-12-04 16:46:13 +000034
35 us->peer.init = ngx_http_upstream_init_round_robin_peer;
36
37 if (us->servers) {
Igor Sysoev3d2fd182006-12-04 16:46:13 +000038 server = us->servers->elts;
39
Igor Sysoev6876bcd2007-08-09 13:54:33 +000040 n = 0;
Maxim Dounin1ba6ecd2012-06-03 23:22:41 +000041 w = 0;
Igor Sysoev6876bcd2007-08-09 13:54:33 +000042
Igor Sysoev3d2fd182006-12-04 16:46:13 +000043 for (i = 0; i < us->servers->nelts; i++) {
Igor Sysoev6876bcd2007-08-09 13:54:33 +000044 if (server[i].backup) {
45 continue;
46 }
47
Igor Sysoev3d2fd182006-12-04 16:46:13 +000048 n += server[i].naddrs;
Maxim Dounin1ba6ecd2012-06-03 23:22:41 +000049 w += server[i].naddrs * server[i].weight;
Igor Sysoev3d2fd182006-12-04 16:46:13 +000050 }
51
Maxim Dounina5d4f662012-04-02 21:29:35 +000052 if (n == 0) {
53 ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
54 "no servers in upstream \"%V\" in %s:%ui",
55 &us->host, us->file_name, us->line);
56 return NGX_ERROR;
57 }
58
Igor Sysoev3d2fd182006-12-04 16:46:13 +000059 peers = ngx_pcalloc(cf->pool, sizeof(ngx_http_upstream_rr_peers_t)
60 + sizeof(ngx_http_upstream_rr_peer_t) * (n - 1));
61 if (peers == NULL) {
62 return NGX_ERROR;
63 }
64
Igor Sysoev6876bcd2007-08-09 13:54:33 +000065 peers->single = (n == 1);
Igor Sysoev3d2fd182006-12-04 16:46:13 +000066 peers->number = n;
Maxim Dounin1ba6ecd2012-06-03 23:22:41 +000067 peers->weighted = (w != n);
68 peers->total_weight = w;
Igor Sysoev3d2fd182006-12-04 16:46:13 +000069 peers->name = &us->host;
70
71 n = 0;
72
73 for (i = 0; i < us->servers->nelts; i++) {
Xiaochen Wang8f3dfde2013-10-21 18:20:32 +080074 if (server[i].backup) {
75 continue;
76 }
Igor Sysoev6876bcd2007-08-09 13:54:33 +000077
Xiaochen Wang8f3dfde2013-10-21 18:20:32 +080078 for (j = 0; j < server[i].naddrs; j++) {
Igor Sysoev3d2fd182006-12-04 16:46:13 +000079 peers->peer[n].sockaddr = server[i].addrs[j].sockaddr;
80 peers->peer[n].socklen = server[i].addrs[j].socklen;
81 peers->peer[n].name = server[i].addrs[j].name;
Maxim Dounin4d5759e2012-05-14 09:58:07 +000082 peers->peer[n].weight = server[i].weight;
83 peers->peer[n].effective_weight = server[i].weight;
Maxim Dounin52327e02012-05-14 09:57:20 +000084 peers->peer[n].current_weight = 0;
Vladimir Homutov71b9cca2013-12-03 17:12:16 +040085 peers->peer[n].max_fails = server[i].max_fails;
86 peers->peer[n].fail_timeout = server[i].fail_timeout;
87 peers->peer[n].down = server[i].down;
Igor Sysoev3d2fd182006-12-04 16:46:13 +000088 n++;
89 }
90 }
91
92 us->peer.data = peers;
93
Igor Sysoev6876bcd2007-08-09 13:54:33 +000094 /* backup servers */
95
96 n = 0;
Maxim Dounin1ba6ecd2012-06-03 23:22:41 +000097 w = 0;
Igor Sysoev6876bcd2007-08-09 13:54:33 +000098
99 for (i = 0; i < us->servers->nelts; i++) {
100 if (!server[i].backup) {
101 continue;
102 }
103
104 n += server[i].naddrs;
Maxim Dounin1ba6ecd2012-06-03 23:22:41 +0000105 w += server[i].naddrs * server[i].weight;
Igor Sysoev6876bcd2007-08-09 13:54:33 +0000106 }
107
108 if (n == 0) {
109 return NGX_OK;
110 }
111
112 backup = ngx_pcalloc(cf->pool, sizeof(ngx_http_upstream_rr_peers_t)
113 + sizeof(ngx_http_upstream_rr_peer_t) * (n - 1));
114 if (backup == NULL) {
115 return NGX_ERROR;
116 }
117
118 peers->single = 0;
119 backup->single = 0;
120 backup->number = n;
Maxim Dounin1ba6ecd2012-06-03 23:22:41 +0000121 backup->weighted = (w != n);
122 backup->total_weight = w;
Igor Sysoev6876bcd2007-08-09 13:54:33 +0000123 backup->name = &us->host;
124
125 n = 0;
126
127 for (i = 0; i < us->servers->nelts; i++) {
Xiaochen Wang8f3dfde2013-10-21 18:20:32 +0800128 if (!server[i].backup) {
129 continue;
130 }
Igor Sysoev6876bcd2007-08-09 13:54:33 +0000131
Xiaochen Wang8f3dfde2013-10-21 18:20:32 +0800132 for (j = 0; j < server[i].naddrs; j++) {
Igor Sysoev6876bcd2007-08-09 13:54:33 +0000133 backup->peer[n].sockaddr = server[i].addrs[j].sockaddr;
134 backup->peer[n].socklen = server[i].addrs[j].socklen;
135 backup->peer[n].name = server[i].addrs[j].name;
136 backup->peer[n].weight = server[i].weight;
Maxim Dounin52327e02012-05-14 09:57:20 +0000137 backup->peer[n].effective_weight = server[i].weight;
138 backup->peer[n].current_weight = 0;
Igor Sysoev6876bcd2007-08-09 13:54:33 +0000139 backup->peer[n].max_fails = server[i].max_fails;
140 backup->peer[n].fail_timeout = server[i].fail_timeout;
141 backup->peer[n].down = server[i].down;
142 n++;
143 }
144 }
145
146 peers->next = backup;
147
Igor Sysoev3d2fd182006-12-04 16:46:13 +0000148 return NGX_OK;
149 }
150
151
152 /* an upstream implicitly defined by proxy_pass, etc. */
153
Ruslan Ermilova2a22912013-01-10 12:58:55 +0000154 if (us->port == 0) {
Igor Sysoevbf3aaac2006-12-12 16:46:16 +0000155 ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
156 "no port in upstream \"%V\" in %s:%ui",
Igor Sysoev4b96baa2007-09-15 17:11:06 +0000157 &us->host, us->file_name, us->line);
Igor Sysoevbf3aaac2006-12-12 16:46:16 +0000158 return NGX_ERROR;
159 }
160
Igor Sysoev3d2fd182006-12-04 16:46:13 +0000161 ngx_memzero(&u, sizeof(ngx_url_t));
162
163 u.host = us->host;
Ruslan Ermilova2a22912013-01-10 12:58:55 +0000164 u.port = us->port;
Igor Sysoev3d2fd182006-12-04 16:46:13 +0000165
Igor Sysoev7ed63ee2007-10-08 08:55:12 +0000166 if (ngx_inet_resolve_host(cf->pool, &u) != NGX_OK) {
Igor Sysoev3d2fd182006-12-04 16:46:13 +0000167 if (u.err) {
168 ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
Igor Sysoev5d118d32006-12-11 08:59:30 +0000169 "%s in upstream \"%V\" in %s:%ui",
Igor Sysoev4b96baa2007-09-15 17:11:06 +0000170 u.err, &us->host, us->file_name, us->line);
Igor Sysoev3d2fd182006-12-04 16:46:13 +0000171 }
172
173 return NGX_ERROR;
174 }
175
Igor Sysoev3d2fd182006-12-04 16:46:13 +0000176 n = u.naddrs;
177
178 peers = ngx_pcalloc(cf->pool, sizeof(ngx_http_upstream_rr_peers_t)
179 + sizeof(ngx_http_upstream_rr_peer_t) * (n - 1));
180 if (peers == NULL) {
181 return NGX_ERROR;
182 }
183
Igor Sysoev6876bcd2007-08-09 13:54:33 +0000184 peers->single = (n == 1);
Igor Sysoev3d2fd182006-12-04 16:46:13 +0000185 peers->number = n;
Maxim Dounin1ba6ecd2012-06-03 23:22:41 +0000186 peers->weighted = 0;
187 peers->total_weight = n;
Igor Sysoev3d2fd182006-12-04 16:46:13 +0000188 peers->name = &us->host;
189
Igor Sysoev3d2fd182006-12-04 16:46:13 +0000190 for (i = 0; i < u.naddrs; i++) {
Igor Sysoev47a1ebb2007-10-10 13:58:47 +0000191 peers->peer[i].sockaddr = u.addrs[i].sockaddr;
192 peers->peer[i].socklen = u.addrs[i].socklen;
193 peers->peer[i].name = u.addrs[i].name;
194 peers->peer[i].weight = 1;
Maxim Dounin52327e02012-05-14 09:57:20 +0000195 peers->peer[i].effective_weight = 1;
196 peers->peer[i].current_weight = 0;
Igor Sysoev47a1ebb2007-10-10 13:58:47 +0000197 peers->peer[i].max_fails = 1;
198 peers->peer[i].fail_timeout = 10;
Igor Sysoev3d2fd182006-12-04 16:46:13 +0000199 }
200
201 us->peer.data = peers;
202
Igor Sysoev6876bcd2007-08-09 13:54:33 +0000203 /* implicitly defined upstream has no backup servers */
204
Igor Sysoev3d2fd182006-12-04 16:46:13 +0000205 return NGX_OK;
206}
207
208
209ngx_int_t
210ngx_http_upstream_init_round_robin_peer(ngx_http_request_t *r,
211 ngx_http_upstream_srv_conf_t *us)
212{
213 ngx_uint_t n;
214 ngx_http_upstream_rr_peer_data_t *rrp;
215
216 rrp = r->upstream->peer.data;
217
218 if (rrp == NULL) {
219 rrp = ngx_palloc(r->pool, sizeof(ngx_http_upstream_rr_peer_data_t));
220 if (rrp == NULL) {
221 return NGX_ERROR;
222 }
223
224 r->upstream->peer.data = rrp;
225 }
226
227 rrp->peers = us->peer.data;
228 rrp->current = 0;
229
Maxim Douninb7fcb432011-08-18 17:04:52 +0000230 n = rrp->peers->number;
231
232 if (rrp->peers->next && rrp->peers->next->number > n) {
233 n = rrp->peers->next->number;
234 }
235
236 if (n <= 8 * sizeof(uintptr_t)) {
Igor Sysoev3d2fd182006-12-04 16:46:13 +0000237 rrp->tried = &rrp->data;
238 rrp->data = 0;
239
240 } else {
Maxim Douninb7fcb432011-08-18 17:04:52 +0000241 n = (n + (8 * sizeof(uintptr_t) - 1)) / (8 * sizeof(uintptr_t));
Igor Sysoev3d2fd182006-12-04 16:46:13 +0000242
243 rrp->tried = ngx_pcalloc(r->pool, n * sizeof(uintptr_t));
244 if (rrp->tried == NULL) {
245 return NGX_ERROR;
246 }
247 }
248
249 r->upstream->peer.get = ngx_http_upstream_get_round_robin_peer;
250 r->upstream->peer.free = ngx_http_upstream_free_round_robin_peer;
251 r->upstream->peer.tries = rrp->peers->number;
252#if (NGX_HTTP_SSL)
Igor Sysoev8b0a3d22007-07-10 21:04:37 +0000253 r->upstream->peer.set_session =
254 ngx_http_upstream_set_round_robin_peer_session;
255 r->upstream->peer.save_session =
256 ngx_http_upstream_save_round_robin_peer_session;
Igor Sysoev3d2fd182006-12-04 16:46:13 +0000257#endif
258
259 return NGX_OK;
260}
261
262
263ngx_int_t
Igor Sysoev96dd8af2007-11-27 13:34:13 +0000264ngx_http_upstream_create_round_robin_peer(ngx_http_request_t *r,
265 ngx_http_upstream_resolved_t *ur)
266{
267 u_char *p;
268 size_t len;
269 ngx_uint_t i, n;
270 struct sockaddr_in *sin;
271 ngx_http_upstream_rr_peers_t *peers;
272 ngx_http_upstream_rr_peer_data_t *rrp;
273
274 rrp = r->upstream->peer.data;
275
276 if (rrp == NULL) {
277 rrp = ngx_palloc(r->pool, sizeof(ngx_http_upstream_rr_peer_data_t));
278 if (rrp == NULL) {
279 return NGX_ERROR;
280 }
281
282 r->upstream->peer.data = rrp;
283 }
284
285 peers = ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_rr_peers_t)
286 + sizeof(ngx_http_upstream_rr_peer_t) * (ur->naddrs - 1));
287 if (peers == NULL) {
288 return NGX_ERROR;
289 }
290
291 peers->single = (ur->naddrs == 1);
292 peers->number = ur->naddrs;
293 peers->name = &ur->host;
294
Igor Sysoev302cedc2008-12-23 19:35:12 +0000295 if (ur->sockaddr) {
296 peers->peer[0].sockaddr = ur->sockaddr;
297 peers->peer[0].socklen = ur->socklen;
298 peers->peer[0].name = ur->host;
299 peers->peer[0].weight = 1;
Maxim Dounin52327e02012-05-14 09:57:20 +0000300 peers->peer[0].effective_weight = 1;
301 peers->peer[0].current_weight = 0;
Igor Sysoev302cedc2008-12-23 19:35:12 +0000302 peers->peer[0].max_fails = 1;
303 peers->peer[0].fail_timeout = 10;
Igor Sysoev96dd8af2007-11-27 13:34:13 +0000304
Igor Sysoev302cedc2008-12-23 19:35:12 +0000305 } else {
Igor Sysoev96dd8af2007-11-27 13:34:13 +0000306
Igor Sysoev302cedc2008-12-23 19:35:12 +0000307 for (i = 0; i < ur->naddrs; i++) {
308
309 len = NGX_INET_ADDRSTRLEN + sizeof(":65536") - 1;
310
311 p = ngx_pnalloc(r->pool, len);
312 if (p == NULL) {
313 return NGX_ERROR;
314 }
315
316 len = ngx_inet_ntop(AF_INET, &ur->addrs[i], p, NGX_INET_ADDRSTRLEN);
317 len = ngx_sprintf(&p[len], ":%d", ur->port) - p;
318
319 sin = ngx_pcalloc(r->pool, sizeof(struct sockaddr_in));
320 if (sin == NULL) {
321 return NGX_ERROR;
322 }
323
324 sin->sin_family = AF_INET;
325 sin->sin_port = htons(ur->port);
326 sin->sin_addr.s_addr = ur->addrs[i];
327
328 peers->peer[i].sockaddr = (struct sockaddr *) sin;
329 peers->peer[i].socklen = sizeof(struct sockaddr_in);
330 peers->peer[i].name.len = len;
331 peers->peer[i].name.data = p;
332 peers->peer[i].weight = 1;
Maxim Dounin52327e02012-05-14 09:57:20 +0000333 peers->peer[i].effective_weight = 1;
334 peers->peer[i].current_weight = 0;
Igor Sysoev302cedc2008-12-23 19:35:12 +0000335 peers->peer[i].max_fails = 1;
336 peers->peer[i].fail_timeout = 10;
Igor Sysoev96dd8af2007-11-27 13:34:13 +0000337 }
Igor Sysoev96dd8af2007-11-27 13:34:13 +0000338 }
339
340 rrp->peers = peers;
341 rrp->current = 0;
342
343 if (rrp->peers->number <= 8 * sizeof(uintptr_t)) {
344 rrp->tried = &rrp->data;
345 rrp->data = 0;
346
347 } else {
348 n = (rrp->peers->number + (8 * sizeof(uintptr_t) - 1))
349 / (8 * sizeof(uintptr_t));
350
351 rrp->tried = ngx_pcalloc(r->pool, n * sizeof(uintptr_t));
352 if (rrp->tried == NULL) {
353 return NGX_ERROR;
354 }
355 }
356
357 r->upstream->peer.get = ngx_http_upstream_get_round_robin_peer;
358 r->upstream->peer.free = ngx_http_upstream_free_round_robin_peer;
359 r->upstream->peer.tries = rrp->peers->number;
360#if (NGX_HTTP_SSL)
Igor Sysoev08b59752011-07-22 16:30:17 +0000361 r->upstream->peer.set_session = ngx_http_upstream_empty_set_session;
362 r->upstream->peer.save_session = ngx_http_upstream_empty_save_session;
Igor Sysoev96dd8af2007-11-27 13:34:13 +0000363#endif
364
365 return NGX_OK;
366}
367
368
369ngx_int_t
Igor Sysoev3d2fd182006-12-04 16:46:13 +0000370ngx_http_upstream_get_round_robin_peer(ngx_peer_connection_t *pc, void *data)
371{
372 ngx_http_upstream_rr_peer_data_t *rrp = data;
373
Igor Sysoev6876bcd2007-08-09 13:54:33 +0000374 ngx_int_t rc;
375 ngx_uint_t i, n;
Igor Sysoev6876bcd2007-08-09 13:54:33 +0000376 ngx_http_upstream_rr_peer_t *peer;
377 ngx_http_upstream_rr_peers_t *peers;
Igor Sysoev3d2fd182006-12-04 16:46:13 +0000378
379 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0,
380 "get rr peer, try: %ui", pc->tries);
381
Igor Sysoev3d2fd182006-12-04 16:46:13 +0000382 /* ngx_lock_mutex(rrp->peers->mutex); */
383
Igor Sysoev3d2fd182006-12-04 16:46:13 +0000384 pc->cached = 0;
385 pc->connection = NULL;
386
Igor Sysoev6876bcd2007-08-09 13:54:33 +0000387 if (rrp->peers->single) {
Igor Sysoev3d2fd182006-12-04 16:46:13 +0000388 peer = &rrp->peers->peer[0];
389
Ruslan Ermilov4d0d2b22012-11-16 12:18:05 +0000390 if (peer->down) {
391 goto failed;
392 }
393
Igor Sysoev3d2fd182006-12-04 16:46:13 +0000394 } else {
395
396 /* there are several peers */
397
Maxim Dounin52327e02012-05-14 09:57:20 +0000398 peer = ngx_http_upstream_get_peer(rrp);
Igor Sysoev3d2fd182006-12-04 16:46:13 +0000399
Maxim Dounin52327e02012-05-14 09:57:20 +0000400 if (peer == NULL) {
401 goto failed;
Igor Sysoev3d2fd182006-12-04 16:46:13 +0000402 }
403
Maxim Dounin52327e02012-05-14 09:57:20 +0000404 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, pc->log, 0,
405 "get rr peer, current: %ui %i",
406 rrp->current, peer->current_weight);
Igor Sysoev3d2fd182006-12-04 16:46:13 +0000407 }
408
409 pc->sockaddr = peer->sockaddr;
410 pc->socklen = peer->socklen;
411 pc->name = &peer->name;
Igor Sysoev3d2fd182006-12-04 16:46:13 +0000412
413 /* ngx_unlock_mutex(rrp->peers->mutex); */
414
Igor Sysoev6876bcd2007-08-09 13:54:33 +0000415 if (pc->tries == 1 && rrp->peers->next) {
416 pc->tries += rrp->peers->next->number;
Igor Sysoev6876bcd2007-08-09 13:54:33 +0000417 }
418
Igor Sysoev3d2fd182006-12-04 16:46:13 +0000419 return NGX_OK;
420
421failed:
422
Igor Sysoev6876bcd2007-08-09 13:54:33 +0000423 peers = rrp->peers;
Igor Sysoev3d2fd182006-12-04 16:46:13 +0000424
Igor Sysoev6876bcd2007-08-09 13:54:33 +0000425 if (peers->next) {
426
427 /* ngx_unlock_mutex(peers->mutex); */
428
429 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, pc->log, 0, "backup servers");
430
431 rrp->peers = peers->next;
432 pc->tries = rrp->peers->number;
433
Valentin Bartenevdd46cc62012-12-25 08:02:21 +0000434 n = (rrp->peers->number + (8 * sizeof(uintptr_t) - 1))
435 / (8 * sizeof(uintptr_t));
436
Igor Sysoevcc076092007-08-14 13:35:52 +0000437 for (i = 0; i < n; i++) {
Igor Sysoev6876bcd2007-08-09 13:54:33 +0000438 rrp->tried[i] = 0;
439 }
440
441 rc = ngx_http_upstream_get_round_robin_peer(pc, rrp);
442
443 if (rc != NGX_BUSY) {
444 return rc;
445 }
446
447 /* ngx_lock_mutex(peers->mutex); */
Igor Sysoev3d2fd182006-12-04 16:46:13 +0000448 }
449
Igor Sysoev6876bcd2007-08-09 13:54:33 +0000450 /* all peers failed, mark them as live for quick recovery */
Igor Sysoev3d2fd182006-12-04 16:46:13 +0000451
Igor Sysoev6876bcd2007-08-09 13:54:33 +0000452 for (i = 0; i < peers->number; i++) {
453 peers->peer[i].fails = 0;
454 }
455
456 /* ngx_unlock_mutex(peers->mutex); */
457
458 pc->name = peers->name;
Igor Sysoev3d2fd182006-12-04 16:46:13 +0000459
460 return NGX_BUSY;
461}
462
463
Maxim Dounin52327e02012-05-14 09:57:20 +0000464static ngx_http_upstream_rr_peer_t *
465ngx_http_upstream_get_peer(ngx_http_upstream_rr_peer_data_t *rrp)
Igor Sysoevd12a5712007-07-28 16:04:01 +0000466{
Maxim Dounin52327e02012-05-14 09:57:20 +0000467 time_t now;
468 uintptr_t m;
469 ngx_int_t total;
470 ngx_uint_t i, n;
471 ngx_http_upstream_rr_peer_t *peer, *best;
Igor Sysoevd12a5712007-07-28 16:04:01 +0000472
Maxim Dounin52327e02012-05-14 09:57:20 +0000473 now = ngx_time();
Igor Sysoevd12a5712007-07-28 16:04:01 +0000474
Maxim Dounin52327e02012-05-14 09:57:20 +0000475 best = NULL;
476 total = 0;
Igor Sysoevd12a5712007-07-28 16:04:01 +0000477
Maxim Dounin52327e02012-05-14 09:57:20 +0000478 for (i = 0; i < rrp->peers->number; i++) {
Igor Sysoevd12a5712007-07-28 16:04:01 +0000479
Maxim Dounin52327e02012-05-14 09:57:20 +0000480 n = i / (8 * sizeof(uintptr_t));
481 m = (uintptr_t) 1 << i % (8 * sizeof(uintptr_t));
Igor Sysoevd12a5712007-07-28 16:04:01 +0000482
Maxim Dounin52327e02012-05-14 09:57:20 +0000483 if (rrp->tried[n] & m) {
484 continue;
Igor Sysoevd12a5712007-07-28 16:04:01 +0000485 }
486
Maxim Dounin52327e02012-05-14 09:57:20 +0000487 peer = &rrp->peers->peer[i];
488
489 if (peer->down) {
490 continue;
Maxim Dounin624fbe92011-08-18 16:52:38 +0000491 }
492
Maxim Dounin52327e02012-05-14 09:57:20 +0000493 if (peer->max_fails
494 && peer->fails >= peer->max_fails
495 && now - peer->checked <= peer->fail_timeout)
496 {
497 continue;
498 }
499
500 peer->current_weight += peer->effective_weight;
501 total += peer->effective_weight;
502
503 if (peer->effective_weight < peer->weight) {
504 peer->effective_weight++;
505 }
506
507 if (best == NULL || peer->current_weight > best->current_weight) {
508 best = peer;
Igor Sysoevd12a5712007-07-28 16:04:01 +0000509 }
510 }
Maxim Dounin52327e02012-05-14 09:57:20 +0000511
512 if (best == NULL) {
513 return NULL;
514 }
515
516 i = best - &rrp->peers->peer[0];
517
518 rrp->current = i;
519
520 n = i / (8 * sizeof(uintptr_t));
521 m = (uintptr_t) 1 << i % (8 * sizeof(uintptr_t));
522
523 rrp->tried[n] |= m;
524
525 best->current_weight -= total;
Maxim Dounina1ab0dd2013-05-21 21:47:50 +0400526
527 if (now - best->checked > best->fail_timeout) {
528 best->checked = now;
529 }
Maxim Dounin52327e02012-05-14 09:57:20 +0000530
531 return best;
Igor Sysoevd12a5712007-07-28 16:04:01 +0000532}
533
534
Igor Sysoev3d2fd182006-12-04 16:46:13 +0000535void
536ngx_http_upstream_free_round_robin_peer(ngx_peer_connection_t *pc, void *data,
537 ngx_uint_t state)
538{
539 ngx_http_upstream_rr_peer_data_t *rrp = data;
540
541 time_t now;
542 ngx_http_upstream_rr_peer_t *peer;
543
544 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, pc->log, 0,
545 "free rr peer %ui %ui", pc->tries, state);
546
Igor Sysoev3d2fd182006-12-04 16:46:13 +0000547 /* TODO: NGX_PEER_KEEPALIVE */
548
Igor Sysoev6876bcd2007-08-09 13:54:33 +0000549 if (rrp->peers->single) {
Igor Sysoev3d2fd182006-12-04 16:46:13 +0000550 pc->tries = 0;
551 return;
552 }
553
Maxim Douninb713e482011-10-12 14:22:48 +0000554 peer = &rrp->peers->peer[rrp->current];
555
Igor Sysoev3d2fd182006-12-04 16:46:13 +0000556 if (state & NGX_PEER_FAILED) {
557 now = ngx_time();
558
Igor Sysoev3d2fd182006-12-04 16:46:13 +0000559 /* ngx_lock_mutex(rrp->peers->mutex); */
560
561 peer->fails++;
562 peer->accessed = now;
Maxim Douninb713e482011-10-12 14:22:48 +0000563 peer->checked = now;
Igor Sysoev3d2fd182006-12-04 16:46:13 +0000564
Igor Sysoev333723e2008-08-26 14:34:16 +0000565 if (peer->max_fails) {
Maxim Dounin52327e02012-05-14 09:57:20 +0000566 peer->effective_weight -= peer->weight / peer->max_fails;
Igor Sysoev333723e2008-08-26 14:34:16 +0000567 }
Igor Sysoevd12a5712007-07-28 16:04:01 +0000568
569 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, pc->log, 0,
570 "free rr peer failed: %ui %i",
Maxim Dounin52327e02012-05-14 09:57:20 +0000571 rrp->current, peer->effective_weight);
Igor Sysoevd12a5712007-07-28 16:04:01 +0000572
Maxim Dounin52327e02012-05-14 09:57:20 +0000573 if (peer->effective_weight < 0) {
574 peer->effective_weight = 0;
Igor Sysoev3d2fd182006-12-04 16:46:13 +0000575 }
576
577 /* ngx_unlock_mutex(rrp->peers->mutex); */
Maxim Douninb713e482011-10-12 14:22:48 +0000578
579 } else {
580
581 /* mark peer live if check passed */
582
583 if (peer->accessed < peer->checked) {
584 peer->fails = 0;
585 }
Igor Sysoev3d2fd182006-12-04 16:46:13 +0000586 }
587
Igor Sysoev3d2fd182006-12-04 16:46:13 +0000588 if (pc->tries) {
589 pc->tries--;
590 }
591
592 /* ngx_unlock_mutex(rrp->peers->mutex); */
593}
594
595
596#if (NGX_HTTP_SSL)
597
Igor Sysoev8b0a3d22007-07-10 21:04:37 +0000598ngx_int_t
599ngx_http_upstream_set_round_robin_peer_session(ngx_peer_connection_t *pc,
600 void *data)
Igor Sysoev3d2fd182006-12-04 16:46:13 +0000601{
602 ngx_http_upstream_rr_peer_data_t *rrp = data;
603
Igor Sysoev8b0a3d22007-07-10 21:04:37 +0000604 ngx_int_t rc;
Igor Sysoev3d2fd182006-12-04 16:46:13 +0000605 ngx_ssl_session_t *ssl_session;
606 ngx_http_upstream_rr_peer_t *peer;
607
Igor Sysoev8b0a3d22007-07-10 21:04:37 +0000608 peer = &rrp->peers->peer[rrp->current];
609
610 /* TODO: threads only mutex */
611 /* ngx_lock_mutex(rrp->peers->mutex); */
612
613 ssl_session = peer->ssl_session;
614
615 rc = ngx_ssl_set_session(pc->connection, ssl_session);
616
617 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, pc->log, 0,
Igor Sysoevb3dd3fd2007-08-31 12:13:12 +0000618 "set session: %p:%d",
619 ssl_session, ssl_session ? ssl_session->references : 0);
Igor Sysoev8b0a3d22007-07-10 21:04:37 +0000620
621 /* ngx_unlock_mutex(rrp->peers->mutex); */
622
623 return rc;
624}
625
626
627void
628ngx_http_upstream_save_round_robin_peer_session(ngx_peer_connection_t *pc,
629 void *data)
630{
631 ngx_http_upstream_rr_peer_data_t *rrp = data;
632
633 ngx_ssl_session_t *old_ssl_session, *ssl_session;
634 ngx_http_upstream_rr_peer_t *peer;
635
Igor Sysoev3d2fd182006-12-04 16:46:13 +0000636 ssl_session = ngx_ssl_get_session(pc->connection);
637
638 if (ssl_session == NULL) {
639 return;
640 }
641
Igor Sysoev8b0a3d22007-07-10 21:04:37 +0000642 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, pc->log, 0,
Igor Sysoevb3dd3fd2007-08-31 12:13:12 +0000643 "save session: %p:%d", ssl_session, ssl_session->references);
Igor Sysoev8b0a3d22007-07-10 21:04:37 +0000644
Igor Sysoev3d2fd182006-12-04 16:46:13 +0000645 peer = &rrp->peers->peer[rrp->current];
646
Igor Sysoev8b0a3d22007-07-10 21:04:37 +0000647 /* TODO: threads only mutex */
Igor Sysoev3d2fd182006-12-04 16:46:13 +0000648 /* ngx_lock_mutex(rrp->peers->mutex); */
Igor Sysoev8b0a3d22007-07-10 21:04:37 +0000649
650 old_ssl_session = peer->ssl_session;
Igor Sysoev3d2fd182006-12-04 16:46:13 +0000651 peer->ssl_session = ssl_session;
Igor Sysoev8b0a3d22007-07-10 21:04:37 +0000652
Igor Sysoev3d2fd182006-12-04 16:46:13 +0000653 /* ngx_unlock_mutex(rrp->peers->mutex); */
654
Igor Sysoev8b0a3d22007-07-10 21:04:37 +0000655 if (old_ssl_session) {
656
657 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, pc->log, 0,
Igor Sysoevb3dd3fd2007-08-31 12:13:12 +0000658 "old session: %p:%d",
Igor Sysoev8b0a3d22007-07-10 21:04:37 +0000659 old_ssl_session, old_ssl_session->references);
660
Igor Sysoev3d2fd182006-12-04 16:46:13 +0000661 /* TODO: may block */
Igor Sysoev8b0a3d22007-07-10 21:04:37 +0000662
663 ngx_ssl_free_session(old_ssl_session);
Igor Sysoev3d2fd182006-12-04 16:46:13 +0000664 }
665}
666
Igor Sysoev08b59752011-07-22 16:30:17 +0000667
668static ngx_int_t
669ngx_http_upstream_empty_set_session(ngx_peer_connection_t *pc, void *data)
670{
671 return NGX_OK;
672}
673
674
675static void
676ngx_http_upstream_empty_save_session(ngx_peer_connection_t *pc, void *data)
677{
678 return;
679}
680
Igor Sysoev3d2fd182006-12-04 16:46:13 +0000681#endif