Mercurial > hg > nginx
view src/core/ngx_open_file_cache.h @ 7281:bd6563e81cea
Limit req: improved handling of negative times.
Negative times can appear since workers only update time on an event
loop iteration start. If a worker was blocked for a long time during
an event loop iteration, it is possible that another worker already
updated the time stored in the node. As such, time since last update
of the node (ms) will be negative.
Previous code used ngx_abs(ms) in the calculations. That is, negative
times were effectively treated as positive ones. As a result, it was
not possible to maintain high request rates, where the same node can be
updated multiple times from during an event loop iteration.
In particular, this affected setups with many SSL handshakes, see
http://mailman.nginx.org/pipermail/nginx/2018-May/056291.html.
Fix is to only update the last update time stored in the node if the
new time is larger than previously stored one. If a future time is
stored in the node, we preserve this time as is.
To prevent breaking things on platforms without monotonic time available
if system time is updated backwards, a safety limit of 60 seconds is
used. If the time stored in the node is more than 60 seconds in the future,
we assume that the time was changed backwards and update lr->last
to the current time.
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Wed, 30 May 2018 15:40:34 +0300 |
parents | 47ece8818978 |
children |
line wrap: on
line source
/* * Copyright (C) Igor Sysoev * Copyright (C) Nginx, Inc. */ #include <ngx_config.h> #include <ngx_core.h> #ifndef _NGX_OPEN_FILE_CACHE_H_INCLUDED_ #define _NGX_OPEN_FILE_CACHE_H_INCLUDED_ #define NGX_OPEN_FILE_DIRECTIO_OFF NGX_MAX_OFF_T_VALUE typedef struct { ngx_fd_t fd; ngx_file_uniq_t uniq; time_t mtime; off_t size; off_t fs_size; off_t directio; size_t read_ahead; ngx_err_t err; char *failed; time_t valid; ngx_uint_t min_uses; #if (NGX_HAVE_OPENAT) size_t disable_symlinks_from; unsigned disable_symlinks:2; #endif unsigned test_dir:1; unsigned test_only:1; unsigned log:1; unsigned errors:1; unsigned events:1; unsigned is_dir:1; unsigned is_file:1; unsigned is_link:1; unsigned is_exec:1; unsigned is_directio:1; } ngx_open_file_info_t; typedef struct ngx_cached_open_file_s ngx_cached_open_file_t; struct ngx_cached_open_file_s { ngx_rbtree_node_t node; ngx_queue_t queue; u_char *name; time_t created; time_t accessed; ngx_fd_t fd; ngx_file_uniq_t uniq; time_t mtime; off_t size; ngx_err_t err; uint32_t uses; #if (NGX_HAVE_OPENAT) size_t disable_symlinks_from; unsigned disable_symlinks:2; #endif unsigned count:24; unsigned close:1; unsigned use_event:1; unsigned is_dir:1; unsigned is_file:1; unsigned is_link:1; unsigned is_exec:1; unsigned is_directio:1; ngx_event_t *event; }; typedef struct { ngx_rbtree_t rbtree; ngx_rbtree_node_t sentinel; ngx_queue_t expire_queue; ngx_uint_t current; ngx_uint_t max; time_t inactive; } ngx_open_file_cache_t; typedef struct { ngx_open_file_cache_t *cache; ngx_cached_open_file_t *file; ngx_uint_t min_uses; ngx_log_t *log; } ngx_open_file_cache_cleanup_t; typedef struct { /* ngx_connection_t stub to allow use c->fd as event ident */ void *data; ngx_event_t *read; ngx_event_t *write; ngx_fd_t fd; ngx_cached_open_file_t *file; ngx_open_file_cache_t *cache; } ngx_open_file_cache_event_t; ngx_open_file_cache_t *ngx_open_file_cache_init(ngx_pool_t *pool, ngx_uint_t max, time_t inactive); ngx_int_t ngx_open_cached_file(ngx_open_file_cache_t *cache, ngx_str_t *name, ngx_open_file_info_t *of, ngx_pool_t *pool); #endif /* _NGX_OPEN_FILE_CACHE_H_INCLUDED_ */