##// END OF EJS Templates
configs: moved gunicorn configs to python files
super-admin -
r5125:d0f694ba default
parent child Browse files
Show More
@@ -27,9 +27,10 b' debug = true'
27 27 #smtp_use_ssl = true
28 28
29 29 [server:main]
30 ; COMMON HOST/IP CONFIG
30 ; COMMON HOST/IP CONFIG, This applies mostly to develop setup,
31 ; Host port for gunicorn are controlled by gunicorn_conf.py
31 32 host = 127.0.0.1
32 port = 5000
33 port = 10020
33 34
34 35 ; ##################################################
35 36 ; WAITRESS WSGI SERVER - Recommended for Development
@@ -53,85 +54,11 b' asyncore_use_poll = true'
53 54 ; GUNICORN APPLICATION SERVER
54 55 ; ###########################
55 56
56 ; run with gunicorn --log-config rhodecode.ini --paste rhodecode.ini
57 ; run with gunicorn --paste rhodecode.ini --config gunicorn_conf.py
57 58
58 59 ; Module to use, this setting shouldn't be changed
59 60 #use = egg:gunicorn#main
60 61
61 ; Sets the number of process workers. More workers means more concurrent connections
62 ; RhodeCode can handle at the same time. Each additional worker also it increases
63 ; memory usage as each has it's own set of caches.
64 ; Recommended value is (2 * NUMBER_OF_CPUS + 1), eg 2CPU = 5 workers, but no more
65 ; than 8-10 unless for really big deployments .e.g 700-1000 users.
66 ; `instance_id = *` must be set in the [app:main] section below (which is the default)
67 ; when using more than 1 worker.
68 #workers = 2
69
70 ; Gunicorn access log level
71 #loglevel = info
72
73 ; Process name visible in process list
74 #proc_name = rhodecode
75
76 ; Type of worker class, one of `sync`, `gevent`
77 ; Recommended type is `gevent`
78 #worker_class = gevent
79
80 ; The maximum number of simultaneous clients per worker. Valid only for gevent
81 #worker_connections = 10
82
83 ; The maximum number of pending connections worker will queue to handle
84 #backlog = 64
85
86 ; Max number of requests that worker will handle before being gracefully restarted.
87 ; Prevents memory leaks, jitter adds variability so not all workers are restarted at once.
88 #max_requests = 1000
89 #max_requests_jitter = 30
90
91 ; Amount of time a worker can spend with handling a request before it
92 ; gets killed and restarted. By default set to 21600 (6hrs)
93 ; Examples: 1800 (30min), 3600 (1hr), 7200 (2hr), 43200 (12h)
94 #timeout = 21600
95
96 ; The maximum size of HTTP request line in bytes.
97 ; 0 for unlimited
98 #limit_request_line = 0
99
100 ; Limit the number of HTTP headers fields in a request.
101 ; By default this value is 100 and can't be larger than 32768.
102 #limit_request_fields = 32768
103
104 ; Limit the allowed size of an HTTP request header field.
105 ; Value is a positive number or 0.
106 ; Setting it to 0 will allow unlimited header field sizes.
107 #limit_request_field_size = 0
108
109 ; Timeout for graceful workers restart.
110 ; After receiving a restart signal, workers have this much time to finish
111 ; serving requests. Workers still alive after the timeout (starting from the
112 ; receipt of the restart signal) are force killed.
113 ; Examples: 1800 (30min), 3600 (1hr), 7200 (2hr), 43200 (12h)
114 #graceful_timeout = 3600
115
116 # The number of seconds to wait for requests on a Keep-Alive connection.
117 # Generally set in the 1-5 seconds range.
118 #keepalive = 2
119
120 ; Maximum memory usage that each worker can use before it will receive a
121 ; graceful restart signal 0 = memory monitoring is disabled
122 ; Examples: 268435456 (256MB), 536870912 (512MB)
123 ; 1073741824 (1GB), 2147483648 (2GB), 4294967296 (4GB)
124 #memory_max_usage = 0
125
126 ; How often in seconds to check for memory usage for each gunicorn worker
127 #memory_usage_check_interval = 60
128
129 ; Threshold value for which we don't recycle worker if GarbageCollection
130 ; frees up enough resources. Before each restart we try to run GC on worker
131 ; in case we get enough free memory after that, restart will not happen.
132 #memory_usage_recovery_threshold = 0.8
133
134
135 62 ; Prefix middleware for RhodeCode.
136 63 ; recommended when using proxy setup.
137 64 ; allows to set RhodeCode under a prefix in server.
@@ -625,6 +552,9 b' sqlalchemy.db1.pool_recycle = 3600'
625 552
626 553 ; the number of connections to keep open inside the connection pool.
627 554 ; 0 indicates no limit
555 ; the general calculus with gevent is:
556 ; if your system allows 500 concurrent greenlets (max_connections) that all do database access,
557 ; then increase pool size + max overflow so that they add up to 500.
628 558 #sqlalchemy.db1.pool_size = 5
629 559
630 560 ; The number of connections to allow in connection pool "overflow", that is
@@ -12,6 +12,7 b' import threading'
12 12 import traceback
13 13 import random
14 14 import socket
15 import dataclasses
15 16 from gunicorn.glogging import Logger
16 17
17 18
@@ -19,8 +20,14 b' def get_workers():'
19 20 import multiprocessing
20 21 return multiprocessing.cpu_count() * 2 + 1
21 22
22 # GLOBAL
23
24 bind = "127.0.0.1:10020"
25
26
27 # Error logging output for gunicorn (-) is stdout
23 28 errorlog = '-'
29
30 # Access logging output for gunicorn (-) is stdout
24 31 accesslog = '-'
25 32
26 33
@@ -30,6 +37,7 b" accesslog = '-'"
30 37 worker_tmp_dir = None
31 38 tmp_upload_dir = None
32 39
40 # use re-use port logic
33 41 #reuse_port = True
34 42
35 43 # Custom log format
@@ -40,9 +48,91 b' tmp_upload_dir = None'
40 48 access_log_format = (
41 49 'time="%(t)s" pid=%(p)s level="INFO" type="[GNCRN]" ip="%(h)-15s" rqt="%(L)s" response_code="%(s)s" response_bytes="%(b)-6s" uri="%(m)s:%(U)s %(q)s" user=":%(u)s" user_agent="%(a)s"')
42 50
43 # self adjust workers based on CPU count
51
52 # Sets the number of process workers. More workers means more concurrent connections
53 # RhodeCode can handle at the same time. Each additional worker also it increases
54 # memory usage as each has it's own set of caches.
55 # Recommended value is (2 * NUMBER_OF_CPUS + 1), eg 2CPU = 5 workers, but no more
56 # than 8-10 unless for huge deployments .e.g 700-1000 users.
57 # `instance_id = *` must be set in the [app:main] section below (which is the default)
58 # when using more than 1 worker.
59 workers = 4
60
61 # self adjust workers based on CPU count, to use maximum of CPU and not overquota the resources
44 62 # workers = get_workers()
45 63
64 # Gunicorn access log level
65 loglevel = 'info'
66
67 # Process name visible in process list
68 proc_name = 'rhodecode_enterprise'
69
70 # Type of worker class, one of `sync`, `gevent`
71 # currently `sync` is the only option allowed.
72 worker_class = 'gevent'
73
74 # The maximum number of simultaneous clients. Valid only for gevent
75 worker_connections = 10
76
77 # Max number of requests that worker will handle before being gracefully restarted.
78 # Prevents memory leaks, jitter adds variability so not all workers are restarted at once.
79 max_requests = 2000
80 max_requests_jitter = 30
81
82 # The maximum number of pending connections.
83 # Exceeding this number results in the client getting an error when attempting to connect.
84 backlog = 64
85
86 # Amount of time a worker can spend with handling a request before it
87 # gets killed and restarted. By default set to 21600 (6hrs)
88 # Examples: 1800 (30min), 3600 (1hr), 7200 (2hr), 43200 (12h)
89 timeout = 21600
90
91 # The maximum size of HTTP request line in bytes.
92 # 0 for unlimited
93 limit_request_line = 0
94
95 # Limit the number of HTTP headers fields in a request.
96 # By default this value is 100 and can't be larger than 32768.
97 limit_request_fields = 32768
98
99 # Limit the allowed size of an HTTP request header field.
100 # Value is a positive number or 0.
101 # Setting it to 0 will allow unlimited header field sizes.
102 limit_request_field_size = 0
103
104 # Timeout for graceful workers restart.
105 # After receiving a restart signal, workers have this much time to finish
106 # serving requests. Workers still alive after the timeout (starting from the
107 # receipt of the restart signal) are force killed.
108 # Examples: 1800 (30min), 3600 (1hr), 7200 (2hr), 43200 (12h)
109 graceful_timeout = 21600
110
111 # The number of seconds to wait for requests on a Keep-Alive connection.
112 # Generally set in the 1-5 seconds range.
113 keepalive = 2
114
115 # Maximum memory usage that each worker can use before it will receive a
116 # graceful restart signal 0 = memory monitoring is disabled
117 # Examples: 268435456 (256MB), 536870912 (512MB)
118 # 1073741824 (1GB), 2147483648 (2GB), 4294967296 (4GB)
119 memory_max_usage = 0
120
121 # How often in seconds to check for memory usage for each gunicorn worker
122 memory_usage_check_interval = 60
123
124 # Threshold value for which we don't recycle worker if GarbageCollection
125 # frees up enough resources. Before each restart we try to run GC on worker
126 # in case we get enough free memory after that, restart will not happen.
127 memory_usage_recovery_threshold = 0.8
128
129
130 @dataclasses.dataclass
131 class MemoryCheckConfig:
132 max_usage: int
133 check_interval: int
134 recovery_threshold: float
135
46 136
47 137 def _get_process_rss(pid=None):
48 138 try:
@@ -67,8 +157,40 b' def _get_config(ini_path):'
67 157 return None
68 158
69 159
70 def _time_with_offset(memory_usage_check_interval):
71 return time.time() - random.randint(0, memory_usage_check_interval/2.0)
160 def get_memory_usage_params(config=None):
161 # memory spec defaults
162 _memory_max_usage = memory_max_usage
163 _memory_usage_check_interval = memory_usage_check_interval
164 _memory_usage_recovery_threshold = memory_usage_recovery_threshold
165
166 if config:
167 ini_path = os.path.abspath(config)
168 conf = _get_config(ini_path)
169
170 section = 'server:main'
171 if conf and conf.has_section(section):
172
173 if conf.has_option(section, 'memory_max_usage'):
174 _memory_max_usage = conf.getint(section, 'memory_max_usage')
175
176 if conf.has_option(section, 'memory_usage_check_interval'):
177 _memory_usage_check_interval = conf.getint(section, 'memory_usage_check_interval')
178
179 if conf.has_option(section, 'memory_usage_recovery_threshold'):
180 _memory_usage_recovery_threshold = conf.getfloat(section, 'memory_usage_recovery_threshold')
181
182 _memory_max_usage = int(os.environ.get('RC_GUNICORN_MEMORY_MAX_USAGE', '')
183 or _memory_max_usage)
184 _memory_usage_check_interval = int(os.environ.get('RC_GUNICORN_MEMORY_USAGE_CHECK_INTERVAL', '')
185 or _memory_usage_check_interval)
186 _memory_usage_recovery_threshold = float(os.environ.get('RC_GUNICORN_MEMORY_USAGE_RECOVERY_THRESHOLD', '')
187 or _memory_usage_recovery_threshold)
188
189 return MemoryCheckConfig(_memory_max_usage, _memory_usage_check_interval, _memory_usage_recovery_threshold)
190
191
192 def _time_with_offset(check_interval):
193 return time.time() - random.randint(0, check_interval/2.0)
72 194
73 195
74 196 def pre_fork(server, worker):
@@ -77,25 +199,10 b' def pre_fork(server, worker):'
77 199
78 200 def post_fork(server, worker):
79 201
80 # memory spec defaults
81 _memory_max_usage = 0
82 _memory_usage_check_interval = 60
83 _memory_usage_recovery_threshold = 0.8
84
85 ini_path = os.path.abspath(server.cfg.paste)
86 conf = _get_config(ini_path)
87
88 section = 'server:main'
89 if conf and conf.has_section(section):
90
91 if conf.has_option(section, 'memory_max_usage'):
92 _memory_max_usage = conf.getint(section, 'memory_max_usage')
93
94 if conf.has_option(section, 'memory_usage_check_interval'):
95 _memory_usage_check_interval = conf.getint(section, 'memory_usage_check_interval')
96
97 if conf.has_option(section, 'memory_usage_recovery_threshold'):
98 _memory_usage_recovery_threshold = conf.getfloat(section, 'memory_usage_recovery_threshold')
202 memory_conf = get_memory_usage_params()
203 _memory_max_usage = memory_conf.max_usage
204 _memory_usage_check_interval = memory_conf.check_interval
205 _memory_usage_recovery_threshold = memory_conf.recovery_threshold
99 206
100 207 worker._memory_max_usage = int(os.environ.get('RC_GUNICORN_MEMORY_MAX_USAGE', '')
101 208 or _memory_max_usage)
@@ -109,10 +216,10 b' def post_fork(server, worker):'
109 216 worker._last_memory_check_time = _time_with_offset(_memory_usage_check_interval)
110 217
111 218 if _memory_max_usage:
112 server.log.info("[%-10s] WORKER spawned with max memory set at %s", worker.pid,
219 server.log.info("pid=[%-10s] WORKER spawned with max memory set at %s", worker.pid,
113 220 _format_data_size(_memory_max_usage))
114 221 else:
115 server.log.info("[%-10s] WORKER spawned", worker.pid)
222 server.log.info("pid=[%-10s] WORKER spawned", worker.pid)
116 223
117 224
118 225 def pre_exec(server):
@@ -181,42 +288,45 b' def _format_data_size(size, unit="B", pr'
181 288
182 289
183 290 def _check_memory_usage(worker):
184 memory_max_usage = worker._memory_max_usage
185 if not memory_max_usage:
291 _memory_max_usage = worker._memory_max_usage
292 if not _memory_max_usage:
186 293 return
187 294
188 memory_usage_check_interval = worker._memory_usage_check_interval
189 memory_usage_recovery_threshold = memory_max_usage * worker._memory_usage_recovery_threshold
295 _memory_usage_check_interval = worker._memory_usage_check_interval
296 _memory_usage_recovery_threshold = memory_max_usage * worker._memory_usage_recovery_threshold
190 297
191 298 elapsed = time.time() - worker._last_memory_check_time
192 if elapsed > memory_usage_check_interval:
299 if elapsed > _memory_usage_check_interval:
193 300 mem_usage = _get_process_rss()
194 if mem_usage and mem_usage > memory_max_usage:
301 if mem_usage and mem_usage > _memory_max_usage:
195 302 worker.log.info(
196 303 "memory usage %s > %s, forcing gc",
197 _format_data_size(mem_usage), _format_data_size(memory_max_usage))
304 _format_data_size(mem_usage), _format_data_size(_memory_max_usage))
198 305 # Try to clean it up by forcing a full collection.
199 306 gc.collect()
200 307 mem_usage = _get_process_rss()
201 if mem_usage > memory_usage_recovery_threshold:
308 if mem_usage > _memory_usage_recovery_threshold:
202 309 # Didn't clean up enough, we'll have to terminate.
203 310 worker.log.warning(
204 311 "memory usage %s > %s after gc, quitting",
205 _format_data_size(mem_usage), _format_data_size(memory_max_usage))
312 _format_data_size(mem_usage), _format_data_size(_memory_max_usage))
206 313 # This will cause worker to auto-restart itself
207 314 worker.alive = False
208 315 worker._last_memory_check_time = time.time()
209 316
210 317
211 318 def worker_int(worker):
212 worker.log.info("[%-10s] worker received INT or QUIT signal", worker.pid)
319 worker.log.info("pid=[%-10s] worker received INT or QUIT signal", worker.pid)
213 320
214 321 # get traceback info, on worker crash
215 id2name = dict([(th.ident, th.name) for th in threading.enumerate()])
322 def get_thread_id(t_id):
323 id2name = dict([(th.ident, th.name) for th in threading.enumerate()])
324 return id2name.get(t_id, "unknown_thread_id")
325
216 326 code = []
217 327 for thread_id, stack in sys._current_frames().items():
218 328 code.append(
219 "\n# Thread: %s(%d)" % (id2name.get(thread_id, ""), thread_id))
329 "\n# Thread: %s(%d)" % (get_thread_id(thread_id), thread_id))
220 330 for fname, lineno, name, line in traceback.extract_stack(stack):
221 331 code.append('File: "%s", line %d, in %s' % (fname, lineno, name))
222 332 if line:
@@ -225,15 +335,15 b' def worker_int(worker):'
225 335
226 336
227 337 def worker_abort(worker):
228 worker.log.info("[%-10s] worker received SIGABRT signal", worker.pid)
338 worker.log.info("pid=[%-10s] worker received SIGABRT signal", worker.pid)
229 339
230 340
231 341 def worker_exit(server, worker):
232 worker.log.info("[%-10s] worker exit", worker.pid)
342 worker.log.info("pid=[%-10s] worker exit", worker.pid)
233 343
234 344
235 345 def child_exit(server, worker):
236 worker.log.info("[%-10s] worker child exit", worker.pid)
346 worker.log.info("pid=[%-10s] worker child exit", worker.pid)
237 347
238 348
239 349 def pre_request(worker, req):
@@ -306,7 +416,9 b' def get_ip_addr(environ):'
306 416 proxy_key = 'HTTP_X_REAL_IP'
307 417 proxy_key2 = 'HTTP_X_FORWARDED_FOR'
308 418 def_key = 'REMOTE_ADDR'
309 _filters = lambda x: _filter_port(_filter_proxy(x))
419
420 def _filters(x):
421 return _filter_port(_filter_proxy(x))
310 422
311 423 ip = environ.get(proxy_key)
312 424 if ip:
@@ -390,4 +502,5 b' class RhodeCodeLogger(Logger):'
390 502
391 503 return atoms
392 504
505
393 506 logger_class = RhodeCodeLogger
@@ -27,94 +27,21 b' debug = false'
27 27 #smtp_use_ssl = true
28 28
29 29 [server:main]
30 ; COMMON HOST/IP CONFIG
30 ; COMMON HOST/IP CONFIG, This applies mostly to develop setup,
31 ; Host port for gunicorn are controlled by gunicorn_conf.py
31 32 host = 127.0.0.1
32 port = 5000
33 port = 10020
33 34
34 35
35 36 ; ###########################
36 37 ; GUNICORN APPLICATION SERVER
37 38 ; ###########################
38 39
39 ; run with gunicorn --paste rhodecode.ini
40 ; run with gunicorn --paste rhodecode.ini --config gunicorn_conf.py
40 41
41 42 ; Module to use, this setting shouldn't be changed
42 43 use = egg:gunicorn#main
43 44
44 ; Sets the number of process workers. More workers means more concurrent connections
45 ; RhodeCode can handle at the same time. Each additional worker also it increases
46 ; memory usage as each has it's own set of caches.
47 ; Recommended value is (2 * NUMBER_OF_CPUS + 1), eg 2CPU = 5 workers, but no more
48 ; than 8-10 unless for really big deployments .e.g 700-1000 users.
49 ; `instance_id = *` must be set in the [app:main] section below (which is the default)
50 ; when using more than 1 worker.
51 workers = 2
52
53 ; Gunicorn access log level
54 loglevel = info
55
56 ; Process name visible in process list
57 proc_name = rhodecode
58
59 ; Type of worker class, one of `sync`, `gevent`
60 ; Recommended type is `gevent`
61 worker_class = gevent
62
63 ; The maximum number of simultaneous clients per worker. Valid only for gevent
64 worker_connections = 10
65
66 ; The maximum number of pending connections worker will queue to handle
67 backlog = 64
68
69 ; Max number of requests that worker will handle before being gracefully restarted.
70 ; Prevents memory leaks, jitter adds variability so not all workers are restarted at once.
71 max_requests = 1000
72 max_requests_jitter = 30
73
74 ; Amount of time a worker can spend with handling a request before it
75 ; gets killed and restarted. By default set to 21600 (6hrs)
76 ; Examples: 1800 (30min), 3600 (1hr), 7200 (2hr), 43200 (12h)
77 timeout = 21600
78
79 ; The maximum size of HTTP request line in bytes.
80 ; 0 for unlimited
81 limit_request_line = 0
82
83 ; Limit the number of HTTP headers fields in a request.
84 ; By default this value is 100 and can't be larger than 32768.
85 limit_request_fields = 32768
86
87 ; Limit the allowed size of an HTTP request header field.
88 ; Value is a positive number or 0.
89 ; Setting it to 0 will allow unlimited header field sizes.
90 limit_request_field_size = 0
91
92 ; Timeout for graceful workers restart.
93 ; After receiving a restart signal, workers have this much time to finish
94 ; serving requests. Workers still alive after the timeout (starting from the
95 ; receipt of the restart signal) are force killed.
96 ; Examples: 1800 (30min), 3600 (1hr), 7200 (2hr), 43200 (12h)
97 graceful_timeout = 3600
98
99 # The number of seconds to wait for requests on a Keep-Alive connection.
100 # Generally set in the 1-5 seconds range.
101 keepalive = 2
102
103 ; Maximum memory usage that each worker can use before it will receive a
104 ; graceful restart signal 0 = memory monitoring is disabled
105 ; Examples: 268435456 (256MB), 536870912 (512MB)
106 ; 1073741824 (1GB), 2147483648 (2GB), 4294967296 (4GB)
107 memory_max_usage = 0
108
109 ; How often in seconds to check for memory usage for each gunicorn worker
110 memory_usage_check_interval = 60
111
112 ; Threshold value for which we don't recycle worker if GarbageCollection
113 ; frees up enough resources. Before each restart we try to run GC on worker
114 ; in case we get enough free memory after that, restart will not happen.
115 memory_usage_recovery_threshold = 0.8
116
117
118 45 ; Prefix middleware for RhodeCode.
119 46 ; recommended when using proxy setup.
120 47 ; allows to set RhodeCode under a prefix in server.
General Comments 0
You need to be logged in to leave comments. Login now