Show HN: Dracan – Open-source, 1:1 proxy with simple filtering/validation config (github.com)
If you are tired of using Apache or Nginx to proxy your app and implement validation or limiting you may be interested in this hobbyist project. Thanks for all feedback.
28 comments
[ 2.6 ms ] story [ 68.3 ms ] threadUsed rules that are example within repository.
Results: https://pastebin.com/61Fyy2Pe ( too long to past it here... sorry )
Request Time: The average request time in all tests is about the same, ranging from 0.006 to 0.007 seconds. Max request time does increase with more requests; it peaks for the most substantial test of 100,000 requests at 0.136 seconds, which does show that some requests take much longer.
Requests per Second: The number of requests per second is highest in the smaller tests, around 143 RPS for the 10 requests, whereas for 100,000 requests it goes down to about 122 RPS. A probable conclusion in this case could be that while increasing the number of requests, some little slowdown starts to develop in the system.
Percentiles: The median, which usually stands at approximately 0.0035 seconds, essentially means half of the requests are done in under that time. The far higher values of the 90th and 99th percentiles just prove that while most of the requests may be fast, the others take considerably longer.
In general, it performs quite well under a reasonable load but biffs a bit if the number of requests is increased.
I can test OKD/k8s on Thursday at the earliest.
In real-world, business and enterprise situations, which is where Zato is used, about 99% of latency comes from the backend systems that your API integration platform integrates.
These are all the databases, CRMs, IoT, cloud and other software or hardware components that you'll be integrating.
Whether you use Python or not, they're always going to be the culprits.
That it's very convenient to integrate complex systems in Python is what does matter though.
Consider that a network of hospitals, an airport, or a telecommunications operator will have at least 50-500 different sorts of systems to integrate, and to do it properly you need to have a team of at least 6-10 people working for several years.
Looking at it from that perspective, taking the whole enterprise into account, Python is the only choice.
It's easy to find people with backend experience who will be eager to work on API-heavy projects, new people leaving universities know primarily Python, and the kinds of complex business logic that is needed to handle such scenarios are best expressed in a very high-level language.
Here's a few articles for you to explore this subject further:
https://zato.io/articles/index.html
A lot of people on HN say things like “for 99% of production apps Postgres is perfect”, but I consider Postgres a bit lackluster because above that scale it’s more annoying to manage than “worse” dbs like MySQL. The difference in our takes is because my “production” needs look very different from their “production” needs.
(I personally wouldn’t put an interpreted GC language in the request pathway for my production app; we sometimes use Cloudflare functions which are JS, but a very heavily optimized JS runtime and even that is a bit concerning)
Now that the GIL will be removed and adding a JIT is an inevitable step as well, we're looking into replacing everything written in Java with Python in the perspective of the next 10-20 years, depending on how soon people retire in a specific geographic region around the world.
The generation of people who, between 1995-2010, rewrote everything from C++ and COBOL into Java is now in their late 40s and 50s, so it's safe to assume there will be plenty of work for Python people until the next generation begins to mature around 2035-2040.
Now, whether it makes sense today to rewrite in Python something like a proxy, which is not a very complex type of software in itself?
If, starting today, you'd like to build within a year a proxy for something like StackOverflow, it's better to leave it for lower-level languages, like Go and Rust. These are replacements for C and C++, rather than Java, so they would likely be a better choice.
That said, my real message is, don't stick to writing such simple software for too long anyway.
If it's for educational purposes, to learn how all the various protocols work, or how to design server-side software, or to learn how to build an online community, that's a different story.
But you have this high level language in Python that lets you easily accomplish things that the lower-level languages just aren't best suited for, so once you wrote your first proxy and it can handle a few hundred or thousand requests/s, pick a high-level goal and work towards that instead! :-)
Compared to compiled languages and JIT languages CPython is not fast, and removing the GIL does not improve the single thread performance of the language, right now it causes a 1-2% performance regression of single thread. Something like request validation seems like it wouldn’t benefit from more threads much; or if you need N threads to validate a request in 1ms in Python, it’s likely you could validate the same request in 1 thread in 1ms with another language.
Whether it's going to be a worthy goal in the future, I'm not quite sure. I consider this class of software an already well-researched subject in a congested space, and I'd just move on to something more interesting, to a greener field.
P.S: Yes I am looking for some high-level project to participate in or just help with the knowledge I have.
https://github.com/tluyben/go-proxy
https://github.com/tluyben/redis-sentinel-proxy
just to make them easier to instrument for my experiments. The first one I made because after trying all tutorials on haproxy/nginx to make proxying work without the target domain being resolvable (so no dns entry until it's up), I got annoyed (nothing worked while everything only and gpt said it should work) and just did it like this. Also it makes it very easy to throw in my own, complex as I want rules and logging and telemetry (to whatever I want) at any level.
The second I needed to test an existing, not able to change (they have an old version running they cannot update at the moment, don't ask) software against a redis sentinel setup.
The main thing is that I am more and going towards having the program language as config instead of greenspun's tenth rule where everyone builds some annoying and limited 'almost (usually esoteric) programming language' as config language over time. I want that hard lifting to be done in my native language (Lisp, Go, Rust) and have the config be for ip addresses and ports only.
With "forward auth", when the server receives a request it first sends the key information about the request to a separate HTTP server - if the response is a 200 then the proxy server continues processing the request, any other response rejects the request.
You can do all sorts of authorization and authentication and some validation (the request body is not typically sent to the forward auth server).
I wrote Checkpoint401 which is a forward auth server desgined specifically for doing the job of handling forward auth requests from proxy servers. Its written in TypeScript/Deno - all you do is write short authorization functions. https://github.com/crowdwave/checkpoint401
One of the good things about forward auth is that it is not a proxy so it is not sitting as a barrier in between client and server shoveling data back and forth - forward auth focuses only on examining the inbound request - this makes things more simple.
Forward auth does not have all the validation and filtering which Dracan seems to have but they solve some similar problems.
I see some merit to moving the size limits etc out of the application to reduce CPU waste there on overly large requests, but either way I’m still burning some CPUs on it.
Is the use-case for this mostly about sticking some validation in front of a system who’s code you can’t or don’t want to modify for some reason, like in front of Wordpress?