Mercurial > hg > nginx-quic
annotate src/http/modules/ngx_http_upstream_keepalive_module.c @ 7726:f388c0ad3477 quic
Added processing of client transport parameters.
note:
+ parameters are available in SSL connection since they are obtained by ssl
stack
quote:
During connection establishment, both endpoints make authenticated
declarations of their transport parameters. These declarations are
made unilaterally by each endpoint.
and really, we send our parameters before we read client's.
no handling of incoming parameters is made by this patch.
author | Vladimir Homutov <vl@nginx.com> |
---|---|
date | Sat, 21 Mar 2020 20:51:59 +0300 |
parents | 3939483cd1b5 |
children | fdc3d40979b0 |
rev | line source |
---|---|
4127 | 1 |
2 /* | |
3 * Copyright (C) Maxim Dounin | |
4412 | 4 * Copyright (C) Nginx, Inc. |
4127 | 5 */ |
6 | |
7 | |
8 #include <ngx_config.h> | |
9 #include <ngx_core.h> | |
10 #include <ngx_http.h> | |
11 | |
12 | |
13 typedef struct { | |
14 ngx_uint_t max_cached; | |
7340
70c6b08973a0
Upstream keepalive: keepalive_requests directive.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7339
diff
changeset
|
15 ngx_uint_t requests; |
7339
d9029e113a05
Upstream keepalive: keepalive_timeout directive.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7338
diff
changeset
|
16 ngx_msec_t timeout; |
4127 | 17 |
18 ngx_queue_t cache; | |
19 ngx_queue_t free; | |
20 | |
21 ngx_http_upstream_init_pt original_init_upstream; | |
22 ngx_http_upstream_init_peer_pt original_init_peer; | |
23 | |
24 } ngx_http_upstream_keepalive_srv_conf_t; | |
25 | |
26 | |
27 typedef struct { | |
28 ngx_http_upstream_keepalive_srv_conf_t *conf; | |
29 | |
6167
87d48f8793b6
Upstream keepalive: reduced diffs to the plus version of nginx.
Roman Arutyunyan <arut@nginx.com>
parents:
5999
diff
changeset
|
30 ngx_queue_t queue; |
87d48f8793b6
Upstream keepalive: reduced diffs to the plus version of nginx.
Roman Arutyunyan <arut@nginx.com>
parents:
5999
diff
changeset
|
31 ngx_connection_t *connection; |
87d48f8793b6
Upstream keepalive: reduced diffs to the plus version of nginx.
Roman Arutyunyan <arut@nginx.com>
parents:
5999
diff
changeset
|
32 |
87d48f8793b6
Upstream keepalive: reduced diffs to the plus version of nginx.
Roman Arutyunyan <arut@nginx.com>
parents:
5999
diff
changeset
|
33 socklen_t socklen; |
6559
adf25b8d0431
Introduced the ngx_sockaddr_t type.
Ruslan Ermilov <ru@nginx.com>
parents:
6332
diff
changeset
|
34 ngx_sockaddr_t sockaddr; |
6167
87d48f8793b6
Upstream keepalive: reduced diffs to the plus version of nginx.
Roman Arutyunyan <arut@nginx.com>
parents:
5999
diff
changeset
|
35 |
87d48f8793b6
Upstream keepalive: reduced diffs to the plus version of nginx.
Roman Arutyunyan <arut@nginx.com>
parents:
5999
diff
changeset
|
36 } ngx_http_upstream_keepalive_cache_t; |
87d48f8793b6
Upstream keepalive: reduced diffs to the plus version of nginx.
Roman Arutyunyan <arut@nginx.com>
parents:
5999
diff
changeset
|
37 |
87d48f8793b6
Upstream keepalive: reduced diffs to the plus version of nginx.
Roman Arutyunyan <arut@nginx.com>
parents:
5999
diff
changeset
|
38 |
87d48f8793b6
Upstream keepalive: reduced diffs to the plus version of nginx.
Roman Arutyunyan <arut@nginx.com>
parents:
5999
diff
changeset
|
39 typedef struct { |
87d48f8793b6
Upstream keepalive: reduced diffs to the plus version of nginx.
Roman Arutyunyan <arut@nginx.com>
parents:
5999
diff
changeset
|
40 ngx_http_upstream_keepalive_srv_conf_t *conf; |
87d48f8793b6
Upstream keepalive: reduced diffs to the plus version of nginx.
Roman Arutyunyan <arut@nginx.com>
parents:
5999
diff
changeset
|
41 |
4127 | 42 ngx_http_upstream_t *upstream; |
43 | |
44 void *data; | |
45 | |
46 ngx_event_get_peer_pt original_get_peer; | |
47 ngx_event_free_peer_pt original_free_peer; | |
48 | |
49 #if (NGX_HTTP_SSL) | |
50 ngx_event_set_peer_session_pt original_set_session; | |
51 ngx_event_save_peer_session_pt original_save_session; | |
52 #endif | |
53 | |
54 } ngx_http_upstream_keepalive_peer_data_t; | |
55 | |
56 | |
57 static ngx_int_t ngx_http_upstream_init_keepalive_peer(ngx_http_request_t *r, | |
58 ngx_http_upstream_srv_conf_t *us); | |
59 static ngx_int_t ngx_http_upstream_get_keepalive_peer(ngx_peer_connection_t *pc, | |
60 void *data); | |
61 static void ngx_http_upstream_free_keepalive_peer(ngx_peer_connection_t *pc, | |
62 void *data, ngx_uint_t state); | |
63 | |
64 static void ngx_http_upstream_keepalive_dummy_handler(ngx_event_t *ev); | |
65 static void ngx_http_upstream_keepalive_close_handler(ngx_event_t *ev); | |
66 static void ngx_http_upstream_keepalive_close(ngx_connection_t *c); | |
67 | |
68 #if (NGX_HTTP_SSL) | |
69 static ngx_int_t ngx_http_upstream_keepalive_set_session( | |
70 ngx_peer_connection_t *pc, void *data); | |
71 static void ngx_http_upstream_keepalive_save_session(ngx_peer_connection_t *pc, | |
72 void *data); | |
73 #endif | |
74 | |
75 static void *ngx_http_upstream_keepalive_create_conf(ngx_conf_t *cf); | |
76 static char *ngx_http_upstream_keepalive(ngx_conf_t *cf, ngx_command_t *cmd, | |
77 void *conf); | |
78 | |
79 | |
80 static ngx_command_t ngx_http_upstream_keepalive_commands[] = { | |
81 | |
82 { ngx_string("keepalive"), | |
5830
3e5b630e0ec9
Upstream keepalive: removed "single" parameter remnants.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5213
diff
changeset
|
83 NGX_HTTP_UPS_CONF|NGX_CONF_TAKE1, |
4127 | 84 ngx_http_upstream_keepalive, |
5213
822b82191940
Upstream keepalive: slightly simplified code.
Ruslan Ermilov <ru@nginx.com>
parents:
5133
diff
changeset
|
85 NGX_HTTP_SRV_CONF_OFFSET, |
4127 | 86 0, |
87 NULL }, | |
88 | |
7339
d9029e113a05
Upstream keepalive: keepalive_timeout directive.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7338
diff
changeset
|
89 { ngx_string("keepalive_timeout"), |
d9029e113a05
Upstream keepalive: keepalive_timeout directive.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7338
diff
changeset
|
90 NGX_HTTP_UPS_CONF|NGX_CONF_TAKE1, |
d9029e113a05
Upstream keepalive: keepalive_timeout directive.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7338
diff
changeset
|
91 ngx_conf_set_msec_slot, |
d9029e113a05
Upstream keepalive: keepalive_timeout directive.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7338
diff
changeset
|
92 NGX_HTTP_SRV_CONF_OFFSET, |
d9029e113a05
Upstream keepalive: keepalive_timeout directive.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7338
diff
changeset
|
93 offsetof(ngx_http_upstream_keepalive_srv_conf_t, timeout), |
d9029e113a05
Upstream keepalive: keepalive_timeout directive.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7338
diff
changeset
|
94 NULL }, |
d9029e113a05
Upstream keepalive: keepalive_timeout directive.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7338
diff
changeset
|
95 |
7340
70c6b08973a0
Upstream keepalive: keepalive_requests directive.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7339
diff
changeset
|
96 { ngx_string("keepalive_requests"), |
70c6b08973a0
Upstream keepalive: keepalive_requests directive.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7339
diff
changeset
|
97 NGX_HTTP_UPS_CONF|NGX_CONF_TAKE1, |
70c6b08973a0
Upstream keepalive: keepalive_requests directive.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7339
diff
changeset
|
98 ngx_conf_set_num_slot, |
70c6b08973a0
Upstream keepalive: keepalive_requests directive.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7339
diff
changeset
|
99 NGX_HTTP_SRV_CONF_OFFSET, |
70c6b08973a0
Upstream keepalive: keepalive_requests directive.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7339
diff
changeset
|
100 offsetof(ngx_http_upstream_keepalive_srv_conf_t, requests), |
70c6b08973a0
Upstream keepalive: keepalive_requests directive.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7339
diff
changeset
|
101 NULL }, |
70c6b08973a0
Upstream keepalive: keepalive_requests directive.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7339
diff
changeset
|
102 |
4127 | 103 ngx_null_command |
104 }; | |
105 | |
106 | |
107 static ngx_http_module_t ngx_http_upstream_keepalive_module_ctx = { | |
108 NULL, /* preconfiguration */ | |
109 NULL, /* postconfiguration */ | |
110 | |
111 NULL, /* create main configuration */ | |
112 NULL, /* init main configuration */ | |
113 | |
114 ngx_http_upstream_keepalive_create_conf, /* create server configuration */ | |
115 NULL, /* merge server configuration */ | |
116 | |
117 NULL, /* create location configuration */ | |
118 NULL /* merge location configuration */ | |
119 }; | |
120 | |
121 | |
122 ngx_module_t ngx_http_upstream_keepalive_module = { | |
123 NGX_MODULE_V1, | |
124 &ngx_http_upstream_keepalive_module_ctx, /* module context */ | |
125 ngx_http_upstream_keepalive_commands, /* module directives */ | |
126 NGX_HTTP_MODULE, /* module type */ | |
127 NULL, /* init master */ | |
128 NULL, /* init module */ | |
129 NULL, /* init process */ | |
130 NULL, /* init thread */ | |
131 NULL, /* exit thread */ | |
132 NULL, /* exit process */ | |
133 NULL, /* exit master */ | |
134 NGX_MODULE_V1_PADDING | |
135 }; | |
136 | |
137 | |
138 static ngx_int_t | |
139 ngx_http_upstream_init_keepalive(ngx_conf_t *cf, | |
140 ngx_http_upstream_srv_conf_t *us) | |
141 { | |
142 ngx_uint_t i; | |
143 ngx_http_upstream_keepalive_srv_conf_t *kcf; | |
144 ngx_http_upstream_keepalive_cache_t *cached; | |
145 | |
146 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, cf->log, 0, | |
147 "init keepalive"); | |
148 | |
149 kcf = ngx_http_conf_upstream_srv_conf(us, | |
150 ngx_http_upstream_keepalive_module); | |
151 | |
7339
d9029e113a05
Upstream keepalive: keepalive_timeout directive.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7338
diff
changeset
|
152 ngx_conf_init_msec_value(kcf->timeout, 60000); |
7340
70c6b08973a0
Upstream keepalive: keepalive_requests directive.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7339
diff
changeset
|
153 ngx_conf_init_uint_value(kcf->requests, 100); |
7339
d9029e113a05
Upstream keepalive: keepalive_timeout directive.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7338
diff
changeset
|
154 |
4127 | 155 if (kcf->original_init_upstream(cf, us) != NGX_OK) { |
156 return NGX_ERROR; | |
157 } | |
158 | |
159 kcf->original_init_peer = us->peer.init; | |
160 | |
161 us->peer.init = ngx_http_upstream_init_keepalive_peer; | |
162 | |
163 /* allocate cache items and add to free queue */ | |
164 | |
165 cached = ngx_pcalloc(cf->pool, | |
166 sizeof(ngx_http_upstream_keepalive_cache_t) * kcf->max_cached); | |
167 if (cached == NULL) { | |
168 return NGX_ERROR; | |
169 } | |
170 | |
171 ngx_queue_init(&kcf->cache); | |
172 ngx_queue_init(&kcf->free); | |
173 | |
174 for (i = 0; i < kcf->max_cached; i++) { | |
175 ngx_queue_insert_head(&kcf->free, &cached[i].queue); | |
176 cached[i].conf = kcf; | |
177 } | |
178 | |
179 return NGX_OK; | |
180 } | |
181 | |
182 | |
183 static ngx_int_t | |
184 ngx_http_upstream_init_keepalive_peer(ngx_http_request_t *r, | |
185 ngx_http_upstream_srv_conf_t *us) | |
186 { | |
187 ngx_http_upstream_keepalive_peer_data_t *kp; | |
188 ngx_http_upstream_keepalive_srv_conf_t *kcf; | |
189 | |
190 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
191 "init keepalive peer"); | |
192 | |
193 kcf = ngx_http_conf_upstream_srv_conf(us, | |
194 ngx_http_upstream_keepalive_module); | |
195 | |
196 kp = ngx_palloc(r->pool, sizeof(ngx_http_upstream_keepalive_peer_data_t)); | |
197 if (kp == NULL) { | |
198 return NGX_ERROR; | |
199 } | |
200 | |
201 if (kcf->original_init_peer(r, us) != NGX_OK) { | |
202 return NGX_ERROR; | |
203 } | |
204 | |
205 kp->conf = kcf; | |
206 kp->upstream = r->upstream; | |
207 kp->data = r->upstream->peer.data; | |
208 kp->original_get_peer = r->upstream->peer.get; | |
209 kp->original_free_peer = r->upstream->peer.free; | |
210 | |
211 r->upstream->peer.data = kp; | |
212 r->upstream->peer.get = ngx_http_upstream_get_keepalive_peer; | |
213 r->upstream->peer.free = ngx_http_upstream_free_keepalive_peer; | |
214 | |
215 #if (NGX_HTTP_SSL) | |
216 kp->original_set_session = r->upstream->peer.set_session; | |
217 kp->original_save_session = r->upstream->peer.save_session; | |
218 r->upstream->peer.set_session = ngx_http_upstream_keepalive_set_session; | |
219 r->upstream->peer.save_session = ngx_http_upstream_keepalive_save_session; | |
220 #endif | |
221 | |
222 return NGX_OK; | |
223 } | |
224 | |
225 | |
226 static ngx_int_t | |
227 ngx_http_upstream_get_keepalive_peer(ngx_peer_connection_t *pc, void *data) | |
228 { | |
229 ngx_http_upstream_keepalive_peer_data_t *kp = data; | |
230 ngx_http_upstream_keepalive_cache_t *item; | |
231 | |
232 ngx_int_t rc; | |
233 ngx_queue_t *q, *cache; | |
234 ngx_connection_t *c; | |
235 | |
236 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, pc->log, 0, | |
237 "get keepalive peer"); | |
238 | |
4694
5b5c07dee156
Upstream keepalive: "single" parameter deprecated.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4412
diff
changeset
|
239 /* ask balancer */ |
4127 | 240 |
241 rc = kp->original_get_peer(pc, kp->data); | |
242 | |
4694
5b5c07dee156
Upstream keepalive: "single" parameter deprecated.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4412
diff
changeset
|
243 if (rc != NGX_OK) { |
4127 | 244 return rc; |
245 } | |
246 | |
247 /* search cache for suitable connection */ | |
248 | |
249 cache = &kp->conf->cache; | |
250 | |
251 for (q = ngx_queue_head(cache); | |
252 q != ngx_queue_sentinel(cache); | |
253 q = ngx_queue_next(q)) | |
254 { | |
255 item = ngx_queue_data(q, ngx_http_upstream_keepalive_cache_t, queue); | |
256 c = item->connection; | |
257 | |
258 if (ngx_memn2cmp((u_char *) &item->sockaddr, (u_char *) pc->sockaddr, | |
259 item->socklen, pc->socklen) | |
260 == 0) | |
261 { | |
262 ngx_queue_remove(q); | |
263 ngx_queue_insert_head(&kp->conf->free, q); | |
264 | |
6167
87d48f8793b6
Upstream keepalive: reduced diffs to the plus version of nginx.
Roman Arutyunyan <arut@nginx.com>
parents:
5999
diff
changeset
|
265 goto found; |
4127 | 266 } |
267 } | |
268 | |
269 return NGX_OK; | |
6167
87d48f8793b6
Upstream keepalive: reduced diffs to the plus version of nginx.
Roman Arutyunyan <arut@nginx.com>
parents:
5999
diff
changeset
|
270 |
87d48f8793b6
Upstream keepalive: reduced diffs to the plus version of nginx.
Roman Arutyunyan <arut@nginx.com>
parents:
5999
diff
changeset
|
271 found: |
87d48f8793b6
Upstream keepalive: reduced diffs to the plus version of nginx.
Roman Arutyunyan <arut@nginx.com>
parents:
5999
diff
changeset
|
272 |
87d48f8793b6
Upstream keepalive: reduced diffs to the plus version of nginx.
Roman Arutyunyan <arut@nginx.com>
parents:
5999
diff
changeset
|
273 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0, |
87d48f8793b6
Upstream keepalive: reduced diffs to the plus version of nginx.
Roman Arutyunyan <arut@nginx.com>
parents:
5999
diff
changeset
|
274 "get keepalive peer: using connection %p", c); |
87d48f8793b6
Upstream keepalive: reduced diffs to the plus version of nginx.
Roman Arutyunyan <arut@nginx.com>
parents:
5999
diff
changeset
|
275 |
87d48f8793b6
Upstream keepalive: reduced diffs to the plus version of nginx.
Roman Arutyunyan <arut@nginx.com>
parents:
5999
diff
changeset
|
276 c->idle = 0; |
87d48f8793b6
Upstream keepalive: reduced diffs to the plus version of nginx.
Roman Arutyunyan <arut@nginx.com>
parents:
5999
diff
changeset
|
277 c->sent = 0; |
7600
3939483cd1b5
Upstream keepalive: clearing of c->data in cached connections.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7340
diff
changeset
|
278 c->data = NULL; |
6167
87d48f8793b6
Upstream keepalive: reduced diffs to the plus version of nginx.
Roman Arutyunyan <arut@nginx.com>
parents:
5999
diff
changeset
|
279 c->log = pc->log; |
87d48f8793b6
Upstream keepalive: reduced diffs to the plus version of nginx.
Roman Arutyunyan <arut@nginx.com>
parents:
5999
diff
changeset
|
280 c->read->log = pc->log; |
87d48f8793b6
Upstream keepalive: reduced diffs to the plus version of nginx.
Roman Arutyunyan <arut@nginx.com>
parents:
5999
diff
changeset
|
281 c->write->log = pc->log; |
87d48f8793b6
Upstream keepalive: reduced diffs to the plus version of nginx.
Roman Arutyunyan <arut@nginx.com>
parents:
5999
diff
changeset
|
282 c->pool->log = pc->log; |
87d48f8793b6
Upstream keepalive: reduced diffs to the plus version of nginx.
Roman Arutyunyan <arut@nginx.com>
parents:
5999
diff
changeset
|
283 |
7339
d9029e113a05
Upstream keepalive: keepalive_timeout directive.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7338
diff
changeset
|
284 if (c->read->timer_set) { |
d9029e113a05
Upstream keepalive: keepalive_timeout directive.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7338
diff
changeset
|
285 ngx_del_timer(c->read); |
d9029e113a05
Upstream keepalive: keepalive_timeout directive.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7338
diff
changeset
|
286 } |
d9029e113a05
Upstream keepalive: keepalive_timeout directive.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7338
diff
changeset
|
287 |
6167
87d48f8793b6
Upstream keepalive: reduced diffs to the plus version of nginx.
Roman Arutyunyan <arut@nginx.com>
parents:
5999
diff
changeset
|
288 pc->connection = c; |
87d48f8793b6
Upstream keepalive: reduced diffs to the plus version of nginx.
Roman Arutyunyan <arut@nginx.com>
parents:
5999
diff
changeset
|
289 pc->cached = 1; |
87d48f8793b6
Upstream keepalive: reduced diffs to the plus version of nginx.
Roman Arutyunyan <arut@nginx.com>
parents:
5999
diff
changeset
|
290 |
87d48f8793b6
Upstream keepalive: reduced diffs to the plus version of nginx.
Roman Arutyunyan <arut@nginx.com>
parents:
5999
diff
changeset
|
291 return NGX_DONE; |
4127 | 292 } |
293 | |
294 | |
295 static void | |
296 ngx_http_upstream_free_keepalive_peer(ngx_peer_connection_t *pc, void *data, | |
297 ngx_uint_t state) | |
298 { | |
299 ngx_http_upstream_keepalive_peer_data_t *kp = data; | |
300 ngx_http_upstream_keepalive_cache_t *item; | |
301 | |
302 ngx_queue_t *q; | |
303 ngx_connection_t *c; | |
304 ngx_http_upstream_t *u; | |
305 | |
306 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, pc->log, 0, | |
307 "free keepalive peer"); | |
308 | |
309 /* cache valid connections */ | |
310 | |
311 u = kp->upstream; | |
312 c = pc->connection; | |
313 | |
5133
089a662c17d1
Upstream: removed double-free workarounds in peer.free() methods.
Ruslan Ermilov <ru@nginx.com>
parents:
4998
diff
changeset
|
314 if (state & NGX_PEER_FAILED |
4127 | 315 || c == NULL |
316 || c->read->eof | |
317 || c->read->error | |
318 || c->read->timedout | |
319 || c->write->error | |
320 || c->write->timedout) | |
321 { | |
322 goto invalid; | |
323 } | |
324 | |
7340
70c6b08973a0
Upstream keepalive: keepalive_requests directive.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7339
diff
changeset
|
325 if (c->requests >= kp->conf->requests) { |
70c6b08973a0
Upstream keepalive: keepalive_requests directive.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7339
diff
changeset
|
326 goto invalid; |
70c6b08973a0
Upstream keepalive: keepalive_requests directive.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7339
diff
changeset
|
327 } |
70c6b08973a0
Upstream keepalive: keepalive_requests directive.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7339
diff
changeset
|
328 |
4127 | 329 if (!u->keepalive) { |
330 goto invalid; | |
331 } | |
332 | |
6332
78b4e10b4367
Upstream: don't keep connections on early responses (ticket #669).
Maxim Dounin <mdounin@mdounin.ru>
parents:
6220
diff
changeset
|
333 if (!u->request_body_sent) { |
78b4e10b4367
Upstream: don't keep connections on early responses (ticket #669).
Maxim Dounin <mdounin@mdounin.ru>
parents:
6220
diff
changeset
|
334 goto invalid; |
78b4e10b4367
Upstream: don't keep connections on early responses (ticket #669).
Maxim Dounin <mdounin@mdounin.ru>
parents:
6220
diff
changeset
|
335 } |
78b4e10b4367
Upstream: don't keep connections on early responses (ticket #669).
Maxim Dounin <mdounin@mdounin.ru>
parents:
6220
diff
changeset
|
336 |
6220
5e6142609e48
Core: idle connections now closed only once on exiting.
Valentin Bartenev <vbart@nginx.com>
parents:
6167
diff
changeset
|
337 if (ngx_terminate || ngx_exiting) { |
5e6142609e48
Core: idle connections now closed only once on exiting.
Valentin Bartenev <vbart@nginx.com>
parents:
6167
diff
changeset
|
338 goto invalid; |
5e6142609e48
Core: idle connections now closed only once on exiting.
Valentin Bartenev <vbart@nginx.com>
parents:
6167
diff
changeset
|
339 } |
5e6142609e48
Core: idle connections now closed only once on exiting.
Valentin Bartenev <vbart@nginx.com>
parents:
6167
diff
changeset
|
340 |
4127 | 341 if (ngx_handle_read_event(c->read, 0) != NGX_OK) { |
342 goto invalid; | |
343 } | |
344 | |
345 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0, | |
346 "free keepalive peer: saving connection %p", c); | |
347 | |
348 if (ngx_queue_empty(&kp->conf->free)) { | |
349 | |
350 q = ngx_queue_last(&kp->conf->cache); | |
351 ngx_queue_remove(q); | |
352 | |
353 item = ngx_queue_data(q, ngx_http_upstream_keepalive_cache_t, queue); | |
354 | |
355 ngx_http_upstream_keepalive_close(item->connection); | |
356 | |
357 } else { | |
358 q = ngx_queue_head(&kp->conf->free); | |
359 ngx_queue_remove(q); | |
360 | |
361 item = ngx_queue_data(q, ngx_http_upstream_keepalive_cache_t, queue); | |
362 } | |
363 | |
6167
87d48f8793b6
Upstream keepalive: reduced diffs to the plus version of nginx.
Roman Arutyunyan <arut@nginx.com>
parents:
5999
diff
changeset
|
364 ngx_queue_insert_head(&kp->conf->cache, q); |
87d48f8793b6
Upstream keepalive: reduced diffs to the plus version of nginx.
Roman Arutyunyan <arut@nginx.com>
parents:
5999
diff
changeset
|
365 |
4127 | 366 item->connection = c; |
367 | |
368 pc->connection = NULL; | |
369 | |
7339
d9029e113a05
Upstream keepalive: keepalive_timeout directive.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7338
diff
changeset
|
370 c->read->delayed = 0; |
d9029e113a05
Upstream keepalive: keepalive_timeout directive.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7338
diff
changeset
|
371 ngx_add_timer(c->read, kp->conf->timeout); |
d9029e113a05
Upstream keepalive: keepalive_timeout directive.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7338
diff
changeset
|
372 |
4127 | 373 if (c->write->timer_set) { |
374 ngx_del_timer(c->write); | |
375 } | |
376 | |
377 c->write->handler = ngx_http_upstream_keepalive_dummy_handler; | |
378 c->read->handler = ngx_http_upstream_keepalive_close_handler; | |
379 | |
380 c->data = item; | |
381 c->idle = 1; | |
382 c->log = ngx_cycle->log; | |
383 c->read->log = ngx_cycle->log; | |
384 c->write->log = ngx_cycle->log; | |
385 c->pool->log = ngx_cycle->log; | |
386 | |
387 item->socklen = pc->socklen; | |
388 ngx_memcpy(&item->sockaddr, pc->sockaddr, pc->socklen); | |
389 | |
390 if (c->read->ready) { | |
391 ngx_http_upstream_keepalive_close_handler(c->read); | |
392 } | |
393 | |
394 invalid: | |
395 | |
396 kp->original_free_peer(pc, kp->data, state); | |
397 } | |
398 | |
399 | |
400 static void | |
401 ngx_http_upstream_keepalive_dummy_handler(ngx_event_t *ev) | |
402 { | |
403 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ev->log, 0, | |
404 "keepalive dummy handler"); | |
405 } | |
406 | |
407 | |
408 static void | |
409 ngx_http_upstream_keepalive_close_handler(ngx_event_t *ev) | |
410 { | |
411 ngx_http_upstream_keepalive_srv_conf_t *conf; | |
412 ngx_http_upstream_keepalive_cache_t *item; | |
413 | |
414 int n; | |
415 char buf[1]; | |
416 ngx_connection_t *c; | |
417 | |
418 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ev->log, 0, | |
419 "keepalive close handler"); | |
420 | |
421 c = ev->data; | |
422 | |
7339
d9029e113a05
Upstream keepalive: keepalive_timeout directive.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7338
diff
changeset
|
423 if (c->close || c->read->timedout) { |
4127 | 424 goto close; |
425 } | |
426 | |
427 n = recv(c->fd, buf, 1, MSG_PEEK); | |
428 | |
429 if (n == -1 && ngx_socket_errno == NGX_EAGAIN) { | |
5999
4d8936b1fc32
Upstream keepalive: drop ready flag on EAGAIN from recv(MSG_PEEK).
Valentin Bartenev <vbart@nginx.com>
parents:
5864
diff
changeset
|
430 ev->ready = 0; |
4127 | 431 |
432 if (ngx_handle_read_event(c->read, 0) != NGX_OK) { | |
433 goto close; | |
434 } | |
435 | |
436 return; | |
437 } | |
438 | |
439 close: | |
440 | |
441 item = c->data; | |
442 conf = item->conf; | |
443 | |
444 ngx_http_upstream_keepalive_close(c); | |
445 | |
446 ngx_queue_remove(&item->queue); | |
447 ngx_queue_insert_head(&conf->free, &item->queue); | |
448 } | |
449 | |
450 | |
451 static void | |
452 ngx_http_upstream_keepalive_close(ngx_connection_t *c) | |
453 { | |
454 | |
455 #if (NGX_HTTP_SSL) | |
456 | |
457 if (c->ssl) { | |
458 c->ssl->no_wait_shutdown = 1; | |
459 c->ssl->no_send_shutdown = 1; | |
460 | |
461 if (ngx_ssl_shutdown(c) == NGX_AGAIN) { | |
462 c->ssl->handler = ngx_http_upstream_keepalive_close; | |
463 return; | |
464 } | |
465 } | |
466 | |
467 #endif | |
468 | |
469 ngx_destroy_pool(c->pool); | |
470 ngx_close_connection(c); | |
471 } | |
472 | |
473 | |
474 #if (NGX_HTTP_SSL) | |
475 | |
476 static ngx_int_t | |
477 ngx_http_upstream_keepalive_set_session(ngx_peer_connection_t *pc, void *data) | |
478 { | |
479 ngx_http_upstream_keepalive_peer_data_t *kp = data; | |
480 | |
481 return kp->original_set_session(pc, kp->data); | |
482 } | |
483 | |
484 | |
485 static void | |
486 ngx_http_upstream_keepalive_save_session(ngx_peer_connection_t *pc, void *data) | |
487 { | |
488 ngx_http_upstream_keepalive_peer_data_t *kp = data; | |
489 | |
490 kp->original_save_session(pc, kp->data); | |
491 return; | |
492 } | |
493 | |
494 #endif | |
495 | |
496 | |
497 static void * | |
498 ngx_http_upstream_keepalive_create_conf(ngx_conf_t *cf) | |
499 { | |
500 ngx_http_upstream_keepalive_srv_conf_t *conf; | |
501 | |
502 conf = ngx_pcalloc(cf->pool, | |
503 sizeof(ngx_http_upstream_keepalive_srv_conf_t)); | |
504 if (conf == NULL) { | |
505 return NULL; | |
506 } | |
507 | |
508 /* | |
509 * set by ngx_pcalloc(): | |
510 * | |
511 * conf->original_init_upstream = NULL; | |
512 * conf->original_init_peer = NULL; | |
6167
87d48f8793b6
Upstream keepalive: reduced diffs to the plus version of nginx.
Roman Arutyunyan <arut@nginx.com>
parents:
5999
diff
changeset
|
513 * conf->max_cached = 0; |
4127 | 514 */ |
515 | |
7339
d9029e113a05
Upstream keepalive: keepalive_timeout directive.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7338
diff
changeset
|
516 conf->timeout = NGX_CONF_UNSET_MSEC; |
7340
70c6b08973a0
Upstream keepalive: keepalive_requests directive.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7339
diff
changeset
|
517 conf->requests = NGX_CONF_UNSET_UINT; |
7339
d9029e113a05
Upstream keepalive: keepalive_timeout directive.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7338
diff
changeset
|
518 |
4127 | 519 return conf; |
520 } | |
521 | |
522 | |
523 static char * | |
524 ngx_http_upstream_keepalive(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | |
525 { | |
526 ngx_http_upstream_srv_conf_t *uscf; | |
5213
822b82191940
Upstream keepalive: slightly simplified code.
Ruslan Ermilov <ru@nginx.com>
parents:
5133
diff
changeset
|
527 ngx_http_upstream_keepalive_srv_conf_t *kcf = conf; |
4127 | 528 |
529 ngx_int_t n; | |
530 ngx_str_t *value; | |
531 | |
6167
87d48f8793b6
Upstream keepalive: reduced diffs to the plus version of nginx.
Roman Arutyunyan <arut@nginx.com>
parents:
5999
diff
changeset
|
532 if (kcf->max_cached) { |
4998
82336a9ce26d
Upstream keepalive: detect duplicate "keepalive" directive.
Ruslan Ermilov <ru@nginx.com>
parents:
4694
diff
changeset
|
533 return "is duplicate"; |
82336a9ce26d
Upstream keepalive: detect duplicate "keepalive" directive.
Ruslan Ermilov <ru@nginx.com>
parents:
4694
diff
changeset
|
534 } |
82336a9ce26d
Upstream keepalive: detect duplicate "keepalive" directive.
Ruslan Ermilov <ru@nginx.com>
parents:
4694
diff
changeset
|
535 |
4127 | 536 /* read options */ |
537 | |
538 value = cf->args->elts; | |
539 | |
540 n = ngx_atoi(value[1].data, value[1].len); | |
541 | |
542 if (n == NGX_ERROR || n == 0) { | |
543 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
544 "invalid value \"%V\" in \"%V\" directive", | |
545 &value[1], &cmd->name); | |
546 return NGX_CONF_ERROR; | |
547 } | |
548 | |
549 kcf->max_cached = n; | |
550 | |
7338
46174066b75f
Upstream keepalive: comment added.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7165
diff
changeset
|
551 /* init upstream handler */ |
46174066b75f
Upstream keepalive: comment added.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7165
diff
changeset
|
552 |
6167
87d48f8793b6
Upstream keepalive: reduced diffs to the plus version of nginx.
Roman Arutyunyan <arut@nginx.com>
parents:
5999
diff
changeset
|
553 uscf = ngx_http_conf_get_module_srv_conf(cf, ngx_http_upstream_module); |
87d48f8793b6
Upstream keepalive: reduced diffs to the plus version of nginx.
Roman Arutyunyan <arut@nginx.com>
parents:
5999
diff
changeset
|
554 |
87d48f8793b6
Upstream keepalive: reduced diffs to the plus version of nginx.
Roman Arutyunyan <arut@nginx.com>
parents:
5999
diff
changeset
|
555 kcf->original_init_upstream = uscf->peer.init_upstream |
87d48f8793b6
Upstream keepalive: reduced diffs to the plus version of nginx.
Roman Arutyunyan <arut@nginx.com>
parents:
5999
diff
changeset
|
556 ? uscf->peer.init_upstream |
87d48f8793b6
Upstream keepalive: reduced diffs to the plus version of nginx.
Roman Arutyunyan <arut@nginx.com>
parents:
5999
diff
changeset
|
557 : ngx_http_upstream_init_round_robin; |
87d48f8793b6
Upstream keepalive: reduced diffs to the plus version of nginx.
Roman Arutyunyan <arut@nginx.com>
parents:
5999
diff
changeset
|
558 |
87d48f8793b6
Upstream keepalive: reduced diffs to the plus version of nginx.
Roman Arutyunyan <arut@nginx.com>
parents:
5999
diff
changeset
|
559 uscf->peer.init_upstream = ngx_http_upstream_init_keepalive; |
87d48f8793b6
Upstream keepalive: reduced diffs to the plus version of nginx.
Roman Arutyunyan <arut@nginx.com>
parents:
5999
diff
changeset
|
560 |
4127 | 561 return NGX_CONF_OK; |
562 } |