Move to JCache (JSR 107) for quote caching
Opened this issue · 2 comments
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.
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.
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:
- 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'sclasses
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?) - 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 therediss:
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