Mercurial > hg > nginx
annotate src/stream/ngx_stream_upstream.c @ 6629:8ed51b02f655
Stream: style.
author | Vladimir Homutov <vl@nginx.com> |
---|---|
date | Tue, 12 Jul 2016 17:34:40 +0300 |
parents | 2f41d383c9c7 |
children | ab9b4fd8c5b7 |
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 static char *ngx_stream_upstream(ngx_conf_t *cf, ngx_command_t *cmd, | |
14 void *dummy); | |
15 static char *ngx_stream_upstream_server(ngx_conf_t *cf, ngx_command_t *cmd, | |
16 void *conf); | |
17 static void *ngx_stream_upstream_create_main_conf(ngx_conf_t *cf); | |
18 static char *ngx_stream_upstream_init_main_conf(ngx_conf_t *cf, void *conf); | |
19 | |
20 | |
21 static ngx_command_t ngx_stream_upstream_commands[] = { | |
22 | |
23 { ngx_string("upstream"), | |
24 NGX_STREAM_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_TAKE1, | |
25 ngx_stream_upstream, | |
26 0, | |
27 0, | |
28 NULL }, | |
29 | |
30 { ngx_string("server"), | |
31 NGX_STREAM_UPS_CONF|NGX_CONF_1MORE, | |
32 ngx_stream_upstream_server, | |
33 NGX_STREAM_SRV_CONF_OFFSET, | |
34 0, | |
35 NULL }, | |
36 | |
37 ngx_null_command | |
38 }; | |
39 | |
40 | |
41 static ngx_stream_module_t ngx_stream_upstream_module_ctx = { | |
6606
2f41d383c9c7
Stream: added preconfiguration step.
Vladimir Homutov <vl@nginx.com>
parents:
6459
diff
changeset
|
42 NULL, /* preconfiguration */ |
6174
68c106e6fa0a
Stream: added postconfiguration method to stream modules.
Vladimir Homutov <vl@nginx.com>
parents:
6115
diff
changeset
|
43 NULL, /* postconfiguration */ |
68c106e6fa0a
Stream: added postconfiguration method to stream modules.
Vladimir Homutov <vl@nginx.com>
parents:
6115
diff
changeset
|
44 |
6115 | 45 ngx_stream_upstream_create_main_conf, /* create main configuration */ |
46 ngx_stream_upstream_init_main_conf, /* init main configuration */ | |
47 | |
48 NULL, /* create server configuration */ | |
6629 | 49 NULL /* merge server configuration */ |
6115 | 50 }; |
51 | |
52 | |
53 ngx_module_t ngx_stream_upstream_module = { | |
54 NGX_MODULE_V1, | |
55 &ngx_stream_upstream_module_ctx, /* module context */ | |
56 ngx_stream_upstream_commands, /* module directives */ | |
57 NGX_STREAM_MODULE, /* module type */ | |
58 NULL, /* init master */ | |
59 NULL, /* init module */ | |
60 NULL, /* init process */ | |
61 NULL, /* init thread */ | |
62 NULL, /* exit thread */ | |
63 NULL, /* exit process */ | |
64 NULL, /* exit master */ | |
65 NGX_MODULE_V1_PADDING | |
66 }; | |
67 | |
68 | |
69 static char * | |
70 ngx_stream_upstream(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy) | |
71 { | |
72 char *rv; | |
73 void *mconf; | |
74 ngx_str_t *value; | |
75 ngx_url_t u; | |
76 ngx_uint_t m; | |
77 ngx_conf_t pcf; | |
78 ngx_stream_module_t *module; | |
79 ngx_stream_conf_ctx_t *ctx, *stream_ctx; | |
80 ngx_stream_upstream_srv_conf_t *uscf; | |
81 | |
82 ngx_memzero(&u, sizeof(ngx_url_t)); | |
83 | |
84 value = cf->args->elts; | |
85 u.host = value[1]; | |
86 u.no_resolve = 1; | |
87 u.no_port = 1; | |
88 | |
89 uscf = ngx_stream_upstream_add(cf, &u, NGX_STREAM_UPSTREAM_CREATE | |
90 |NGX_STREAM_UPSTREAM_WEIGHT | |
91 |NGX_STREAM_UPSTREAM_MAX_FAILS | |
92 |NGX_STREAM_UPSTREAM_FAIL_TIMEOUT | |
93 |NGX_STREAM_UPSTREAM_DOWN | |
94 |NGX_STREAM_UPSTREAM_BACKUP); | |
95 if (uscf == NULL) { | |
96 return NGX_CONF_ERROR; | |
97 } | |
98 | |
99 | |
100 ctx = ngx_pcalloc(cf->pool, sizeof(ngx_stream_conf_ctx_t)); | |
101 if (ctx == NULL) { | |
102 return NGX_CONF_ERROR; | |
103 } | |
104 | |
105 stream_ctx = cf->ctx; | |
106 ctx->main_conf = stream_ctx->main_conf; | |
107 | |
108 /* the upstream{}'s srv_conf */ | |
109 | |
110 ctx->srv_conf = ngx_pcalloc(cf->pool, | |
111 sizeof(void *) * ngx_stream_max_module); | |
112 if (ctx->srv_conf == NULL) { | |
113 return NGX_CONF_ERROR; | |
114 } | |
115 | |
116 ctx->srv_conf[ngx_stream_upstream_module.ctx_index] = uscf; | |
117 | |
118 uscf->srv_conf = ctx->srv_conf; | |
119 | |
6379
cf5e822cf470
Dynamic modules: changed ngx_modules to cycle->modules.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6174
diff
changeset
|
120 for (m = 0; cf->cycle->modules[m]; m++) { |
cf5e822cf470
Dynamic modules: changed ngx_modules to cycle->modules.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6174
diff
changeset
|
121 if (cf->cycle->modules[m]->type != NGX_STREAM_MODULE) { |
6115 | 122 continue; |
123 } | |
124 | |
6379
cf5e822cf470
Dynamic modules: changed ngx_modules to cycle->modules.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6174
diff
changeset
|
125 module = cf->cycle->modules[m]->ctx; |
6115 | 126 |
127 if (module->create_srv_conf) { | |
128 mconf = module->create_srv_conf(cf); | |
129 if (mconf == NULL) { | |
130 return NGX_CONF_ERROR; | |
131 } | |
132 | |
6379
cf5e822cf470
Dynamic modules: changed ngx_modules to cycle->modules.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6174
diff
changeset
|
133 ctx->srv_conf[cf->cycle->modules[m]->ctx_index] = mconf; |
6115 | 134 } |
135 } | |
136 | |
137 uscf->servers = ngx_array_create(cf->pool, 4, | |
138 sizeof(ngx_stream_upstream_server_t)); | |
139 if (uscf->servers == NULL) { | |
140 return NGX_CONF_ERROR; | |
141 } | |
142 | |
143 | |
144 /* parse inside upstream{} */ | |
145 | |
146 pcf = *cf; | |
147 cf->ctx = ctx; | |
148 cf->cmd_type = NGX_STREAM_UPS_CONF; | |
149 | |
150 rv = ngx_conf_parse(cf, NULL); | |
151 | |
152 *cf = pcf; | |
153 | |
154 if (rv != NGX_CONF_OK) { | |
155 return rv; | |
156 } | |
157 | |
158 if (uscf->servers->nelts == 0) { | |
159 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
160 "no servers are inside upstream"); | |
161 return NGX_CONF_ERROR; | |
162 } | |
163 | |
164 return rv; | |
165 } | |
166 | |
167 | |
168 static char * | |
169 ngx_stream_upstream_server(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | |
170 { | |
171 ngx_stream_upstream_srv_conf_t *uscf = conf; | |
172 | |
173 time_t fail_timeout; | |
174 ngx_str_t *value, s; | |
175 ngx_url_t u; | |
176 ngx_int_t weight, max_fails; | |
177 ngx_uint_t i; | |
178 ngx_stream_upstream_server_t *us; | |
179 | |
180 us = ngx_array_push(uscf->servers); | |
181 if (us == NULL) { | |
182 return NGX_CONF_ERROR; | |
183 } | |
184 | |
185 ngx_memzero(us, sizeof(ngx_stream_upstream_server_t)); | |
186 | |
187 value = cf->args->elts; | |
188 | |
189 weight = 1; | |
190 max_fails = 1; | |
191 fail_timeout = 10; | |
192 | |
193 for (i = 2; i < cf->args->nelts; i++) { | |
194 | |
195 if (ngx_strncmp(value[i].data, "weight=", 7) == 0) { | |
196 | |
197 if (!(uscf->flags & NGX_STREAM_UPSTREAM_WEIGHT)) { | |
198 goto not_supported; | |
199 } | |
200 | |
201 weight = ngx_atoi(&value[i].data[7], value[i].len - 7); | |
202 | |
203 if (weight == NGX_ERROR || weight == 0) { | |
204 goto invalid; | |
205 } | |
206 | |
207 continue; | |
208 } | |
209 | |
210 if (ngx_strncmp(value[i].data, "max_fails=", 10) == 0) { | |
211 | |
212 if (!(uscf->flags & NGX_STREAM_UPSTREAM_MAX_FAILS)) { | |
213 goto not_supported; | |
214 } | |
215 | |
216 max_fails = ngx_atoi(&value[i].data[10], value[i].len - 10); | |
217 | |
218 if (max_fails == NGX_ERROR) { | |
219 goto invalid; | |
220 } | |
221 | |
222 continue; | |
223 } | |
224 | |
225 if (ngx_strncmp(value[i].data, "fail_timeout=", 13) == 0) { | |
226 | |
227 if (!(uscf->flags & NGX_STREAM_UPSTREAM_FAIL_TIMEOUT)) { | |
228 goto not_supported; | |
229 } | |
230 | |
231 s.len = value[i].len - 13; | |
232 s.data = &value[i].data[13]; | |
233 | |
234 fail_timeout = ngx_parse_time(&s, 1); | |
235 | |
236 if (fail_timeout == (time_t) NGX_ERROR) { | |
237 goto invalid; | |
238 } | |
239 | |
240 continue; | |
241 } | |
242 | |
243 if (ngx_strcmp(value[i].data, "backup") == 0) { | |
244 | |
245 if (!(uscf->flags & NGX_STREAM_UPSTREAM_BACKUP)) { | |
246 goto not_supported; | |
247 } | |
248 | |
249 us->backup = 1; | |
250 | |
251 continue; | |
252 } | |
253 | |
254 if (ngx_strcmp(value[i].data, "down") == 0) { | |
255 | |
256 if (!(uscf->flags & NGX_STREAM_UPSTREAM_DOWN)) { | |
257 goto not_supported; | |
258 } | |
259 | |
260 us->down = 1; | |
261 | |
262 continue; | |
263 } | |
264 | |
265 goto invalid; | |
266 } | |
267 | |
268 ngx_memzero(&u, sizeof(ngx_url_t)); | |
269 | |
270 u.url = value[1]; | |
271 | |
272 if (ngx_parse_url(cf->pool, &u) != NGX_OK) { | |
273 if (u.err) { | |
274 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
275 "%s in upstream \"%V\"", u.err, &u.url); | |
276 } | |
277 | |
278 return NGX_CONF_ERROR; | |
279 } | |
280 | |
281 if (u.no_port) { | |
282 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
283 "no port in upstream \"%V\"", &u.url); | |
284 return NGX_CONF_ERROR; | |
285 } | |
286 | |
287 us->name = u.url; | |
288 us->addrs = u.addrs; | |
289 us->naddrs = u.naddrs; | |
290 us->weight = weight; | |
291 us->max_fails = max_fails; | |
292 us->fail_timeout = fail_timeout; | |
293 | |
294 return NGX_CONF_OK; | |
295 | |
296 invalid: | |
297 | |
298 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
299 "invalid parameter \"%V\"", &value[i]); | |
300 | |
301 return NGX_CONF_ERROR; | |
302 | |
303 not_supported: | |
304 | |
305 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
306 "balancing method does not support parameter \"%V\"", | |
307 &value[i]); | |
308 | |
309 return NGX_CONF_ERROR; | |
310 } | |
311 | |
312 | |
313 ngx_stream_upstream_srv_conf_t * | |
314 ngx_stream_upstream_add(ngx_conf_t *cf, ngx_url_t *u, ngx_uint_t flags) | |
315 { | |
316 ngx_uint_t i; | |
317 ngx_stream_upstream_server_t *us; | |
318 ngx_stream_upstream_srv_conf_t *uscf, **uscfp; | |
319 ngx_stream_upstream_main_conf_t *umcf; | |
320 | |
321 if (!(flags & NGX_STREAM_UPSTREAM_CREATE)) { | |
322 | |
323 if (ngx_parse_url(cf->pool, u) != NGX_OK) { | |
324 if (u->err) { | |
325 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
326 "%s in upstream \"%V\"", u->err, &u->url); | |
327 } | |
328 | |
329 return NULL; | |
330 } | |
331 } | |
332 | |
333 umcf = ngx_stream_conf_get_module_main_conf(cf, ngx_stream_upstream_module); | |
334 | |
335 uscfp = umcf->upstreams.elts; | |
336 | |
337 for (i = 0; i < umcf->upstreams.nelts; i++) { | |
338 | |
339 if (uscfp[i]->host.len != u->host.len | |
340 || ngx_strncasecmp(uscfp[i]->host.data, u->host.data, u->host.len) | |
341 != 0) | |
342 { | |
343 continue; | |
344 } | |
345 | |
346 if ((flags & NGX_STREAM_UPSTREAM_CREATE) | |
347 && (uscfp[i]->flags & NGX_STREAM_UPSTREAM_CREATE)) | |
348 { | |
349 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
350 "duplicate upstream \"%V\"", &u->host); | |
351 return NULL; | |
352 } | |
353 | |
354 if ((uscfp[i]->flags & NGX_STREAM_UPSTREAM_CREATE) && !u->no_port) { | |
355 ngx_conf_log_error(NGX_LOG_WARN, cf, 0, | |
356 "upstream \"%V\" may not have port %d", | |
357 &u->host, u->port); | |
358 return NULL; | |
359 } | |
360 | |
361 if ((flags & NGX_STREAM_UPSTREAM_CREATE) && !uscfp[i]->no_port) { | |
362 ngx_log_error(NGX_LOG_WARN, cf->log, 0, | |
363 "upstream \"%V\" may not have port %d in %s:%ui", | |
364 &u->host, uscfp[i]->port, | |
365 uscfp[i]->file_name, uscfp[i]->line); | |
366 return NULL; | |
367 } | |
368 | |
369 if (uscfp[i]->port != u->port) { | |
370 continue; | |
371 } | |
372 | |
373 if (flags & NGX_STREAM_UPSTREAM_CREATE) { | |
374 uscfp[i]->flags = flags; | |
375 } | |
376 | |
377 return uscfp[i]; | |
378 } | |
379 | |
380 uscf = ngx_pcalloc(cf->pool, sizeof(ngx_stream_upstream_srv_conf_t)); | |
381 if (uscf == NULL) { | |
382 return NULL; | |
383 } | |
384 | |
385 uscf->flags = flags; | |
386 uscf->host = u->host; | |
387 uscf->file_name = cf->conf_file->file.name.data; | |
388 uscf->line = cf->conf_file->line; | |
389 uscf->port = u->port; | |
390 uscf->no_port = u->no_port; | |
391 | |
6459
78fc2dce69e7
Stream: detect port absence in proxy_pass with IP literal.
Roman Arutyunyan <arut@nginx.com>
parents:
6379
diff
changeset
|
392 if (u->naddrs == 1 && (u->port || u->family == AF_UNIX)) { |
6115 | 393 uscf->servers = ngx_array_create(cf->pool, 1, |
394 sizeof(ngx_stream_upstream_server_t)); | |
395 if (uscf->servers == NULL) { | |
396 return NULL; | |
397 } | |
398 | |
399 us = ngx_array_push(uscf->servers); | |
400 if (us == NULL) { | |
401 return NULL; | |
402 } | |
403 | |
404 ngx_memzero(us, sizeof(ngx_stream_upstream_server_t)); | |
405 | |
406 us->addrs = u->addrs; | |
407 us->naddrs = 1; | |
408 } | |
409 | |
410 uscfp = ngx_array_push(&umcf->upstreams); | |
411 if (uscfp == NULL) { | |
412 return NULL; | |
413 } | |
414 | |
415 *uscfp = uscf; | |
416 | |
417 return uscf; | |
418 } | |
419 | |
420 | |
421 static void * | |
422 ngx_stream_upstream_create_main_conf(ngx_conf_t *cf) | |
423 { | |
424 ngx_stream_upstream_main_conf_t *umcf; | |
425 | |
426 umcf = ngx_pcalloc(cf->pool, sizeof(ngx_stream_upstream_main_conf_t)); | |
427 if (umcf == NULL) { | |
428 return NULL; | |
429 } | |
430 | |
431 if (ngx_array_init(&umcf->upstreams, cf->pool, 4, | |
432 sizeof(ngx_stream_upstream_srv_conf_t *)) | |
433 != NGX_OK) | |
434 { | |
435 return NULL; | |
436 } | |
437 | |
438 return umcf; | |
439 } | |
440 | |
441 | |
442 static char * | |
443 ngx_stream_upstream_init_main_conf(ngx_conf_t *cf, void *conf) | |
444 { | |
445 ngx_stream_upstream_main_conf_t *umcf = conf; | |
446 | |
447 ngx_uint_t i; | |
448 ngx_stream_upstream_init_pt init; | |
449 ngx_stream_upstream_srv_conf_t **uscfp; | |
450 | |
451 uscfp = umcf->upstreams.elts; | |
452 | |
453 for (i = 0; i < umcf->upstreams.nelts; i++) { | |
454 | |
455 init = uscfp[i]->peer.init_upstream | |
456 ? uscfp[i]->peer.init_upstream | |
457 : ngx_stream_upstream_init_round_robin; | |
458 | |
459 if (init(cf, uscfp[i]) != NGX_OK) { | |
460 return NGX_CONF_ERROR; | |
461 } | |
462 } | |
463 | |
464 return NGX_CONF_OK; | |
465 } |