Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move to JCache (JSR 107) for quote caching #9

Open
jwalcorn opened this issue May 1, 2020 · 2 comments
Open

Move to JCache (JSR 107) for quote caching #9

jwalcorn opened this issue May 1, 2020 · 2 comments

Comments

@jwalcorn
Copy link
Member

jwalcorn commented May 1, 2020

Right now, I'm using the Jedis (Java for Redis) library to cache quotes, so that I don't make extra-cluster calls every time someone asks for the price of a given stock. If I've gotten a quote for a given stock symbol in the past hour (that's configurable, via an env var), I just use that from the cache, rather than calling out to API Connect again. This way, when I run a stress test, like via my Looper microservice, I'm not racking up thousands of calls to APIC or IEX (my free plan only allows 50,000 calls per month, then cuts me off for the rest of the month, unless I upgrade to a paid plan).

I'd like to switch from hardcoding the caching provider to Redis, to instead use the portable JCache library added to Java EE 8 under JSR 107. This defines the industry-standard javax.cache package, rather than me directly coding to the redis.clients.jedis package. Then I could presumably plug in any JCache provider (much like how I use JMS, rather than coding directly to the MQ client package, in my portfolio microservice).

I'm considering moving the caching logic out of the main JAX-RS class and into a QuoteCache class. That would simplify the main JAX-RS class, which is currently way too concerned about talking to Redis. So if I move to JCache, I'll likely split up this microservice into at least two Java classes, rather than the all-in-one-class approach used today.

@jwalcorn
Copy link
Member Author

Note I investigated this for several days back a year or so ago, and ended up holding off on pulling the trigger on this. I liked the simplicity of the API, but I was hitting issues at runtime with the JCache environment not being stable. When run under load, there would be intermittent exceptions, and sometimes the server would just start spewing periodic exceptions even if there wasn't any load. I'd looked at both Redisson's JCache support, and looked a bit at the Red Hat Data Grid. I think the latter (a productization of the open source Infinispan project - https://infinispan.org) looks more production-ready and supported, so if I pick this back up, that is likely the way I'd go. But for now, there are higher priority issues, so this remains a "good idea to work on some day" issue.

@jwalcorn
Copy link
Member Author

I've proceeded on this further. I have a version of StockQuote.java coded to JCache now, using Redisson as the caching provider. It is stable and runs well in our stress tests. However, I hit a couple of issues for which I need to figure out some solution, which is why I haven't checked it in yet:

  1. I don't see a way to pass the Redis URL as an env var to this JCache/Redisson environment like we do with Jedis. They expect you to have a redisson-jcache.yaml file in your war file's classes directory that contains a line for that Redis URL, among other things. So for now in my local copy I've hardcoded that to point to our ElastiCache server in AWS, but obviously I don't want that hardcoded going forward. Need to see if there's some way to override that setting (or perhaps store that file in a Secret and mount it to a place on the class path?)
  2. I also haven't found a way to get Redisson to use the SSL cert from the env var, like I can do with Jedis. Liberty has a cool feature that lets you add to the truststore at runtime via an env var, rather than having to burn that into the truststore file in your Docker image. But in that redisson-jcache.yaml file, you have to tell it the path to your truststore, and it doesn't honor the thing of that being dynamically updated at runtime, leading to SSL exceptions if you are pointing to a Redis server that requires TLS (via the rediss: protocol)

Both of these issues defeat my usual approach of letting people specify such stuff in their CR yaml and me passing such values in as env vars via my operator. So it will take some more investigation to figure out a solution that doesn't involve me hardcoding stuff/burning it in to my Docker image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant