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