1

I'm hoping the experienced Java developers here can share some insight about this problem we have been trying to solve for so many months.

We're currently building a Java web application that uses Jetbrains Xodus as its database. The web application itself is pretty much "done" except for a major issue which the database by design is not designed to be used on a horizontal-scaling environment[I may be wrong], plus the fact that we're pretty much constrained in using NGINX Unit as our application server.

The problem with Horizontal Scaling

Our server is not a typical server that processes just CRUD database requests and can return a response quickly, it processes custom logic that can take up form 0 to 10 seconds (the hard limit) depending on the logic. This brings us to the problem that if the application is not scaled horizontally then these request processing becomes a "blocking" problem. It blocks other requests for seconds.

The problem with Vertical Scaling

Given the first problem, vertical scaling is our next best option, however NGINX Unit (at least it's Java runtime) does not play well with this, it's runtime can only do single thread processing of a request. Thus, even we scale up the cores and memory of the server Unit will just process the request in a single-threaded fashion, making it a "blocking" problem also.

This brings us again to the notion of why we don't just scale horizontally by configuring Unit to spawn more processes (since you can hard set Unit to allow 1 to n processes), the problem is with the database, Jetbrains Xodus is accessed by the application through an embedded Java object which is locked into one process. Accessing it from another process while it is locked to one will not work. So currently, we run our Unit at the max of "1" process.

We've tried to solve this by using off-heap caching, but the database object can't be serialized so this object can only go as far as the heap of the application process, other processes cannot access this object. Also tried to research on sharing objects across multiple Java processes but looking at it, it seems it not a reality atm.

What could be the best approach to solve this within given the given constraints? Using Jetbrains Xodus and NGINX Unit.

8
  • 1
    How seriously are you locked into that database? Is it possible to have many Read-only instances and one writeable instance?
    – Kain0_0
    Sep 15, 2020 at 1:04
  • 5
    According to the readme, Xodus is highly concurrent. Thus, if you have "an embedded Java object which is locked into one process" your problem is homemade. Get rid of that.
    – mtj
    Sep 15, 2020 at 4:43
  • @mtj can you clarity
    – xybrek
    Sep 15, 2020 at 10:25
  • @mtj with Xodus you can only access the db through one Environment object
    – xybrek
    Sep 15, 2020 at 10:43
  • 1
    @xybrek I have never worked with xodus (nor do I intend to) but I see no indication from a quick scan of the docs, that the Environment-object is locking. Thus, generate it in your application once and use it from different threads. If you actually need different processes, you are screwed. In this case, either get another database, or add a database manager service, which only does DB-I/O without the heavy calculations and have all other processes talk to that one.
    – mtj
    Sep 15, 2020 at 12:35

2 Answers 2

1

Unless there's something extremely unique about your application, there's definitely a way to scale it effectively. I'm sensing a couple of design / implemention issues that might be restricting you.

As a general rule, all i/o bound requests should be structured in a non blocking fashion. Asynchronous and coroutines are also viable alternatives so long as control is maintained by the i/o thread. How are you ensuring this today?

On the database locking piece it reminds me of sqlite and how the entire database is locked while one connection occurs. What are your alternative databases or operating modes?

It seems we're missing some pieces on what's a core constraint.

-3

I mix programming languages, using the ideal one on each part of the infrastructure.

For anything that requires scale, performance and concurrency I use go. Only in that particular part.

I glue the rest with the simplest programming language that will work in that context. It usually is Bash for back-end, javascript for front-end, and Kotlin or Java for apps.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.