*
the original controversy was about whether it's better to let slow HTTP requests block
things or stack up in an async context, and the contention was that it doesn't much
matter either way and that the difference won't be too big.
TL;DR: The difference isn't only big, it's enough to make the OP's proposed
scenario work.
Using the sample code I listed above, I tested this at 750 INVITEs/second using a minimal
number of listener processes in docker on WSL2 in the background of my laptop while I did
my other work (far from an ideal). Yes, I had to bump the shared memory up to 1 GB. And
that is high, but it's far more sane than 750 listener processes. At one point in
time, there was a problem with the http connection to the http service, but this
didn't cause any type of crash or unmanagable event. For a variety of reasons,
I'd probably look to implement two of these redirect servers in the real world and
balance requests between the two.
[ben@NV0162~/projects/AAA_examples/kamailio/http_async]$ dc exec kamailio kamcmd ps
1 main process - attendant
7 udp receiver child=0 sock=127.0.0.1:5060
8 udp receiver child=1 sock=127.0.0.1:5060
9 udp receiver child=0 sock=172.23.0.2:5060
10 udp receiver child=1 sock=172.23.0.2:5060
11 slow timer
12 timer
13 secondary timer
14 Http Async Worker
15 ctl handler
16 tcp receiver (generic) child=0
17 tcp receiver (generic) child=1
18 tcp main process
[cid:fc4b45d6-ef07-4d63-ad78-39bfb8404f2e]
Less than 1% failure rate to the UA, under far from ideal conditions, with no re-attempts,
etc.
Kaufman
Senior Voice Engineer
E: bkaufman(a)bcmone.com
SIP.US Client Support: 800.566.9810 | SIPTRUNK Client Support: 800.250.6510 |
Flowroute Client Support: 855.356.9768
[img]<https://www.sip.us/>
[
img]<https://www.siptrunk.com/>
[
img]<https://www.flowroute.com/>
________________________________
From: Alex Balashov via sr-users <sr-users(a)lists.kamailio.org>
Sent: Monday, December 23, 2024 11:17 AM
To: Kamailio - Users Mailing List <sr-users(a)lists.kamailio.org>
Cc: Alex Balashov <abalashov(a)evaristesys.com>
Subject: [SR-Users] Re: Kamailio not receiving packets on high CPS
CAUTION: This email originated from outside the organization. Do not click links or open
attachments unless you recognize the sender and know the content is safe.
The http_async_client event loop is a better performer, for sure. But the original
controversy was about whether it's better to let slow HTTP requests block things or
stack up in an async context, and the contention was that it doesn't much matter
either way and that the difference won't be too big. You just can't have a slow
HTTP API.
The beauty of EVAPI is that there's no query, no new connection, and no event loop
beyond normal TCP socket multiplexing.
—
Sent from mobile, apologies for brevity and errors.
On Dec 23, 2024, at 12:10 PM, Ben Kaufman <bkaufman(a)bcmone.com> wrote:
We're agreed on creating a dedicated redirect server for this process, I'm not
sure I agree on the need to ramp up processes on this, when the tradeoff of holding the
transaction in shared memory while waiting for an http response exists. To be sure,
you're trading increased shared memory vs increased package memory, but there's
frequently other considerations as well. In situations like this, I find that I'm
doing a database dip, etc. in addition to the http request . Adding more workers adds more
DB connections, unnecessarily increasing memory consumption.
I'd go so far as to say that the older http_client generally shouldn't be used.
If you have very infrequent http requests to execute and want to use it because it's
syntactically easier then it might make sense, but beyond that it only offers lesser
performance.
Honestly, this thread has mostly devolved to two points:
1.
Should HTTP requests ever be used: I think we're all agreed that they're not
ideal. **HOW** not ideal they are and how much we can force other things to use an
alternate process remain.
2.
When making http requests, which module should be used. Without hesitation I would say to
use http_async_query for the performance gain.
Kaufman
Senior Voice Engineer
E: bkaufman(a)bcmone.com
SIP.US Client Support: 800.566.9810 | SIPTRUNK Client Support: 800.250.6510 |
Flowroute Client Support: 855.356.9768
[img]<https://www.sip.us/>
[
img]<https://www.siptrunk.com/>
[
img]<https://www.flowroute.com/>
________________________________
From: Alex Balashov via sr-users <sr-users(a)lists.kamailio.org>
Sent: Monday, December 23, 2024 10:51 AM
To: Kamailio (SER) - Users Mailing List <sr-users(a)lists.kamailio.org>
Cc: Alex Balashov <abalashov(a)evaristesys.com>
Subject: [SR-Users] Re: Kamailio not receiving packets on high CPS
CAUTION: This email originated from outside the organization. Do not click links or open
attachments unless you recognize the sender and know the content is safe.
One additional thought -- sorry for the numerous messages:
This discussion has got a little too academic. When talking about concurrency, it's
important to ask what the workload actually is and how parallelisable it is.
1) All these async tricks are most useful when you have a busy Kamailio server that does
lots of different kinds of things. Freeing up worker processes becomes an important
objective, because not blocking them with these requests allows them to handle those
requests and those other replies.
2) The other important consideration is locking: how much are shared-memory structures
(transaction state, dialog state, htables, etc) being accessed by multiple worker
processes?
These issues are typical of Kamailio-based multiservice SIP gateways that perform
functions like call routing, registration, presence, etc. all in one system.
Purpose-built redirect servers that query an HTTP API have a trivial and one-track
workload. They receive an INVITE, it's allocated to a worker, the worker goes and
bangs on an HTTP server, gets a response, and sends it back to the callee. There are no
other requests to juggle, save for the incidental OPTIONS ping maybe, there are no SIP
replies to process and relay, and nothing else to do except to absorb ACKs (if the
redirects are sent statefully). Along the way, vanishingly little is being accessed apart
from transaction memory (if stateful), and concurrent accesses to that are fast because
the locks are pretty granular.
Thus, this type of workload doesn't benefit from general-purpose throughput
optimisations much. The proper approach, using whichever HTTP client module, is to spin up
as many child processes as can be spun up without diminishing returns, and just dedicating
them to that singular function while studiously avoiding lockable shared data (e.g.
htable). This keeps all the cars mostly in their own lanes, and the success or failure of
that per se will dictate throughput.
-- Alex
On Dec 23, 2024, at 11:25 am, Alex Balashov
<abalashov(a)evaristesys.com> wrote:
PS. A key selling point of this is that if the TCP client crashes or becomes unavailable,
the transaction just times out after a while, instead of any Kamailio worker processes
shitting themselves or blocking because they're unable to connect to something.
There's nothing to connect to.
This alone sold me. Once you go EVAPI, you can't go back.
-- Alex
On Dec 23, 2024, at 11:23 am, Alex Balashov
<abalashov(a)evaristesys.com> wrote:
On Dec 23, 2024, at 10:56 am, Ben Kaufman via
sr-users <sr-users(a)lists.kamailio.org> wrote:
This came off a bit more harsh than I intended. I think I understand the advantage of
EVAPI in that it can initiate a command to Kamailio (thus Kamailio doesn't need to
hold the thread, possibly it doesn't need to store the message even), but it would
still be nice to have a higher level overview of how this would be achieved. Not even
example code, but more a base architecture explanation / diagram of the flow.
It's probably not complicated enough to warrant a diagram.
1) EVAPI server is initialised:
loadmodule "evapi"
modparam("evapi", "workers", 3)
modparam("evapi", "bind_addr", "xxx:10399")
2) TCP client connects to this socket when it becomes available;
2) Kamailio receives request and serialises it (e.g. JSON), embedding the transaction ID
and label in whatever serialisation structure is used, then emits it on the EVAPI bus,
e.g.
evapi_async_relay("invite_request:$T(id_index):$T(id_label):$(var(data){s.encode.base64})");
3) TCP client reads this package off the wire; the built-in netstring support is ideal.
It then processes it, generates a response, serialises it, and puts it back on the wire.
Vitally, the $T(id_index) and $T(id_label) are embedded in the response, allowing Kamailio
to resume the transaction:
4) Kamailio receives this message in $evapi(msg), in this event_route, and resumes the
transaction into route[RESUME]:
event_route[evapi:message-received] {
...
jansson_get("tm_trans.tm_index", "$evapi(msg)",
"$var(t_index)");
jansson_get("tm_trans.tm_label", "$evapi(msg)",
"$var(t_label)");
t_continue("$var(t_index)", "$var(t_label)", "RESUME");
...
}
5) In route[RESUME], INVITE processing continues as normal, enlightened by anything else
that was deserialised out of $evapi(msg).
EVAPI is my favourite Kamailio module, and the only way I interface with outside
services, when it's up to me.
-- Alex
--
Alex Balashov
Principal Consultant
Evariste Systems LLC
Web:
https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Fevaristes…
Tel: +1-706-510-6800
--
Alex Balashov
Principal Consultant
Evariste Systems LLC
Web:
https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Fevaristes…
Tel: +1-706-510-6800
--
Alex Balashov
Principal Consultant
Evariste Systems LLC
Web:
https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Fevaristes…
Tel: +1-706-510-6800
__________________________________________________________
Kamailio - Users Mailing List - Non Commercial Discussions --
sr-users(a)lists.kamailio.org
To unsubscribe send an email to sr-users-leave(a)lists.kamailio.org
Important: keep the mailing list in the recipients, do not reply only to the sender!