annotate src/stream/ngx_stream_upstream_least_conn_module.c @ 7690:8253424d1aff

Added size check to ngx_http_alloc_large_header_buffer(). This ensures that copying won't write more than the buffer size even if the buffer comes from hc->free and it is smaller than the large client header buffer size in the virtual host configuration. This might happen if size of large client header buffers is different in name-based virtual hosts, similarly to the problem with number of buffers fixed in 6926:e662cbf1b932.
author Maxim Dounin <mdounin@mdounin.ru>
date Thu, 06 Aug 2020 05:02:22 +0300
parents 29bf0dbc0a77
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
6115
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
1
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
2 /*
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
3 * Copyright (C) Maxim Dounin
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
4 * Copyright (C) Nginx, Inc.
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
5 */
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
6
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
7
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
8 #include <ngx_config.h>
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
9 #include <ngx_core.h>
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
10 #include <ngx_stream.h>
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
11
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
12
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
13 static ngx_int_t ngx_stream_upstream_init_least_conn_peer(
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
14 ngx_stream_session_t *s, ngx_stream_upstream_srv_conf_t *us);
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
15 static ngx_int_t ngx_stream_upstream_get_least_conn_peer(
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
16 ngx_peer_connection_t *pc, void *data);
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
17 static char *ngx_stream_upstream_least_conn(ngx_conf_t *cf, ngx_command_t *cmd,
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
18 void *conf);
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
19
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
20
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
21 static ngx_command_t ngx_stream_upstream_least_conn_commands[] = {
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
22
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
23 { ngx_string("least_conn"),
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
24 NGX_STREAM_UPS_CONF|NGX_CONF_NOARGS,
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
25 ngx_stream_upstream_least_conn,
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
26 0,
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
27 0,
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
28 NULL },
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
29
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
30 ngx_null_command
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
31 };
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
32
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
33
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
34 static ngx_stream_module_t ngx_stream_upstream_least_conn_module_ctx = {
6606
2f41d383c9c7 Stream: added preconfiguration step.
Vladimir Homutov <vl@nginx.com>
parents: 6474
diff changeset
35 NULL, /* preconfiguration */
6174
68c106e6fa0a Stream: added postconfiguration method to stream modules.
Vladimir Homutov <vl@nginx.com>
parents: 6115
diff changeset
36 NULL, /* postconfiguration */
68c106e6fa0a Stream: added postconfiguration method to stream modules.
Vladimir Homutov <vl@nginx.com>
parents: 6115
diff changeset
37
6115
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
38 NULL, /* create main configuration */
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
39 NULL, /* init main configuration */
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
40
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
41 NULL, /* create server configuration */
6629
8ed51b02f655 Stream: style.
Vladimir Homutov <vl@nginx.com>
parents: 6606
diff changeset
42 NULL /* merge server configuration */
6115
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
43 };
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
44
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
45
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
46 ngx_module_t ngx_stream_upstream_least_conn_module = {
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
47 NGX_MODULE_V1,
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
48 &ngx_stream_upstream_least_conn_module_ctx, /* module context */
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
49 ngx_stream_upstream_least_conn_commands, /* module directives */
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
50 NGX_STREAM_MODULE, /* module type */
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
51 NULL, /* init master */
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
52 NULL, /* init module */
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
53 NULL, /* init process */
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
54 NULL, /* init thread */
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
55 NULL, /* exit thread */
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
56 NULL, /* exit process */
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
57 NULL, /* exit master */
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
58 NGX_MODULE_V1_PADDING
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
59 };
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
60
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
61
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
62 static ngx_int_t
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
63 ngx_stream_upstream_init_least_conn(ngx_conf_t *cf,
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
64 ngx_stream_upstream_srv_conf_t *us)
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
65 {
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
66 ngx_log_debug0(NGX_LOG_DEBUG_STREAM, cf->log, 0,
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
67 "init least conn");
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
68
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
69 if (ngx_stream_upstream_init_round_robin(cf, us) != NGX_OK) {
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
70 return NGX_ERROR;
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
71 }
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
72
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
73 us->peer.init = ngx_stream_upstream_init_least_conn_peer;
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
74
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
75 return NGX_OK;
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
76 }
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
77
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
78
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
79 static ngx_int_t
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
80 ngx_stream_upstream_init_least_conn_peer(ngx_stream_session_t *s,
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
81 ngx_stream_upstream_srv_conf_t *us)
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
82 {
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
83 ngx_log_debug0(NGX_LOG_DEBUG_STREAM, s->connection->log, 0,
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
84 "init least conn peer");
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
85
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
86 if (ngx_stream_upstream_init_round_robin_peer(s, us) != NGX_OK) {
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
87 return NGX_ERROR;
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
88 }
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
89
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
90 s->upstream->peer.get = ngx_stream_upstream_get_least_conn_peer;
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
91
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
92 return NGX_OK;
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
93 }
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
94
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
95
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
96 static ngx_int_t
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
97 ngx_stream_upstream_get_least_conn_peer(ngx_peer_connection_t *pc, void *data)
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
98 {
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
99 ngx_stream_upstream_rr_peer_data_t *rrp = data;
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
100
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
101 time_t now;
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
102 uintptr_t m;
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
103 ngx_int_t rc, total;
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
104 ngx_uint_t i, n, p, many;
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
105 ngx_stream_upstream_rr_peer_t *peer, *best;
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
106 ngx_stream_upstream_rr_peers_t *peers;
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
107
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
108 ngx_log_debug1(NGX_LOG_DEBUG_STREAM, pc->log, 0,
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
109 "get least conn peer, try: %ui", pc->tries);
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
110
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
111 if (rrp->peers->single) {
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
112 return ngx_stream_upstream_get_round_robin_peer(pc, rrp);
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
113 }
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
114
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
115 pc->connection = NULL;
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
116
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
117 now = ngx_time();
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
118
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
119 peers = rrp->peers;
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
120
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
121 ngx_stream_upstream_rr_peers_wlock(peers);
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
122
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
123 best = NULL;
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
124 total = 0;
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
125
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
126 #if (NGX_SUPPRESS_WARN)
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
127 many = 0;
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
128 p = 0;
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
129 #endif
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
130
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
131 for (peer = peers->peer, i = 0;
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
132 peer;
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
133 peer = peer->next, i++)
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
134 {
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
135 n = i / (8 * sizeof(uintptr_t));
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
136 m = (uintptr_t) 1 << i % (8 * sizeof(uintptr_t));
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
137
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
138 if (rrp->tried[n] & m) {
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
139 continue;
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
140 }
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
141
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
142 if (peer->down) {
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
143 continue;
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
144 }
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
145
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
146 if (peer->max_fails
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
147 && peer->fails >= peer->max_fails
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
148 && now - peer->checked <= peer->fail_timeout)
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
149 {
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
150 continue;
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
151 }
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
152
6705
29bf0dbc0a77 Upstream: max_conns.
Ruslan Ermilov <ru@nginx.com>
parents: 6704
diff changeset
153 if (peer->max_conns && peer->conns >= peer->max_conns) {
29bf0dbc0a77 Upstream: max_conns.
Ruslan Ermilov <ru@nginx.com>
parents: 6704
diff changeset
154 continue;
29bf0dbc0a77 Upstream: max_conns.
Ruslan Ermilov <ru@nginx.com>
parents: 6704
diff changeset
155 }
29bf0dbc0a77 Upstream: max_conns.
Ruslan Ermilov <ru@nginx.com>
parents: 6704
diff changeset
156
6115
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
157 /*
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
158 * select peer with least number of connections; if there are
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
159 * multiple peers with the same number of connections, select
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
160 * based on round-robin
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
161 */
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
162
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
163 if (best == NULL
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
164 || peer->conns * best->weight < best->conns * peer->weight)
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
165 {
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
166 best = peer;
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
167 many = 0;
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
168 p = i;
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
169
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
170 } else if (peer->conns * best->weight == best->conns * peer->weight) {
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
171 many = 1;
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
172 }
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
173 }
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
174
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
175 if (best == NULL) {
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
176 ngx_log_debug0(NGX_LOG_DEBUG_STREAM, pc->log, 0,
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
177 "get least conn peer, no peer found");
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
178
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
179 goto failed;
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
180 }
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
181
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
182 if (many) {
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
183 ngx_log_debug0(NGX_LOG_DEBUG_STREAM, pc->log, 0,
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
184 "get least conn peer, many");
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
185
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
186 for (peer = best, i = p;
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
187 peer;
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
188 peer = peer->next, i++)
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
189 {
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
190 n = i / (8 * sizeof(uintptr_t));
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
191 m = (uintptr_t) 1 << i % (8 * sizeof(uintptr_t));
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
192
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
193 if (rrp->tried[n] & m) {
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
194 continue;
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
195 }
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
196
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
197 if (peer->down) {
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
198 continue;
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
199 }
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
200
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
201 if (peer->conns * best->weight != best->conns * peer->weight) {
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
202 continue;
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
203 }
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
204
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
205 if (peer->max_fails
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
206 && peer->fails >= peer->max_fails
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
207 && now - peer->checked <= peer->fail_timeout)
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
208 {
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
209 continue;
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
210 }
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
211
6705
29bf0dbc0a77 Upstream: max_conns.
Ruslan Ermilov <ru@nginx.com>
parents: 6704
diff changeset
212 if (peer->max_conns && peer->conns >= peer->max_conns) {
29bf0dbc0a77 Upstream: max_conns.
Ruslan Ermilov <ru@nginx.com>
parents: 6704
diff changeset
213 continue;
29bf0dbc0a77 Upstream: max_conns.
Ruslan Ermilov <ru@nginx.com>
parents: 6704
diff changeset
214 }
29bf0dbc0a77 Upstream: max_conns.
Ruslan Ermilov <ru@nginx.com>
parents: 6704
diff changeset
215
6115
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
216 peer->current_weight += peer->effective_weight;
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
217 total += peer->effective_weight;
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
218
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
219 if (peer->effective_weight < peer->weight) {
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
220 peer->effective_weight++;
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
221 }
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
222
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
223 if (peer->current_weight > best->current_weight) {
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
224 best = peer;
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
225 p = i;
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
226 }
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
227 }
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
228 }
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
229
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
230 best->current_weight -= total;
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
231
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
232 if (now - best->checked > best->fail_timeout) {
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
233 best->checked = now;
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
234 }
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
235
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
236 pc->sockaddr = best->sockaddr;
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
237 pc->socklen = best->socklen;
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
238 pc->name = &best->name;
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
239
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
240 best->conns++;
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
241
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
242 rrp->current = best;
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
243
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
244 n = p / (8 * sizeof(uintptr_t));
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
245 m = (uintptr_t) 1 << p % (8 * sizeof(uintptr_t));
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
246
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
247 rrp->tried[n] |= m;
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
248
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
249 ngx_stream_upstream_rr_peers_unlock(peers);
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
250
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
251 return NGX_OK;
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
252
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
253 failed:
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
254
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
255 if (peers->next) {
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
256 ngx_log_debug0(NGX_LOG_DEBUG_STREAM, pc->log, 0,
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
257 "get least conn peer, backup servers");
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
258
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
259 rrp->peers = peers->next;
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
260
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
261 n = (rrp->peers->number + (8 * sizeof(uintptr_t) - 1))
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
262 / (8 * sizeof(uintptr_t));
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
263
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
264 for (i = 0; i < n; i++) {
6474
Ruslan Ermilov <ru@nginx.com>
parents: 6174
diff changeset
265 rrp->tried[i] = 0;
6115
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
266 }
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
267
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
268 ngx_stream_upstream_rr_peers_unlock(peers);
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
269
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
270 rc = ngx_stream_upstream_get_least_conn_peer(pc, rrp);
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
271
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
272 if (rc != NGX_BUSY) {
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
273 return rc;
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
274 }
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
275
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
276 ngx_stream_upstream_rr_peers_wlock(peers);
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
277 }
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
278
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
279 ngx_stream_upstream_rr_peers_unlock(peers);
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
280
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
281 pc->name = peers->name;
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
282
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
283 return NGX_BUSY;
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
284 }
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
285
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
286
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
287 static char *
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
288 ngx_stream_upstream_least_conn(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
289 {
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
290 ngx_stream_upstream_srv_conf_t *uscf;
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
291
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
292 uscf = ngx_stream_conf_get_module_srv_conf(cf, ngx_stream_upstream_module);
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
293
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
294 if (uscf->peer.init_upstream) {
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
295 ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
296 "load balancing method redefined");
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
297 }
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
298
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
299 uscf->peer.init_upstream = ngx_stream_upstream_init_least_conn;
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
300
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
301 uscf->flags = NGX_STREAM_UPSTREAM_CREATE
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
302 |NGX_STREAM_UPSTREAM_WEIGHT
6705
29bf0dbc0a77 Upstream: max_conns.
Ruslan Ermilov <ru@nginx.com>
parents: 6704
diff changeset
303 |NGX_STREAM_UPSTREAM_MAX_CONNS
6115
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
304 |NGX_STREAM_UPSTREAM_MAX_FAILS
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
305 |NGX_STREAM_UPSTREAM_FAIL_TIMEOUT
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
306 |NGX_STREAM_UPSTREAM_DOWN
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
307 |NGX_STREAM_UPSTREAM_BACKUP;
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
308
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
309 return NGX_CONF_OK;
61d7ae76647d Stream: port from NGINX+.
Ruslan Ermilov <ru@nginx.com>
parents:
diff changeset
310 }