praveenperera

praveenperera

Load testing: Struggling to get more than 50K-60K connections to a Phoenix Channel using Tsung

I’ve been trying load test of phoenix channels for an app I’ve been working on for a client. I’m using tsung to do so. I’m struggling to get more than 50K-60K connections at a time. I feel like I’m missing something simple, but I’ve been struggling with this for a while now.

EDIT: I also just tried it with a brand new phoenix project:
GitHub - praveenperera/bare_channel · GitHub

Here is my info:

Tsung setup:
Version: 1.6.0
5 worker nodes: DigitalOcean - 16GB 6vCPUs
1 controller node: DigitalOcean - 16GB 6vCPUs

Application server setup:
DigitalOcean - 8GB 4vCPUs also tried 16GB 6vCPUs

Elixir: 1.8.1
Phoenix: 1.4.6

I removed all code from the channel. Now on join it just sends back an :ok response with an empty payload.

What I’ve tried so far:

  1. Increasing limits on all the workers, the controller and the node running the phoenix application. I used this script to do so:
#!/bin/bash

#limits
sudo sysctl -w fs.file-max=12000500;
sudo sysctl -w fs.nr_open=20000500;
ulimit -n 20000001;
sudo sysctl -w net.ipv4.tcp_mem='10000000 10000000 10000000';
sudo sysctl -w net.ipv4.tcp_rmem='1024 4096 16384';
sudo sysctl -w net.ipv4.tcp_wmem='1024 4096 16384';
sudo sysctl -w net.core.rmem_max=16384;
sudo sysctl -w net.core.wmem_max=16384;

echo "fs.file-max = 1048576" >> /etc/sysctl.conf
echo "# limits
* soft     nproc          1048576
* hard     nproc          1048576
* soft     nofile         1048576
* hard     nofile         1048576
root soft     nproc          1048576
root hard     nproc          1048576
root soft     nofile         1048576
root hard     nofile         1048576
" >> /etc/security/limits.conf
echo "session required pam_limits.so" >> /etc/pam.d/common-session
sysctl -p

touch /root/setup_log
echo "COMPLETE AT: $(date)" >> /root/setup_log
  1. Different versions of tsung, different settings.
  2. Tried the websocket instead of tcp on tsung but it wasn’t sending messages properly
  3. Switched over to using releases instead of doing mix phx.server
  4. Removed all application code, only replying with an :ok and empty payload
  5. Deploying a new version straight on the VPS, avoiding docker and k8s
  6. Turned logger level to warn
<?xml version="1.0"?>
<tsung loglevel="warning" version="1.0">
  <clients>
    <client host="tsung-worker-1" use_controller_vm="false" maxusers="64000" cpu="6">
      <ip scan="true" value="eth0"/>
    </client>
    <client host="tsung-worker-2" use_controller_vm="false" maxusers="64000" cpu="6">
      <ip scan="true" value="eth0"/>
    </client>
    <client host="tsung-worker-3" use_controller_vm="false" maxusers="64000" cpu="6">
      <ip scan="true" value="eth0"/>
    </client>
    <client host="tsung-worker-4" use_controller_vm="false" maxusers="64000" cpu="6">
      <ip scan="true" value="eth0"/>
    </client>
    <client host="tsung-worker-5" use_controller_vm="false" maxusers="64000" cpu="6">
      <ip scan="true" value="eth0"/>
    </client>
  </clients>
  <servers>
    <server host="134.209.166.67" port="9962" type="tcp"/>
  </servers>
  <load>
    <arrivalphase phase="1" duration="300" unit="second">
      <users maxnumber="2000000" arrivalrate="2000" unit="second"/>
    </arrivalphase>
  </load>
  <options>
    <option name="ports_range" min="1025" max="65535"/>
  </options>
  <sessions>
    <session name="websocket" probability="100" type="ts_websocket">
      <request>
        <websocket type="connect" path="/socket/v1/websocket?vsn=2.0.0"/>
      </request>
      <request>
        <websocket type="message">          ["1", "1", "payload:url!!!commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4","phx_join", {}]        </websocket>
      </request>
      <for var="i" from="1" to="1000" incr="1">
        <thinktime value="30"/>
      </for>
    </session>
  </sessions>
</tsung>

Results:

I am only hitting about 60% CPU usage and 50% memory usage. Does anyone know how many connections I should be reasonably be expecting on a server this size?

Marked As Solved

outlog

outlog

would think 60 seconds is the default timeout for Phoenix Channels (or rather the socket phoenix/lib/phoenix/transports/websocket.ex at main · phoenixframework/phoenix · GitHub) .. since you are not sending heartbeats, the channels will close down - pretty much at the same rate as new ones are added - thus the flatline..

see https://gist.githubusercontent.com/Gazler/53b842764f778fe57757/raw/9509c3d980f13bbb739f4ae117dc84ef1d721076/phoenix.xml which might help (it sends the heartbeats..)- though I’m searching for a more recent config.

      <for var="i" from="1" to="10" incr="1">
        <thinktime value="10"/>
        <request>
          <websocket ack="no_ack" type="message">{"topic":"phoenix","event":"heartbeat","payload":{},"ref":"3"}</websocket>
        </request>
      </for>

alternatively:
set the phoenix channel timeout to infinity.. eg
user_socket.ex:
transport(:websocket, Phoenix.Transports.WebSocket, timeout: :infinity)

Also Liked

praveenperera

praveenperera

Oh wow that was it! Thanks a lot. I had the heartbeat message in on an earlier test configuration but I was having the same problem. Might have been caused by something else at the time. But it seems to be working now! I had a feeling it was going to be something simple that I over looked.

Thanks for everyone’s input and help!

The commit that fixed it: Set websocket timeout to infinity · praveenperera/bare_channel@00d5653 · GitHub

NOTE: I am getting different errors and crashes around 140 secs now, but I can definitely work through them.

I will report back, I am curious to see what it takes to max out this box (8GB, 4CPU $40/month)

praveenperera

praveenperera

That’s actually going to be my next test. I will post the results.

praveenperera

praveenperera

I ran two tests

  1. On VPS (no k8s) using distillery release: Add and configure distillery for releases · praveenperera/bare_channel@ba93e01 · GitHub

  1. On K8s cluster using distillery release: Add dockerfile and release script · praveenperera/bare_channel@d540f68 · GitHub

I feel like I’m probably missing something again because this is a huge drop. I think I’m going to do the rest of my testing on the VPS and come back to trying to improve performance on the K8s cluster.

More info on cluster:

  • Running on DigitalOcean managed K8s (DOKS)
  • 3 8GB/4vCPU worker nodes
  • Workload running on one node without any other workloads
  • Tsung connects directly to the node using Nodeport service

Where Next?

Popular in Questions Top

electic
Hi, I am new to Elixir. I am trying to use the DateTime component to insert a date into MySQL however the there seems to be no way to fo...
New
Kurisu
For example for a current url like http://localhost:4000/cosmetic/products?_utf8=✓&amp;query=perfume&amp;page=2, I would like to get: ...
New
fireproofsocks
I’m working on defining a simple Ecto schema for a table (in PostGres), but I don’t see where I can define a column as NOT NULL. Conside...
New
pmjoe
I have a relationship of love and hate with Elixir. Lots of things are just absolutely right, but there are some things that are kind of ...
New
alice
Hey, Just curious what are the main benefits of Elixir compared to Clojure? When is Elixir more useful than Clojure and vice versa? Th...
New
srinivasu
How to handle excepions in elixir? Suppose i have A, B, C ,D, E modules. and each module has get() function. A.get() method will call t...
New
rms.mrcs
Hi, I need to transform a list of numbers into a map where the keys are the indexes and the values are the original values of the list. ...
New
komlanvi
Hi everyone, I was playing with phoenix liveView but I run into an issue. I have a form and want to validate each input text when the te...
New
vegabook
I’m brand new to Phoenix and I have stripped one of the demo applications to the bone. I just want to get an svg up on the screen. Here i...
New
lanycrost
Hi everyone! I need implement if…else if…else condition from my elixir code, and anymore of this control flow structures not work proper...
New

Other popular topics Top

lastday4you
I wanted to check elixir version in phoenix because i found that my elixir is 1.5 but when i use Enum.chunk_by it said the function is un...
New
belgoros
I’m not a pro in using Regex and can’t figure out why the following behaviour happens, especially if we take into account the difference ...
New
gausby
I asked this very same question on twitter and got some interesting feedback, but I thought it would be a good question to ask here as we...
1207 39523 209
New
AngeloChecked
What learn first? Rust or Elixir Hi Elixir community! I’m here because i want learn a new language. I’m a junior developer and mainly i ...
New
joeerl
Hello again - after a longish gap I’ve decided I really must dig into Elixir and see what’s been happening here - so I have a few questio...
New
RisingFromAshes
I’ve read in another post that it may be possible with a router helper - but I couldn’t find an appropriate one, and tbh, I’m still just ...
New
nsuchy
Hi. I’ve noticed that Windows Powershell has it’s own IEX command and you cannot access Elixir’s IEX due to the conflict. This isn’t a cr...
New
Qqwy
Update: How to use the Blogs &amp; Podcasts section You can post links to your blog posts or podcasts either in one of the Official Blog...
3271 127536 1222
New
svb
Hi! Currently I want to submit a form by pressing the Enter key. However, since my input field is of type “textarea” this is just adds a...
New
vonH
In asking this question I am more interested about the expressiveness of the language itself and less concerned about the availability of...
New

We're in Beta

About us Mission Statement