Bandit server for Phoenix is next level, check it out!

Hey Guys,

Did you know that there’s an alternative to Cowboy for Phoenix, called Bandit?

And it recently reached {:bandit, "~> 1.0-pre"} version!

Here’s my observation:


In Cowboy based phoenix builds, I noticed that there’s a delay before the websocket connection happened.

As you can notice in the gif below. Other pages load within 100ms, however the websocket connection reaches close to 435ms:

Cowboy


That doesn’t happen with Bandit!

All the resources, along with the socket connection happen within 100ms!
Bandit


Check it out:

7 Likes

I’m already using it in production. It works. The performance is about the same in my use case.

On the plus side, Bandit is built on top of OTP primitives and doesn’t do the annoying silent crashes that Cowboy does.

On the downside, it’s still fairly young, and there are rough edges. Pre-9 version had some breaking bugs, the current (pre-10) version seems okay but some behaviors differ from Cowboy like the lack of interrupting requests when client drops off. We also observed increased memory usage, but these things can be related to one another.

Generally, it looks like it’s the future, and at some point should probably be the default over Cowboy, but you should use it with caution on production (I’m hovering my hand over the switch back to Cowboy just in case for now).

14 Likes

This is the insight I was looking for, thank you.

I’m sticking with Bandit, because I like where its going, and It’s necessary for others to adopt it, so that we can detect those cases where failure happens, and library will improve because of that.

I see only 5 issues on that repo as of now.

6 Likes

I’m here if anyone has any specific blocking issues for adoption at your shops!

28 Likes

The current APM for e.g new relic don’t work with Bandit. This takes away visibility for the apps as there is no telemetry. Any plans to make the telemetry compatible to cowboy so it can be used without losing metrics

The groundwork has been laid, but I do not personally have any plans for such a library (mostly time limitations and the fact that there’s still a lot to do on the core of Bandit).

Bandit provides a rich telemetry interface today (as does Thousand Island). There’s enough there for someone to build everything that’s needed.

3 Likes

Making it “compatible with cowboy” would mean literally emitting events tagged with the :cowboy atom from bandit (and making sure all the metadata was a superset of cowboy’s). The place for bandit support to be added is in the New Relic agent.

3 Likes

On average, I have noticed a 2x - 3x boost in performance with Bandit over Cowboy and it works great with Nginx.

3 Likes

Hi…

When you say it works great with Nginx… What’s the role of Nginx in your case?

I’m curious since it’s both servers, right?

Are you using Nginx as a reverse proxy or maybe for serving static assets only and letting Bandit for the “application” server?

Do you mind sharing some details on your infra?

Thanks!

@hubertlepicki and others; 1.3.0 just went out with a fix for the long-standing issue of increasing memory use (which wasn’t really a memory issue so much as it was an issue with how memory use is reported, but anyway), along with a few other fixes. See CHANGELOG as always. Hopefully this fixes your issue; please report back if so as I’d love to have more evidence that we’ve finally licked this.

9 Likes

Yes, I’m using Nginx as a reverse proxy, caching, serving static files, TLS/SSL termination, and a proxy for gRPC connections.

2 Likes

Hi…
Thanks for the reply…
Does it mean that the requests for static files (e.g. under /priv) are no longer hitting the Phoenix server (here bandit)?
Are you setting this config on Phoenix side or Nginx side? I guess it’s on Nginx… Then the config for static assets on Phoenix becomes somehow useless, right?
For reverse proxy and SSL I was using traefik but I also want to add caching and static assets serving…
So I guess I’ll also switch to Nginx…
Do you think you can share your nginx file (or just the main parts)?

Hi, I’m sorry about not replying sooner. Anyway, the static assets will be served by Nginx. The Nginx configurations will be set within Nginx. Here are some of the main parts to consider:

# Redirect HTTP to HTTPS
server {
    listen 80;
    server_name your_domain.com;
    return 301 https://$host$request_uri;
}

# HTTPS server block
server {
    listen 443 ssl;
    server_name your_domain.com;

    # SSL certificate and key
    ssl_certificate /etc/letsencrypt/live/your_domain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/your_domain.com/privkey.pem;

    # SSL settings
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_prefer_server_ciphers on;
    ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH';

    # Root directory for your Phoenix application's static assets
    root /path/to/your/phoenix/app/priv/static;

    # Proxy requests to Phoenix application
    location / {
        proxy_pass http://127.0.0.1:4000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    # WebSocket support for /live endpoint
    location /live {
        proxy_pass http://127.0.0.1:4000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    # Static file caching
    location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
        expires max;
        add_header Cache-Control "public";
    }
}

The ciphers are a moving target but one can use the following site to assess your overall SSL webserver config:

1 Like