Tuesday, July 7, 2015

Circuit Breaker Pattern using Spring cloud and Hystrix



http://www.java-allandsundry.com/2016/11/parallelizing-hystrix-calls.html
a service which would aggregate responses from multiple such remote calls together would look like this:

?
1
2
3
4
5
6
7
8
9
SampleRemoteCallCommand1 command1 = new SampleRemoteCallCommand1();
SampleRemoteCallCommand2 command2 = new SampleRemoteCallCommand2();
Observable<String> result1Obs = command1.toObservable();
Observable<Integer> result2Obs = command2.toObservable();
Observable<String> result =
        Observable.zip(result1Obs, result2Obs, (result1, result2) -> result1 + result2);
        

Essentially instead of synchronously executing the Hystrix command, we just use the "toObservable()" method to return a Rx-Java Observable representation of the result and use the different ways that Observable provides to aggregate the results together, in this specific instance the zip operator.

https://github.com/andywilsonuk/AsyncResiliencyPatterns
The Throttle pattern ensures that an external dependency is not flooded with more concurrent requests than it is expected to cope with.
The Circuit Breaker pattern ensures that if an external dependency starts to fail, it isn't continued to be hammered by more new requests. The circuit is configured with a level of failure tolerance within a specified time frame and if breached the circuit is 'tripped' and no further requests are send. After an amount of time, an attempt is made and if successful then 'normal' behaviour is resumed and all future requests are sent to the external dependency.
https://github.com/Netflix/Hystrix/wiki/Configuration#coreSize
HystrixThreadPoolProperties.Setter() .withCoreSize(int value)
HystrixThreadPoolProperties.Setter() .withMaxQueueSize(int value)
HystrixThreadPoolProperties.Setter()
   .withQueueSizeRejectionThreshold(int value)
http://blog.zuehlke.com/en/distributed-systems-how-to-design-resilient-applications-with-hystrix/
super(Setter.withGroupKey(HystrixCommandGroupKey.Factory
2      .asKey("MarketDataFeedsGroup"))
3      .andThreadPoolPropertiesDefaults(
4        HystrixThreadPoolProperties.Setter()
5        .withCoreSize(40)));

1super(Setter.withGroupKey(HystrixCommandGroupKey.Factory
2      .asKey("MarketDataFeedsGroup"))
3      .andCommandPropertiesDefaults(
4        HystrixCommandProperties.Setter()
5        .withExecutionTimeoutInMilliseconds(200)));

https://github.com/Netflix/Hystrix/wiki/How-To-Use#fallback-cache-via-network

This is a pretty common pattern at Netflix as well. A variant on it is shown here: https://github.com/Netflix/Hystrix/wiki/How-To-Use#fallback-cache-via-network except that you'll hit the cache first and then origin. I have no idea why I haven't documented the cache-then-origin pattern as we use it often. 

We keep each source (cache and origin) in a separate command and separate thread-pool so that one cannot saturate the others resources and so metrics are available for both. We chain them using getFallback so regardless of how the first starts failing we fallback to the secondary. In other words, they are the same group but different command keys and thread pools. 

The difference in yours is it sounds like a cache miss is expected rather than a failure (we consider it a failure as we eagerly populate the caches) - in that case you don't want to throw an exception but just conditionally invoke the second command from the first when it occurs - and also in getFallback when an error occurs fetching from cache (though under load if the cache is completely failed both commands will end up short-circuited since the origin likely won't be able to handle traffic if the caches are dead, so consider another local fallback strategy for that command if one is possible). 

In short, your approach with two commands is correct, but separate the threadpools otherwise one going bad can cause the other to go bad (reject once saturated) as well - unless that's what you want of course. 

https://github.com/Netflix/Hystrix/wiki/How-To-Use#Caching
You enable request caching by implementing the getCacheKey() method on a HystrixCommand orHystrixObservableCommand object.
    protected String getCacheKey() {
        return String.valueOf(value);
    }

HystrixRequestContext context = HystrixRequestContext.initializeContext();

http://stackoverflow.com/questions/35569560/difference-between-hystrixcommand-and-hystrixobservablecommand
This command is essentially a blocking command but provides an Observable facade if used with observe()
This command should be used for a purely non-blocking call pattern. The caller of this command will be subscribed to the Observable returned by the run() method.
The difference is that HystrixCommand by default supports a blocking paradigm, but also provides non-blocking behavior by way of Observables via a facade, whereas HystrixObservableCommand was implemented specifically for a non-blocking setup. I'm not entirely sure why it's split into two implementations, but I would guess that the reason is because originally HystrixCommand did not support non-blocking. It was added about a year or so after the original implementation. Could have just been cleaner to write a purely non-blocking hystrix class.
If you are working with only non-blocking calls, you should likely be using HystrixObservableCommand. Ben Christensen, one of the Hystrix devs, sums it up nicely in this post:
However, if you are wrapping blocking calls, you should just stick with using HystrixCommand as that’s what it’s built for and it defaults to running everything in a separate thread. Using HystrixCommand.observe() will give you the concurrent, async composition you’re looking for.
HystrixObservableCommand is intended for wrapping around async, non-blocking Observables that don’t need extra threads.

http://hot66hot.iteye.com/blog/2155036
HystrixBadRequestException

An exception representing an error with provided arguments or state rather than an execution failure.
Unlike all other exceptions thrown by a HystrixCommand this will not trigger fallback, not count against failure metrics and thus not trigger the circuit breaker.

NOTE: This should only be used when an error is due to user input such as IllegalArgumentException otherwise it defeats the purpose of fault-tolerance and fallback behavior.

除了HystrixBadRequestException异常之外,所有从run()方法抛出的异常都算作失败,并触发降级getFallback()和断路器逻辑。
          HystrixBadRequestException用在非法参数或非系统故障异常等不应触发回退逻辑的场景。
https://github.com/Netflix/Hystrix/wiki/How-To-Use
All exceptions thrown from the run() method except for HystrixBadRequestException count as failures and trigger getFallback() and circuit-breaker logic.
You can wrap the exception that you would like to throw in HystrixBadRequestException and retrieve it via getCause(). The HystrixBadRequestException is intended for use cases such as reporting illegal arguments or non-system failures that should not count against the failure metrics and should not trigger fallback logic.
http://www.lordofthejars.com/2014/09/defend-your-application-with-hystrix.html
But also Hystrix provides other features:
Each thread has a timeout so a call may not be infinity waiting for a response.
Perform fallbacks wherever feasible to protect users from failure.
Measure success, failures (exceptions thrown by client), timeouts, and thread rejections and allows monitorizations.
Implements a circuit-breaker pattern which automatically or manually to stop all requests to an external service for a period of time if error percentage passes a threshold.

Circuit breaker:

Circuit breaker is a software pattern to detect failures and avoid receiving the same error constantly.
But also if the service is remote you can throw an error without waiting for TCP connection timeout.

So it would be much useful if system could detect that a service is failing and avoid clients do more requests until some period of time. And this is what circuit breaker does. For each execution check if the circuit is open (tripped) which means that an error has occurred and the request will be not sent to service and fallback logic will be executed. But if the circuit is closed then the request is processed and may work.

Hystrix maintains an statistical database of number of success request vs failed requests. When Hystrix detects that in a defined spare of time, a threshold of failed commands has reached, it will open the circuit so future request will be able to return the error as soon as possible without having to consume resources to a service which probably is offline. But the good news is that Hystrix is also the responsible of closing the circuit. After elapsed time Hystrix will try to run again an incoming request, if this request is successful, then it will close the circuit and if not it will maintain the circuit opened.
http://blog.mirkosertic.de/architecturedesign/springhystrix

http://www.java-allandsundry.com/2015/01/using-netflix-hystrix-library-with.html
public DummyRemoteCallService() {
15.try {
16.mockedDelegate = mock(RemoteCallService.class);
17.when(mockedDelegate.call(anyString()))
18..thenThrow(new RuntimeException("Deliberately throwing an exception 1"))
19..thenThrow(new RuntimeException("Deliberately throwing an exception 2"))
20..thenAnswer(new Answer<String>() {
21.@Override
22.public String answer(InvocationOnMock invocationOnMock) throws Throwable {
23.return (String) invocationOnMock.getArguments()[0];
24.}
25.});
26.}catch(Exception e) {
27.throw new IllegalStateException(e);
28.}
29.}
30. 
31.@Override
32.@HystrixCommand(fallbackMethod = "fallBackCall")
33.public String call(String request) throws Exception {
34.return this.mockedDelegate.call(request);
35.}
36. 
37.public String fallBackCall(String request) {
38.return "FALLBACK: " + request;
39.}

40.
@EnableAspectJAutoProxy
33.public static class SpringConfig {
34. 
35.@Bean
36.public HystrixCommandAspect hystrixCommandAspect() {
37.return new HystrixCommandAspect();
38.}


Hystrix use RabbitMQ for internal communication
http://callistaenterprise.se/blogg/teknik/2015/04/10/building-microservices-with-spring-cloud-and-netflix-oss-part-1/
@HystrixCommand(fallbackMethod = "defaultReviews")
 public ResponseEntity<List<Review>> getReviews(int productId) public ResponseEntity<List<Review>> defaultReviews(int productId) {
http://stackoverflow.com/questions/28326711/issue-with-hystrix-fallback-in-spring-cloud
I found 2 problems in your FallbackableService.
1) the fallbackMethod referred to a non-existent method;
2) the @HystrixCommand method (and the fallback) was not public.
http://www.widecodes.com/CNVVXeXqeV/hystrix-javanica-fallback-not-working-in-spring-cloud-10.html@HystrixCommand only works because Spring makes a proxy to call that method on. If you call the method from within the proxy it doesn't go through the interceptor. You need to call the @HystrixCommand from another @Component (or use AspectJ).

@EnableDiscoveryClient
@EnableHystrix
How do u know whether it works?
Check the stack trace, whether it calls the method directly or through reflection.

The method has to be in another calss, same class static inner class does not work.

http://www.slideshare.net/ufried/resilience-with-hystrix
public class HelloCommand extends HystrixCommand<String> {
 private static final String COMMAND_GROUP = "default";
 private final String name;
 public HelloCommand(String name) {
 super(HystrixCommandGroupKey.Factory.asKey(COMMAND_GROUP));
 this.name = name;
 }
 @Override
 protected String run() throws Exception {
 return "Hello, " + name;
 }
}
Synchronous execution
 String result = new HelloCommand("World").execute();
Asynchronous execution

Future<String> f = new HelloCommand("Alice").queue();
String s = null;
try {
s = f.get();
} catch (InterruptedException | ExecutionException e) {
// Handle Future.get() exceptions here
}

Reactive execution (simple)
Observable<String> observable = new HelloCommand("Alice").observe();
String s = observable.toBlockingObservable().single();

public class FallbackCommand extends HystrixCommand<String> {
 private static final String COMMAND_GROUP = "default";
 public FallbackCommand() {
 super(HystrixCommandGroupKey.Factory.asKey(COMMAND_GROUP));
 }
 @Override
 protected String run() throws Exception {
 throw new RuntimeException("I will always fail");
 }
 @Override
 protected String getFallback() {
 return "Powered by fallback";
 }
}

Based on Archaius by Netflix
which extends the Apache Commons Configuration Library
• Four levels of precedence
1. Global default from code
2. Dynamic global default property
3. Instance default from code
4. Dynamic instance property
• hystrix.command.*.execution.isolation.strategy
Either “THREAD” or “SEMAPHORE” (Default: THREAD)
• hystrix.command.*.execution.isolation.thread.timeoutInMilliseconds
Time to wait for the run() method to complete (Default: 1000)
• h.c.*.execution.isolation.semaphore.maxConcurrentRequests
Maximum number of concurrent requests when using semaphores (Default: 10)
• hystrix.command.*.circuitBreaker.errorThresholdPercentage
Error percentage at which the breaker trips open (Default: 50)
• hystrix.command.*.circuitBreaker.sleepWindowInMilliseconds
Time to wait before attempting to reset the breaker after tripping (Default: 5000)
• hystrix.threadpool.*.coreSize
Maximum number of concurrent requests when using thread pools (Default: 10)
• hystrix.threadpool.*.maxQueueSize
Maximum LinkedBlockingQueue size - -1 for using SynchronousQueue (Default: -1)
• hystrix.threadpool.default.queueSizeRejectionThreshold
Queue size rejection threshold (Default: 5)
public class TimeoutCommand extends HystrixCommand<String> {
 private static final String COMMAND_GROUP = "default";
 private final LatentResource resource;
 public TimeoutCommand(int timeout, LatentResource resource) {
 super(Setter.withGroupKey(
 HystrixCommandGroupKey.Factory.asKey(COMMAND_GROUP))
 .andCommandPropertiesDefaults(
 HystrixCommandProperties.Setter()
 .withExecutionIsolationThreadTimeoutInMilliseconds(
 timeout)));
 this.resource = resource;
 }
 @Override
 protected String run() throws Exception {
 return resource.getData();
 }
 @Override
 protected String getFallback() {
 return "Resource timed out";
 }
}

HystrixCommandProperties.Setter().withCircuitBreakerForceOpen(open)));

Load shedder (Thread pool)
List<Future<String>> l = new LinkedList<>();
LatentResource resource = new LatentResource(500L); // Make latent
// Use up all available threads
for (int i = 0; i < 10; i++)
l.add(new LatentCommand(resource).queue());
// Call will be rejected as thread pool is exhausted
String s = new LatentCommand(resource).execute();
assertEquals("Fallback triggered", s);
// All other calls succeed
for (Future<String> f : l)
assertEquals("Some value", get(f)); // wrapper for f.get()

http://ningandjiao.iteye.com/blog/2171191
同步执行:即一旦开始执行该命令,当前线程就得阻塞着直到该命令返回结果,然后才能继续执行下面的逻辑。当调用命令的execute()方法即为同步执行, 示例: 
  1.         ThreadEchoCommand command = new ThreadEchoCommand("xianlinbox");  
  2.         String result = command.execute();  
异步执行:命令开始执行会返回一个Future<T>的对象,不阻塞后面的逻辑,开发者自己根据需要去获取结果。当调用HystrixCommand的queue()方法即为异步执行 
  1. ThreadEchoCommand command = new ThreadEchoCommand("xianlinbox");  
  2.         Future<String> result = command.queue();  
  3.         while (!result.isDone()){  
  4.             System.out.println("Do other things ...");  
  5.         }  
  6.         assertThat(result.get(),equalTo("Echo: xianlinbox"));  

响应式执行:命令开始执行会返回一个Observable<T> 对象,开发者可以给给Obeservable对象注册上Observer或者Action1对象,响应式地处理命令执行过程中的不同阶段。当调用HystrixCommand的observe()方法,或使用Observable的工厂方法(just(),from())即为响应式执行,
  1.     public void reactiveExecute1() throws Exception {  
  2.         ThreadEchoCommand command1 = new ThreadEchoCommand("xianlinbox");  
  3.         Observable<String> result = command1.observe();  
  4.         result.subscribe(new Action1<String>() {  
  5.             @Override  
  6.             public void call(String s) {  
  7.                 logger.info("Command called. Result is:{}", s);  
  8.             }1  
  9.         });  
  10.         Thread.sleep(1000);  
  11.     }  
  12.   
  13.     @Test  
  14.     public void reactiveExecute2() throws Exception {  
  15.         ThreadEchoCommand command = new ThreadEchoCommand("xianlinbox");  
  16.         Observable<String> result = command.observe();  
  17.         result.subscribe(new Observer<String>() {  
  18.             @Override  
  19.             public void onCompleted() {  
  20.                 logger.info("Command Completed");  
  21.             }  
  22.   
  23.             @Override  
  24.             public void onError(Throwable e) {  
  25.                 logger.error("Command failled", e);  
  26.             }  
  27.   
  28.             @Override  
  29.             public void onNext(String args) {  
  30.                 logger.info("Command finished,result is {}", args);  
  31.             }  
  32.         });  
  33.         Thread.sleep(1000);  
  34.     }  

http://www.ebaytechblog.com/2015/09/08/application-resiliency-using-netflix-hystrix/
Resilience is the ability of the network to provide and maintain an acceptable level of service in the face of various faults and challenges to normal operation.

A circuit breaker is a simple structure that constantly remains vigilant, monitoring for faults. In the above-mentioned scenario, the circuit breaker identifies long waiting times among the calls to the vendor and fails-fast, returning an error response to the user instead of making the threads wait. Thus, the circuit breaker prevents the users from having a very sub-optimal response time.
The basic idea behind the circuit breaker is very simple. You wrap a protected function call in a circuit breaker object, which monitors for failures. Once the failures reach a certain threshold, the circuit breaker trips, and all further calls to the circuit breaker return with an error, without the protected call being made at all. Usually you’ll also want some kind of monitor alert if the circuit breaker trips.
-Martin Fowler
Recovery time is crucial for the underlying resource, and having a circuit breaker that fails-fast without overloading the system ensures that the vendor can recover quickly.
A circuit breaker is an always-live system keeping watch over dependency invocations. In case of a high failure rate, the circuit breaker stops the calls from going through for a small amount of time, rather than responding with a standard error.
The circuit breaker is the default one available through the Hystrix library. The functioning of the circuit breaker can be summarized as follows:
  1. Every incoming call is verified against the current state of the circuit breaker.
  2. A Closed state of the Circuit allows the requests to be sent through.
  3. An Open state fails all requests.
  4. A Half-Open state (which occurs when the sleep time is completed), allows one request to go through, and on success or failure moves the circuit to the Closed or Open state as appropriate.
Hystrix is not just a circuit breaker, but also a complete library with extensive monitoring capabilities, which can be easily plugged into existing systems. We have started exploring the usage of the library’s Request Collapsing and Request Caching abilities for future use cases. There are a few other Java-based implementations available, such as Akka and Spring circuit breakers;
http://blog.zuehlke.com/en/distributed-systems-how-to-design-resilient-applications-with-hystrix/

Adapting Hystrix to your needs

recommended to start with the default configuration and monitor the behaviour of the system in production. As it turns out, the default behaviour is viable for most applications. 

super(Setter.withGroupKey(HystrixCommandGroupKey.Factory
      .asKey("MarketDataFeedsGroup"))
      .andThreadPoolPropertiesDefaults(
        HystrixThreadPoolProperties.Setter()
        .withCoreSize(40)));

Or you could change the time-out settings of the circuit. The default time-out is set to 1000 ms. If you have an application with a high request rate, you might want to avoid having your threads blocked for such a large amount of time. If you want to wait for no longer than 200 ms, you could apply the following configuration:
super(Setter.withGroupKey(HystrixCommandGroupKey.Factory
.asKey("MarketDataFeedsGroup"))
.andCommandPropertiesDefaults(
HystrixCommandProperties.Setter()
.withExecutionTimeoutInMilliseconds(200)));

super(Setter.withGroupKey(HystrixCommandGroupKey.Factory
  .asKey("MarketDataFeedsGroup"))
.andCommandPropertiesDefaults(
HystrixCommandProperties.Setter()
.withMetricsRollingStatisticalWindowInMilliseconds(60000)));
http://slamke.blogspot.com/2016/01/hystrix.html
Hystrix is designed to do the following:
  • Give protection from and control over latency and failure from dependencies accessed (typically over the network) via third-party client libraries. 让程序具有处理调用外部服务失败的能力
  • Stop cascading failures in a complex distributed system.
  • Fail fast and rapidly recover.
  • Fallback and gracefully degrade when possible.
  • Enable near real-time monitoring, alerting, and operational control.

Hystrix works by:

  • Preventing any single dependency from using up all container (such as Tomcat) user threads.
  • Shedding load and failing fast instead of queueing.
  • Providing fallbacks wherever feasible to protect users from failure.
  • Using isolation techniques (such as bulkhead, swimlane, and circuit breaker patterns) to limit the impact of any one dependency.
  • Optimizing for time-to-discovery through near real-time metrics, monitoring, and alerting
  • Optimizing for time-to-recovery by means of low latency propagation of configuration changes and support for dynamic property changes in most aspects of Hystrix, which allows you to make real-time operational modifications with low latency feedback loops.
  • Protecting against failures in the entire dependency client execution, not just in the network traffic.
Hystrix使用命令模式HystrixCommand(Command)包装依赖调用逻辑,每个命令在单独线程中/信号授权下执行
从run()方法中抛出的所以异常(除了HystrixBadRequestException)都被计为异常。将触发getFallback()  和熔断逻辑。在HystrixBadRequestException中抛出的例外,你可以根据你的喜好进行包装,然后通过  getCause()获取。  HystrixBadRequestException设计的使用场景为,报告不合法的参数或非系统性错误。这些都不能计入失  败次数的度量,也不应当触发回退逻辑

group进行统一管理  command组键名被用于将command分组,如报表,警告,面板或者组包的所以者。  默认情况下,它被用于command的线程池的命名,除非有单独的定义
线程池的键被用于监控HystrixThreadPool时的呈现,度量的发布,缓存等其它应用。一个  HystrixCommand 是和一个单个的HystrixThreadPool相关联,通过注入它的HystrixThreadPoolKey可以取  得HystrixThreadPool 或者它默认情况下用HystrixCommandGroupKey创建一个。

请求缓存通过实现HystrixCommand或者HystrixObservableCommand中的getCacheKey()方法完成:依赖于request context 的某些东西,必须实例化HystrixRequestContext
请求合并是一个特性,它能自动将一批请求合并到单一的HystrixCommand实例中执行。  可以设定批次的大小和时间作为促发器来执行一个批次  两种style的请求合并
  • request-scoped
  • globally-scoped.  This is configured at collapser construction, and defaulted to request-scoped.
Request Context Setup 为了能使用request的scoped特性(请求缓存,请求折叠,请求日记)HystrixRequestContext 的生命周期 必须被管理起来。(或者一个替代的HystrixConcurrencyStrategy 实现) 这就意味着下面代码必须在一个请求之前执行 HystrixRequestContext context = HystrixRequestContext.initializeContext(); 然后在请求的最后调用 context.shutdown(); 常见模式 快速失败 Fail Fast 无声失败 Fail Silent 无声的失败等同于返回一个空的响应或者删除功能,它通过返回null,空的map对象,空的list或者其他类似 的响应实现。 通常通过HystrixCommand实例中的getFallback() 方法实现 回退:静态的 Fallback:Static 一些回退能返回在代码中硬编码的值。它不能引起特性或将被移除服务(如同无声失败经常处理的方 法),但是执行默认的行为逻辑。 Fallback: Stubbed 一个存根回退典型的被用于包含多个字段的一个组合对象被返回时。它们其中的一部分能被其它请求状态 来决定。当其它字段被设置为默认值。 Fallback: Cache via Network 由于回退如果重掉网络可能导致另外的失败,因此需要通过另外的HystrixCommand转换。 另外重要的是,回退command应当在独立的线程池中执行。如果两个command共享相同的线程池,会导 致主command将变的延迟并且占用整个的线程池,从而阻止回退。
https://github.com/Netflix/Hystrix/issues/796
As described in the Wiki (https://github.com/Netflix/Hystrix/wiki/How-it-Works#semaphores), Hystrix uses a semaphore on the number of concurrent fallbacks that may be in flight at any point in time. It must do this so that latency on the fallback path is able to be controlled, especially since fallbacks may run on the calling thread.
Your options for not encountering this situtation: 1) Trigger the fallback path less frequently (fail the command less often) 2) Make the fallback path less expensive/latent 3) Reconfigure the fallback semaphore :https://github.com/Netflix/Hystrix/wiki/Configuration#fallback.isolation.semaphore.maxConcurrentRequests (Note that this may affect the resiliency/stability of your system if you
increase this too much.
http://www.java-allandsundry.com/2015/10/gentle-introduction-to-hystrix-hello.html
Or, even better it can be made to return a Rx-Java observable:
HelloWorldCommand helloWorldCommand = new HelloWorldCommand("World");
CountDownLatch l = new CountDownLatch(1);
Observable<String> obs = helloWorldCommand.observe();
obs.subscribe(
        s -> logger.info("Received : " + s),
        t -> logger.error(t.getMessage(), t),
        () -> l.countDown()
);
l.await(5, TimeUnit.SECONDS);
The Observable variation of the command also works along the same lines, however we should contrast a small behavior difference:
?
1
2
3
HelloWorldObservableCommand helloWorldCommand = new HelloWorldObservableCommand("World");
logger.info("Completed executing HelloWorld Command");
Observable<String> obs = helloWorldCommand.observe();
There are two ways to obtain an Observable here, one is like the above by making an ".observe()" call, another is the following way:
?
1
2
HelloWorldObservableCommand helloWorldCommand = new HelloWorldObservableCommand("World");
Observable<String> obs = helloWorldCommand.toObservable();
another is the following using ".toObservable()" call :
?
1
2
HelloWorldObservableCommand helloWorldCommand = new HelloWorldObservableCommand("World");
Observable<String> obs = helloWorldCommand.toObservable();
The difference is that the ".observe()" method returns a Hot Observable which starts executing the "construct" method immediately, whereas the ".toObservable" variation returns a Cold Observable and would not call "construct" method unless it is subscribed to, say the following way:
?
1
2
3
CountDownLatch l = new CountDownLatch(1);
obs.subscribe(System.out::println, t -> l.countDown(), () -> l.countDown());
l.await();



http://stackoverflow.com/questions/35569560/difference-between-hystrixcommand-and-hystrixobservablecommand

This command is essentially a blocking command but provides an Observable facade if used with observe()
This command should be used for a purely non-blocking call pattern. The caller of this command will be subscribed to the Observable returned by the run() method.
The difference is that HystrixCommand by default supports a blocking paradigm, but also provides non-blocking behavior by way of Observables via a facade, whereas HystrixObservableCommand was implemented specifically for a non-blocking setup. I'm not entirely sure why it's split into two implementations, but I would guess that the reason is because originally HystrixCommand did not support non-blocking. It was added about a year or so after the original implementation. Could have just been cleaner to write a purely non-blocking hystrix class.
If you are working with only non-blocking calls, you should likely be using HystrixObservableCommand. Ben Christensen, one of the Hystrix devs, sums it up nicely in this post:
However, if you are wrapping blocking calls, you should just stick with using HystrixCommand as that’s what it’s built for and it defaults to running everything in a separate thread. Using HystrixCommand.observe() will give you the concurrent, async composition you’re looking for.
HystrixObservableCommand is intended for wrapping around async, non-blocking Observables that don’t need extra threads.
https://github.com/Netflix/Hystrix/issues/236
HystrixPlugins.getInstance().registerCommandExecutionHook(new MyHystrixCommandExecutionHook());

HystrixPlugins.getInstance().getEventNotifier();
final Field notifierField = HystrixPlugins.getInstance().getClass().getDeclaredField("notifier");
notifierField.setAccessible(true);
((AtomicReference<HystrixEventNotifier>) notifierField.get(HystrixPlugins.getInstance())).set(new GraphiteEventsNotifier(graphiteStats));

HystrixEventNotifier



Labels

Review (572) System Design (334) System Design - Review (198) Java (189) Coding (75) Interview-System Design (65) Interview (63) Book Notes (59) Coding - Review (59) to-do (45) Linux (43) Knowledge (39) Interview-Java (35) Knowledge - Review (32) Database (31) Design Patterns (31) Big Data (29) Product Architecture (28) MultiThread (27) Soft Skills (27) Concurrency (26) Cracking Code Interview (26) Miscs (25) Distributed (24) OOD Design (24) Google (23) Career (22) Interview - Review (21) Java - Code (21) Operating System (21) Interview Q&A (20) System Design - Practice (20) Tips (19) Algorithm (17) Company - Facebook (17) Security (17) How to Ace Interview (16) Brain Teaser (14) Linux - Shell (14) Redis (14) Testing (14) Tools (14) Code Quality (13) Search (13) Spark (13) Spring (13) Company - LinkedIn (12) How to (12) Interview-Database (12) Interview-Operating System (12) Solr (12) Architecture Principles (11) Resource (10) Amazon (9) Cache (9) Git (9) Interview - MultiThread (9) Scalability (9) Trouble Shooting (9) Web Dev (9) Architecture Model (8) Better Programmer (8) Cassandra (8) Company - Uber (8) Java67 (8) Math (8) OO Design principles (8) SOLID (8) Design (7) Interview Corner (7) JVM (7) Java Basics (7) Kafka (7) Mac (7) Machine Learning (7) NoSQL (7) C++ (6) Chrome (6) File System (6) Highscalability (6) How to Better (6) Network (6) Restful (6) CareerCup (5) Code Review (5) Hash (5) How to Interview (5) JDK Source Code (5) JavaScript (5) Leetcode (5) Must Known (5) Python (5)

Popular Posts