The real problem behind highly transactional applications.

Submitted by alvaro.soto on Thu, 03/12/2015 - 13:21

An architecture trying to respond a least 10000 concurrent connections per second, is trying to solve the C10K problem, even if this is so last decade is still breaking servers, architectures and configurations, giving to sysadmins real headaches and not always because of real connections, also for basic DDoS attacks (pretty much is the same concept: lots and lots of new connections to the same service).

Today, because of the need of connecting and sharing resources across infrastructures and also the need of implement high availability in solutions many companies have implemented SOA or multi layer solutions, when this solutions can became handy, it could be also be a problem if are not implemented in the correct way: without the proper testing set, and sometimes people don't even know it if the architecture implemented is going to respond in the correct way or even the way that the developers team are planning. this problem does not only affect to wrong configured architectures, also solutions not properly planned to grow.

The problem usually are errors on coding and validation on every layer of the application solution; proprietary code, web server, application server, DBMS, and so on, if applications were coded properly security and bug hunting guys would be unemployed by now.

So what are you going to see in a highly transactional server with a misconfiguration problem?

  • Lots of TIME_WAIT connections.
  • Lots of CLOSE_WAIT connections.
  • Possibly memory problems.
  • Possibly the system swapping.
  • Really Slow server.
  • Many timeouts in the application log.
  • The application became unreachable.
  • We can't create new connections to the server, even ssh ones.
  • ... Worst case scenario, dead servers.

But service restart, reboot and kill will not solve all the problems, nor the operating system or the kernel are there to solve all the problems, the kernel work is to handle the control plane and in a general and multipurpose way, if you take only the kernel tuning approach, the kernel is going to be part of the problem, and you are going to be far far away to solve the problem.

The kernel has a know way to work and know O(n^2) complexity, with every new connection the kernel has to walk down all the current processes to figure out which thread should handle the packet or if we talk of connection polls the process is the same, each packet had to walk a list of sockets.

Hight level Kernel diagram: layers and intercomunication (1).

Even if you take the complete tuning approach, maybe the application is going to work, but not always, you only are going to get stability, but no the real solution, the correct way to handle and solve the C10K problem, even more, C10M is letting the kernel solve de control plane and applications handle the data plane and/or write software to bypass the stack, such as DPDK (2), this is pretty much like if where talking about an exokernel (3), using an end-to-end principle.

Common Kernel V/S ExoKernel (3).

To build usable and scalable applications to support 10 millions concurrent connections per second (and more), we need to solve other kind of problems first.

  • Packet scalability.
  • Multi-core scalability.
  • Memory scalability.

So the real problem is.... knowledge, lots of developers know how to code client/server applications, but less than a 50% of them know how the TCP/IP or TTCP/IP works, how to use MP libraries, I understand this is no and easy task to accomplish, but we really need to start working on that, with every performance problem we also need to start looking in the code and software architecture searching for scalability errors, not always will have site reliability engineers to help our application to be super reliable, super fast, all the time, even if we have this guys to help us, the solution can be found many iterations behind, before the system stars to loosing points of our precious 99.99…99

And what if, we can correct coding errors fast enough or we can’t (in case of a proprietary software): tuning, will always be the answer, but like I said, tune all the layers, not only the kernel:

  • Tune for aggressive network throughput.
  • Tune timeouts.
  • Tune the sockets parameters.
  • Tune shared filesystems.
  • Tune the schedulers.
  • Tune the complete architecture.
  • ….

There are many layers before can reach the kernel, and even if you want to tune the kernel you need to understand how the application works, communicate and use internal and external applications, libraries and utilities.

Common multi layer software architecture (4).

In common transactional architectures, tuning will work like a tourniquet in a bullet wounded, probably saving the life but In highly transactional applications, tuning is just to help the system, not to solve problems and your application will die slow and painfully.