001/** 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.camel.model; 018 019import java.util.concurrent.BlockingQueue; 020import java.util.concurrent.Future; 021import java.util.concurrent.ThreadPoolExecutor; 022import java.util.concurrent.TimeUnit; 023import javax.xml.bind.annotation.XmlAccessType; 024import javax.xml.bind.annotation.XmlAccessorType; 025import javax.xml.bind.annotation.XmlAttribute; 026 027import org.apache.camel.spi.Metadata; 028 029@XmlAccessorType(XmlAccessType.FIELD) 030public class HystrixConfigurationCommon extends IdentifiedType { 031 032 @XmlAttribute @Metadata(defaultValue = "CamelHystrix") 033 private String groupKey; 034 @XmlAttribute @Metadata(defaultValue = "CamelHystrix") 035 private String threadPoolKey; 036 @XmlAttribute 037 @Metadata(label = "command", defaultValue = "true") 038 private Boolean circuitBreakerEnabled; 039 @XmlAttribute 040 @Metadata(label = "command", defaultValue = "50") 041 private Integer circuitBreakerErrorThresholdPercentage; 042 @XmlAttribute 043 @Metadata(label = "command", defaultValue = "false") 044 private Boolean circuitBreakerForceClosed; 045 @XmlAttribute 046 @Metadata(label = "command", defaultValue = "false") 047 private Boolean circuitBreakerForceOpen; 048 @XmlAttribute 049 @Metadata(label = "command", defaultValue = "20") 050 private Integer circuitBreakerRequestVolumeThreshold; 051 @XmlAttribute 052 @Metadata(label = "command", defaultValue = "5000") 053 private Integer circuitBreakerSleepWindowInMilliseconds; 054 @XmlAttribute 055 @Metadata(label = "command", defaultValue = "20") 056 private Integer executionIsolationSemaphoreMaxConcurrentRequests; 057 @XmlAttribute 058 @Metadata(label = "command", defaultValue = "THREAD", enums = "THREAD,SEMAPHORE") 059 private String executionIsolationStrategy; 060 @XmlAttribute 061 @Metadata(label = "command", defaultValue = "true") 062 private Boolean executionIsolationThreadInterruptOnTimeout; 063 @XmlAttribute 064 @Metadata(label = "command", defaultValue = "1000") 065 private Integer executionTimeoutInMilliseconds; 066 @XmlAttribute 067 @Metadata(label = "command", defaultValue = "true") 068 private Boolean executionTimeoutEnabled; 069 @XmlAttribute 070 @Metadata(label = "command", defaultValue = "10") 071 private Integer fallbackIsolationSemaphoreMaxConcurrentRequests; 072 @XmlAttribute 073 @Metadata(label = "command", defaultValue = "true") 074 private Boolean fallbackEnabled; 075 @XmlAttribute 076 @Metadata(label = "command", defaultValue = "500") 077 private Integer metricsHealthSnapshotIntervalInMilliseconds; 078 @XmlAttribute 079 @Metadata(label = "command", defaultValue = "10") 080 private Integer metricsRollingPercentileBucketSize; 081 @XmlAttribute 082 @Metadata(label = "command", defaultValue = "true") 083 private Boolean metricsRollingPercentileEnabled; 084 @XmlAttribute 085 @Metadata(label = "command", defaultValue = "10000") 086 private Integer metricsRollingPercentileWindowInMilliseconds; 087 @XmlAttribute 088 @Metadata(label = "command", defaultValue = "6") 089 private Integer metricsRollingPercentileWindowBuckets; 090 @XmlAttribute 091 @Metadata(label = "command", defaultValue = "10000") 092 private Integer metricsRollingStatisticalWindowInMilliseconds; 093 @XmlAttribute 094 @Metadata(label = "command", defaultValue = "10") 095 private Integer metricsRollingStatisticalWindowBuckets; 096 @XmlAttribute 097 @Metadata(label = "command", defaultValue = "true") 098 private Boolean requestLogEnabled; 099 100 // thread-pool 101 102 @XmlAttribute 103 @Metadata(label = "threadpool", defaultValue = "10") 104 private Integer corePoolSize; 105 @XmlAttribute 106 @Metadata(label = "threadpool", defaultValue = "10") 107 private Integer maximumSize; 108 @XmlAttribute 109 @Metadata(label = "threadpool", defaultValue = "1") 110 private Integer keepAliveTime; 111 @XmlAttribute 112 @Metadata(label = "threadpool", defaultValue = "-1") 113 private Integer maxQueueSize; 114 @XmlAttribute 115 @Metadata(label = "threadpool", defaultValue = "5") 116 private Integer queueSizeRejectionThreshold; 117 @XmlAttribute 118 @Metadata(label = "threadpool", defaultValue = "10000") 119 private Integer threadPoolRollingNumberStatisticalWindowInMilliseconds; 120 @XmlAttribute 121 @Metadata(label = "threadpool", defaultValue = "10") 122 private Integer threadPoolRollingNumberStatisticalWindowBuckets; 123 @XmlAttribute 124 @Metadata(label = "threadpool", defaultValue = "false") 125 private Boolean allowMaximumSizeToDivergeFromCoreSize; 126 127 128 // Getter/Setter 129 // ------------------------------------------------------------------------- 130 131 public String getGroupKey() { 132 return groupKey; 133 } 134 135 /** 136 * Sets the group key to use. The default value is CamelHystrix. 137 */ 138 public void setGroupKey(String groupKey) { 139 this.groupKey = groupKey; 140 } 141 142 public String getThreadPoolKey() { 143 return threadPoolKey; 144 } 145 146 /** 147 * Sets the thread pool key to use. Will by default use the same value as groupKey has been configured to use. 148 */ 149 public void setThreadPoolKey(String threadPoolKey) { 150 this.threadPoolKey = threadPoolKey; 151 } 152 153 public Boolean getCircuitBreakerEnabled() { 154 return circuitBreakerEnabled; 155 } 156 157 /** 158 * Whether to use a HystrixCircuitBreaker or not. If false no circuit-breaker logic will be used and all requests permitted. 159 * <p> 160 * This is similar in effect to circuitBreakerForceClosed() except that continues tracking metrics and knowing whether it 161 * should be open/closed, this property results in not even instantiating a circuit-breaker. 162 */ 163 public void setCircuitBreakerEnabled(Boolean circuitBreakerEnabled) { 164 this.circuitBreakerEnabled = circuitBreakerEnabled; 165 } 166 167 public Integer getCircuitBreakerErrorThresholdPercentage() { 168 return circuitBreakerErrorThresholdPercentage; 169 } 170 171 /** 172 * Error percentage threshold (as whole number such as 50) at which point the circuit breaker will trip open and reject requests. 173 * <p> 174 * It will stay tripped for the duration defined in circuitBreakerSleepWindowInMilliseconds; 175 * <p> 176 * The error percentage this is compared against comes from HystrixCommandMetrics.getHealthCounts(). 177 */ 178 public void setCircuitBreakerErrorThresholdPercentage(Integer circuitBreakerErrorThresholdPercentage) { 179 this.circuitBreakerErrorThresholdPercentage = circuitBreakerErrorThresholdPercentage; 180 } 181 182 public Boolean getCircuitBreakerForceClosed() { 183 return circuitBreakerForceClosed; 184 } 185 186 /** 187 * If true the HystrixCircuitBreaker#allowRequest() will always return true to allow requests regardless of 188 * the error percentage from HystrixCommandMetrics.getHealthCounts(). 189 * <p> 190 * The circuitBreakerForceOpen() property takes precedence so if it set to true this property does nothing. 191 */ 192 public void setCircuitBreakerForceClosed(Boolean circuitBreakerForceClosed) { 193 this.circuitBreakerForceClosed = circuitBreakerForceClosed; 194 } 195 196 public Boolean getCircuitBreakerForceOpen() { 197 return circuitBreakerForceOpen; 198 } 199 200 /** 201 * If true the HystrixCircuitBreaker.allowRequest() will always return false, causing the circuit to be open (tripped) and reject all requests. 202 * <p> 203 * This property takes precedence over circuitBreakerForceClosed(); 204 */ 205 public void setCircuitBreakerForceOpen(Boolean circuitBreakerForceOpen) { 206 this.circuitBreakerForceOpen = circuitBreakerForceOpen; 207 } 208 209 public Integer getCircuitBreakerRequestVolumeThreshold() { 210 return circuitBreakerRequestVolumeThreshold; 211 } 212 213 /** 214 * Minimum number of requests in the metricsRollingStatisticalWindowInMilliseconds() that must exist before the HystrixCircuitBreaker will trip. 215 * <p> 216 * If below this number the circuit will not trip regardless of error percentage. 217 */ 218 public void setCircuitBreakerRequestVolumeThreshold(Integer circuitBreakerRequestVolumeThreshold) { 219 this.circuitBreakerRequestVolumeThreshold = circuitBreakerRequestVolumeThreshold; 220 } 221 222 public Integer getCircuitBreakerSleepWindowInMilliseconds() { 223 return circuitBreakerSleepWindowInMilliseconds; 224 } 225 226 /** 227 * The time in milliseconds after a HystrixCircuitBreaker trips open that it should wait before trying requests again. 228 */ 229 public void setCircuitBreakerSleepWindowInMilliseconds(Integer circuitBreakerSleepWindowInMilliseconds) { 230 this.circuitBreakerSleepWindowInMilliseconds = circuitBreakerSleepWindowInMilliseconds; 231 } 232 233 public Integer getExecutionIsolationSemaphoreMaxConcurrentRequests() { 234 return executionIsolationSemaphoreMaxConcurrentRequests; 235 } 236 237 /** 238 * Number of concurrent requests permitted to HystrixCommand.run(). Requests beyond the concurrent limit will be rejected. 239 * <p> 240 * Applicable only when executionIsolationStrategy == SEMAPHORE. 241 */ 242 public void setExecutionIsolationSemaphoreMaxConcurrentRequests(Integer executionIsolationSemaphoreMaxConcurrentRequests) { 243 this.executionIsolationSemaphoreMaxConcurrentRequests = executionIsolationSemaphoreMaxConcurrentRequests; 244 } 245 246 public String getExecutionIsolationStrategy() { 247 return executionIsolationStrategy; 248 } 249 250 /** 251 * What isolation strategy HystrixCommand.run() will be executed with. 252 * <p> 253 * If THREAD then it will be executed on a separate thread and concurrent requests limited by the number of threads in the thread-pool. 254 * <p> 255 * If SEMAPHORE then it will be executed on the calling thread and concurrent requests limited by the semaphore count. 256 */ 257 public void setExecutionIsolationStrategy(String executionIsolationStrategy) { 258 this.executionIsolationStrategy = executionIsolationStrategy; 259 } 260 261 public Boolean getExecutionIsolationThreadInterruptOnTimeout() { 262 return executionIsolationThreadInterruptOnTimeout; 263 } 264 265 /** 266 * Whether the execution thread should attempt an interrupt (using {@link Future#cancel}) when a thread times out. 267 * <p> 268 * Applicable only when executionIsolationStrategy() == THREAD. 269 */ 270 public void setExecutionIsolationThreadInterruptOnTimeout(Boolean executionIsolationThreadInterruptOnTimeout) { 271 this.executionIsolationThreadInterruptOnTimeout = executionIsolationThreadInterruptOnTimeout; 272 } 273 274 public Integer getExecutionTimeoutInMilliseconds() { 275 return executionTimeoutInMilliseconds; 276 } 277 278 /** 279 * Time in milliseconds at which point the command will timeout and halt execution. 280 * <p> 281 * If {@link #executionIsolationThreadInterruptOnTimeout} == true and the command is thread-isolated, the executing thread will be interrupted. 282 * If the command is semaphore-isolated and a HystrixObservableCommand, that command will get unsubscribed. 283 */ 284 public void setExecutionTimeoutInMilliseconds(Integer executionTimeoutInMilliseconds) { 285 this.executionTimeoutInMilliseconds = executionTimeoutInMilliseconds; 286 } 287 288 public Boolean getExecutionTimeoutEnabled() { 289 return executionTimeoutEnabled; 290 } 291 /** 292 * Whether the timeout mechanism is enabled for this command 293 */ 294 public void setExecutionTimeoutEnabled(Boolean executionTimeoutEnabled) { 295 this.executionTimeoutEnabled = executionTimeoutEnabled; 296 } 297 298 public Integer getFallbackIsolationSemaphoreMaxConcurrentRequests() { 299 return fallbackIsolationSemaphoreMaxConcurrentRequests; 300 } 301 302 /** 303 * Number of concurrent requests permitted to HystrixCommand.getFallback(). 304 * Requests beyond the concurrent limit will fail-fast and not attempt retrieving a fallback. 305 */ 306 public void setFallbackIsolationSemaphoreMaxConcurrentRequests(Integer fallbackIsolationSemaphoreMaxConcurrentRequests) { 307 this.fallbackIsolationSemaphoreMaxConcurrentRequests = fallbackIsolationSemaphoreMaxConcurrentRequests; 308 } 309 310 public Boolean getFallbackEnabled() { 311 return fallbackEnabled; 312 } 313 314 /** 315 * Whether HystrixCommand.getFallback() should be attempted when failure occurs. 316 */ 317 public void setFallbackEnabled(Boolean fallbackEnabled) { 318 this.fallbackEnabled = fallbackEnabled; 319 } 320 321 public Integer getMetricsHealthSnapshotIntervalInMilliseconds() { 322 return metricsHealthSnapshotIntervalInMilliseconds; 323 } 324 325 /** 326 * Time in milliseconds to wait between allowing health snapshots to be taken that calculate success and error 327 * percentages and affect HystrixCircuitBreaker.isOpen() status. 328 * <p> 329 * On high-volume circuits the continual calculation of error percentage can become CPU intensive thus this controls how often it is calculated. 330 */ 331 public void setMetricsHealthSnapshotIntervalInMilliseconds(Integer metricsHealthSnapshotIntervalInMilliseconds) { 332 this.metricsHealthSnapshotIntervalInMilliseconds = metricsHealthSnapshotIntervalInMilliseconds; 333 } 334 335 public Integer getMetricsRollingPercentileBucketSize() { 336 return metricsRollingPercentileBucketSize; 337 } 338 339 /** 340 * Maximum number of values stored in each bucket of the rolling percentile. 341 * This is passed into HystrixRollingPercentile inside HystrixCommandMetrics. 342 */ 343 public void setMetricsRollingPercentileBucketSize(Integer metricsRollingPercentileBucketSize) { 344 this.metricsRollingPercentileBucketSize = metricsRollingPercentileBucketSize; 345 } 346 347 public Boolean getMetricsRollingPercentileEnabled() { 348 return metricsRollingPercentileEnabled; 349 } 350 351 /** 352 * Whether percentile metrics should be captured using HystrixRollingPercentile inside HystrixCommandMetrics. 353 */ 354 public void setMetricsRollingPercentileEnabled(Boolean metricsRollingPercentileEnabled) { 355 this.metricsRollingPercentileEnabled = metricsRollingPercentileEnabled; 356 } 357 358 public Integer getMetricsRollingPercentileWindowInMilliseconds() { 359 return metricsRollingPercentileWindowInMilliseconds; 360 } 361 362 /** 363 * Duration of percentile rolling window in milliseconds. 364 * This is passed into HystrixRollingPercentile inside HystrixCommandMetrics. 365 */ 366 public void setMetricsRollingPercentileWindowInMilliseconds(Integer metricsRollingPercentileWindowInMilliseconds) { 367 this.metricsRollingPercentileWindowInMilliseconds = metricsRollingPercentileWindowInMilliseconds; 368 } 369 370 public Integer getMetricsRollingPercentileWindowBuckets() { 371 return metricsRollingPercentileWindowBuckets; 372 } 373 374 /** 375 * Number of buckets the rolling percentile window is broken into. 376 * This is passed into HystrixRollingPercentile inside HystrixCommandMetrics. 377 */ 378 public void setMetricsRollingPercentileWindowBuckets(Integer metricsRollingPercentileWindowBuckets) { 379 this.metricsRollingPercentileWindowBuckets = metricsRollingPercentileWindowBuckets; 380 } 381 382 public Integer getMetricsRollingStatisticalWindowInMilliseconds() { 383 return metricsRollingStatisticalWindowInMilliseconds; 384 } 385 386 /** 387 * This property sets the duration of the statistical rolling window, in milliseconds. This is how long metrics are kept for the thread pool. 388 * 389 * The window is divided into buckets and “rolls” by those increments. 390 */ 391 public void setMetricsRollingStatisticalWindowInMilliseconds(Integer metricsRollingStatisticalWindowInMilliseconds) { 392 this.metricsRollingStatisticalWindowInMilliseconds = metricsRollingStatisticalWindowInMilliseconds; 393 } 394 395 public Integer getMetricsRollingStatisticalWindowBuckets() { 396 return metricsRollingStatisticalWindowBuckets; 397 } 398 399 /** 400 * Number of buckets the rolling statistical window is broken into. 401 * This is passed into HystrixRollingNumber inside HystrixCommandMetrics. 402 */ 403 public void setMetricsRollingStatisticalWindowBuckets(Integer metricsRollingStatisticalWindowBuckets) { 404 this.metricsRollingStatisticalWindowBuckets = metricsRollingStatisticalWindowBuckets; 405 } 406 407 public Boolean getRequestLogEnabled() { 408 return requestLogEnabled; 409 } 410 411 /** 412 * Whether HystrixCommand execution and events should be logged to HystrixRequestLog. 413 */ 414 public void setRequestLogEnabled(Boolean requestLogEnabled) { 415 this.requestLogEnabled = requestLogEnabled; 416 } 417 418 public Integer getCorePoolSize() { 419 return corePoolSize; 420 } 421 422 /** 423 * Core thread-pool size that gets passed to {@link java.util.concurrent.ThreadPoolExecutor#setCorePoolSize(int)} 424 */ 425 public void setCorePoolSize(Integer corePoolSize) { 426 this.corePoolSize = corePoolSize; 427 } 428 429 public Integer getMaximumSize() { 430 return maximumSize; 431 } 432 433 /** 434 * Maximum thread-pool size that gets passed to {@link ThreadPoolExecutor#setMaximumPoolSize(int)}. 435 * This is the maximum amount of concurrency that can be supported without starting to reject HystrixCommands. 436 * Please note that this setting only takes effect if you also set allowMaximumSizeToDivergeFromCoreSize 437 */ 438 public void setMaximumSize(Integer maximumSize) { 439 this.maximumSize = maximumSize; 440 } 441 442 public Integer getKeepAliveTime() { 443 return keepAliveTime; 444 } 445 446 /** 447 * Keep-alive time in minutes that gets passed to {@link ThreadPoolExecutor#setKeepAliveTime(long, TimeUnit)} 448 */ 449 public void setKeepAliveTime(Integer keepAliveTime) { 450 this.keepAliveTime = keepAliveTime; 451 } 452 453 public Integer getMaxQueueSize() { 454 return maxQueueSize; 455 } 456 457 /** 458 * Max queue size that gets passed to {@link BlockingQueue} in HystrixConcurrencyStrategy.getBlockingQueue(int) 459 * 460 * This should only affect the instantiation of a threadpool - it is not eliglible to change a queue size on the fly. 461 * For that, use queueSizeRejectionThreshold(). 462 */ 463 public void setMaxQueueSize(Integer maxQueueSize) { 464 this.maxQueueSize = maxQueueSize; 465 } 466 467 public Integer getQueueSizeRejectionThreshold() { 468 return queueSizeRejectionThreshold; 469 } 470 471 /** 472 * Queue size rejection threshold is an artificial "max" size at which rejections will occur even 473 * if {@link #maxQueueSize} has not been reached. This is done because the {@link #maxQueueSize} 474 * of a {@link BlockingQueue} can not be dynamically changed and we want to support dynamically 475 * changing the queue size that affects rejections. 476 * <p> 477 * This is used by HystrixCommand when queuing a thread for execution. 478 */ 479 public void setQueueSizeRejectionThreshold(Integer queueSizeRejectionThreshold) { 480 this.queueSizeRejectionThreshold = queueSizeRejectionThreshold; 481 } 482 483 public Integer getThreadPoolRollingNumberStatisticalWindowInMilliseconds() { 484 return threadPoolRollingNumberStatisticalWindowInMilliseconds; 485 } 486 487 /** 488 * Duration of statistical rolling window in milliseconds. 489 * This is passed into HystrixRollingNumber inside each HystrixThreadPoolMetrics instance. 490 */ 491 public void setThreadPoolRollingNumberStatisticalWindowInMilliseconds(Integer threadPoolRollingNumberStatisticalWindowInMilliseconds) { 492 this.threadPoolRollingNumberStatisticalWindowInMilliseconds = threadPoolRollingNumberStatisticalWindowInMilliseconds; 493 } 494 495 public Integer getThreadPoolRollingNumberStatisticalWindowBuckets() { 496 return threadPoolRollingNumberStatisticalWindowBuckets; 497 } 498 499 /** 500 * Number of buckets the rolling statistical window is broken into. 501 * This is passed into HystrixRollingNumber inside each HystrixThreadPoolMetrics instance. 502 */ 503 public void setThreadPoolRollingNumberStatisticalWindowBuckets(Integer threadPoolRollingNumberStatisticalWindowBuckets) { 504 this.threadPoolRollingNumberStatisticalWindowBuckets = threadPoolRollingNumberStatisticalWindowBuckets; 505 } 506 507 public Boolean getAllowMaximumSizeToDivergeFromCoreSize() { 508 return allowMaximumSizeToDivergeFromCoreSize; 509 } 510 511 /** 512 * Allows the configuration for maximumSize to take effect. That value can then be equal to, or higher, than coreSize 513 */ 514 public void setAllowMaximumSizeToDivergeFromCoreSize(Boolean allowMaximumSizeToDivergeFromCoreSize) { 515 this.allowMaximumSizeToDivergeFromCoreSize = allowMaximumSizeToDivergeFromCoreSize; 516 } 517}