Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Hystrix Request Caching by Example

I am trying to figure out how Hystrix request caching works but am not following the wiki or end-to-end examples they provide in their docs.

Essentially I have the following HystrixCommand subclass:

public class GetFizzCommand extends HystrixCommand<Fizz> {
    private Long id;
    private Map<Long,Fizz> fizzCache = new HashMap<Long,Fizz>();

    void doExecute(Long id) {
        this.id = id;
        execute();
    }

    @Override
    public Fizz run() {
        return getFizzSomehow();
    }

    @Override
    public Fizz getFallback() {
        // Consult a cache somehow.
        // Perhaps something like a Map<Long,Fizz> where the 'id' is the key (?)
        // If the 'id' exists in the cache, return it. Otherwise, give up and return
        // NULL.
        fizzCache.get(id);
    }
}

So I feel like I'm going against the grain here. I believe Hystrix offers built-in caching, as is evidenced by a 'cacheKey', but I can't find any working examples. I don't want to reinvent the wheel here and build caching into my commands if something is already provided out of the box.

So I ask: what does request caching look like with Hystrix (exactly)? How are entries added to the cache? How/when is the cache flushed? Is it configurable (expiries, max sizes, etc.)?

like image 934
IAmYourFaja Avatar asked Nov 25 '14 00:11

IAmYourFaja


People also ask

Which of the following is the method to be implemented to include request caching?

Request caching is enabled by implementing the getCacheKey() method on a HystrixCommand object...

How does hystrix command work?

The Hystrix framework library helps to control the interaction between services by providing fault tolerance and latency tolerance. It improves overall resilience of the system by isolating the failing services and stopping the cascading effect of failures.

How does hystrix fallback work?

The principle is analogous to electronics: Hystrix is watching methods for failing calls to related services. If there is such a failure, it will open the circuit and forward the call to a fallback method. The library will tolerate failures up to a threshold. Beyond that, it leaves the circuit open.

Why is hystrix on Netflix?

In a distributed environment, failure of any given service is inevitable. Hystrix is a library designed to control the interactions between these distributed services providing greater tolerance of latency and failure.


2 Answers

Per the documentation you linked to here,

Request caching is enabled by implementing the getCacheKey() method on a HystrixCommand object...

You haven't implemented getCacheKey(),

@Override
protected String getCacheKey() {
    return String.valueOf(id); // <-- changed from `value` in example
}

Then you also need a HystrixRequestContext

HystrixRequestContext context = HystrixRequestContext.initializeContext();

Which is (again, per the documentation)

Typically this context will be initialized and shutdown via a ServletFilter that wraps a user request or some other lifecycle hook.

Then I believe you cannot change the method signature of execute() like that (doExecute() isn't part of the interface) instead you pass the parameter to your command constructor and please annotate execute with an @Override so you get a compiler error if you forget and then

HystrixRequestContext context = HystrixRequestContext.initializeContext();
GetFizzCommand commandA = new GetFizzCommand(2L);
GetFizzCommand commandB = new GetFizzCommand(2L);
Fizz a = commandA.execute(); // <-- should not be cached
Fizz b = commandB.execute(); // <-- should be cached.
like image 143
Elliott Frisch Avatar answered Sep 28 '22 12:09

Elliott Frisch


You need a HystrixRequestContext in your controller

//init
HystrixRequestContext context = HystrixRequestContext.initializeContext();
// get cache logic ...

//close
context.close();

The better way is that you add a filter class.

import com.netflix.hystrix.strategy.concurrency.HystrixRequestContext;
import org.springframework.stereotype.Component;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;

@Component
@WebFilter(urlPatterns = "/*", asyncSupported = true)
public class HystrixRequestContextFilter implements Filter {
  @Override
  public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
    HystrixRequestContext context = HystrixRequestContext.initializeContext();
    try {
      filterChain.doFilter(servletRequest, servletResponse);
    } finally {
      context.close();
    }
  }
}
like image 40
Zgpeace Avatar answered Sep 28 '22 12:09

Zgpeace