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