مجله ایرانیکاسرورآموزش سرور، هاست، وردپرس و شبکه
آموزشی

چطور یک زیرساخت VoIP مقیاس‌پذیر با Kamailio، Asterisk و RTPengine بسازیم؟

برای ساخت یک سامانه VoIP مقیاس‌پذیر، اضافه‌کردن چند Asterisk به‌تنهایی کافی نیست. معماری باید Signaling، منطق تماس و Media را از هم جدا کند تا هر لایه بتواند مستقل Scale شود، خراب شود و…

چطور یک زیرساخت VoIP مقیاس‌پذیر با Kamailio، Asterisk و RTPengine بسازیم؟
خلاصه سریع این آموزش

برای ساخت یک سامانه VoIP مقیاس‌پذیر، اضافه‌کردن چند Asterisk به‌تنهایی کافی نیست. معماری باید Signaling، منطق تماس و Media را از هم جدا کند تا هر لایه بتواند مستقل Scale…

۲۷ دقیقه مطالعه ۰ دیدگاه ۲۵ مهر ۱۴۰۵ آخرین به‌روزرسانی
برای ساخت یک سامانه VoIP مقیاس‌پذیر، اضافه‌کردن چند Asterisk به‌تنهایی کافی نیست. معماری باید Signaling، منطق تماس و Media را از هم جدا کند تا هر لایه بتواند مستقل Scale شود، خراب شود و بدون متوقف‌کردن کل سرویس جایگزین شود.

یکی از معماری‌های رایج برای چنین کاری ترکیب Kamailio + Asterisk + RTPengine است. Kamailio در لبه شبکه SIP را دریافت و Route می‌کند، چند Asterisk منطق تماس را اجرا می‌کنند و RTPengine مسیر صوت، WebRTC، NAT و SRTP را مدیریت می‌کند.

اما قرار دادن این سه نرم‌افزار کنار یکدیگر هنوز به معنی High Availability نیست. باید مشخص کنیم Registration کجا ذخیره می‌شود، تماس جدید چگونه بین Asteriskها پخش می‌شود، اگر یک Media Node قطع شد چه اتفاقی می‌افتد، DNS چه نقشی دارد، Database چگونه Redundant می‌شود و در خرابی هر جزء چه بخشی از سرویس باید زنده بماند.

در این راهنما یک معماری Production را از پایه طراحی می‌کنیم و سپس سناریوهای خرابی واقعی را بررسی می‌کنیم.

نسخه‌های مبنای مقاله در ۱۷ اکتبر ۲۰۲۶: Kamailio 6.1.5 آخرین Stable شاخه 6.1 است. Asterisk 22.11.0 آخرین نسخه پایدار LTS فعلی است؛ Asterisk 24 هنوز در مرحله Pre-release قرار دارد. RTPengine نیز Release جدید mr26.2.1.5 و شاخه LTS فعال mr13.5.1.30 را دارد.

فهرست مطالب

معماری VoIP مقیاس‌پذیر یعنی چه؟

مقیاس‌پذیری فقط یعنی «سرور قوی‌تر بخریم» نیست.

دو روش کلی برای افزایش ظرفیت داریم:

Scale Up: CPU، RAM و Network همان سرور را بیشتر کنیم.

Scale Out: Nodeهای بیشتری اضافه کنیم و بار را بین آن‌ها تقسیم کنیم.

برای یک سامانه VoIP بزرگ، Scale Out معمولاً معماری انعطاف‌پذیرتری ایجاد می‌کند؛ زیرا Maintenance، Failover و افزایش ظرفیت به یک ماشین وابسته نمی‌ماند.

مشکل معماری تک‌سروره چیست؟

فرض کنید همه‌چیز روی یک Asterisk اجرا می‌شود:

🔹 Registration

🔹 SIP Trunk

🔹 Dialplan

🔹 Queue

🔹 Recording

🔹 RTP

🔹 WebRTC

🔹 Database

اگر این سرور Restart شود، تمام لایه‌های سرویس هم‌زمان از بین می‌روند.

حتی اگر سخت‌افزار بسیار قوی باشد، همچنان یک:

Single Point of Failure یا SPOF

داریم.

راه‌حل: Signaling، Application و Media را جدا کنیم

معماری هدف ما سه لایه اصلی دارد.

لایه اول: Kamailio برای Signaling

وظایف اصلی:

🔹 دریافت SIP از کاربران و Carrierها

🔹 Registrar در صورت انتخاب این معماری

🔹 Authentication

🔹 NAT Signaling

🔹 Load Balancing

🔹 Health Check

🔹 SIP Firewall و Rate Limit

🔹 Topology Hiding

لایه دوم: Asterisk برای منطق تماس

وظایف اصلی:

🔹 Dialplan

🔹 IVR

🔹 Queue

🔹 Voicemail

🔹 Call Application

🔹 ARI/AMI Integration

🔹 Recording در صورت انتخاب این لایه

لایه سوم: RTPengine برای Media

وظایف اصلی:

🔹 RTP Relay

🔹 NAT Traversal

🔹 WebRTC

🔹 ICE

🔹 SRTP/DTLS

🔹 Media Topology Hiding

🔹 Transcoding در صورت نیاز

نمای کلی معماری پیشنهادی

                Phones / Softphones / Carriers
                           |
                       DNS / VIP
                     /           \
                    /             \
             Kamailio-01       Kamailio-02
                |                  |
                +------ DMQ -------+
                    |          |
                    |          |
             +------+----------+------+
             |             |          |
             v             v          v
         Asterisk-01   Asterisk-02  Asterisk-03
             |             |          |
             +-------------+----------+
                           |
                    Shared Services
                     DB / API / CDR

                     Media Plane
                    /           \
                   /             \
             RTPengine-01    RTPengine-02

چرا دو Kamailio؟

اگر پنج Asterisk داشته باشید اما فقط یک Kamailio در ورودی داشته باشید، مشکل Single Point of Failure فقط از Asterisk به Kamailio منتقل شده است.

حداقل دو Edge Node باعث می‌شود:

🔹 Maintenance یکی بدون توقف کامل سرویس انجام شود.

🔹 خرابی یک Edge تماس‌های جدید را کاملاً متوقف نکند.

🔹 Registration بین چند Edge توزیع شود.

کاربر چطور بین دو Kamailio انتخاب می‌کند؟

چند روش وجود دارد.

روش اول: DNS SRV

برای SIP می‌توان SRV Record ساخت.

مثلاً:

_sip._udp.example.com. 60 IN SRV 10 50 5060 sip1.example.com.
_sip._udp.example.com. 60 IN SRV 10 50 5060 sip2.example.com.

و سپس:

sip1.example.com. IN A 203.0.113.10
sip2.example.com. IN A 203.0.113.11

Priority و Weight در SRV چیست؟

Priority عدد کوچک‌تر را ترجیح می‌دهد.

Weight بین Recordهایی با Priority یکسان احتمال انتخاب را تقسیم می‌کند.

پس:

10 50 sip1
10 50 sip2

یعنی هر دو تقریباً هم‌سطح هستند.

DNS SRV را با Load Balancer واقعی اشتباه نگیرید

DNS از CPU، تعداد تماس فعال یا وضعیت داخلی Kamailio خبر ندارد.

همچنین Endpointهای مختلف رفتار یکسانی در Cache و Failover DNS ندارند.

بنابراین SRV برای Discovery و Redundancy بسیار مفید است، اما به‌تنهایی جای Health Check لحظه‌ای را نمی‌گیرد.

روش دوم: Virtual IP

هر دو Kamailio می‌توانند پشت یک VIP قرار بگیرند.

مثلاً:

sip.example.com
        |
    203.0.113.20
       VIP
     /     \
 Kam-01   Kam-02

Keepalived/VRRP یا زیرساخت Network Provider می‌تواند VIP را بین Nodeها منتقل کند.

VIP برای Active/Standby مناسب است

مزیت آن این است که Phone همیشه یک IP می‌بیند.

اما برای Active/Active باید طراحی Flow و State دقیق‌تری داشته باشید.

روش سوم: L4 Load Balancer

یک Load Balancer لایه 4 نیز می‌تواند UDP/TCP/TLS را بین Kamailioها تقسیم کند.

اما Load Balancer باید رفتار SIP Transport را درست پشتیبانی کند.

HTTP Load Balancer ساده را بدون بررسی برای SIP استفاده نکنید.

برای معماری Production کدام روش بهتر است؟

یک پاسخ ثابت وجود ندارد.

برای Hosted PBX کوچک تا متوسط:

DNS SRV + دو Kamailio

می‌تواند نقطه شروع خوبی باشد.

برای Operator یا سامانه با SLA سخت‌تر:

VIP/L4 + DNS Redundancy

قابل بررسی است.

Kamailio Registration را کجا نگه داریم؟

این تصمیم معماری بسیار مهم است.

دو مدل اصلی داریم.

مدل اول: Phone روی خود Asterisk Register شود

Kamailio فقط REGISTER را Forward می‌کند.

در این مدل Registration State داخل Asterisk قرار دارد.

مشکل این است که User به یک Backend وابسته می‌شود.

مدل دوم: Kamailio خودش Registrar باشد

Phone مستقیماً روی Edge ثبت می‌شود.

Kamailio Contact را داخل:

usrloc

نگه می‌دارد.

Asteriskها بیشتر Application Server می‌شوند.

برای Scale بزرگ کدام مدل تمیزتر است؟

در بسیاری از معماری‌های چندنودی، Registrar مرکزی روی Kamailio جداسازی بهتری ایجاد می‌کند؛ چون Asterisk Backend به Registration همان User وابسته نیست.

اما اگر از FreePBX یا Applicationی استفاده می‌کنید که Presence، BLF و Extension State را مستقیماً از Registrationهای Asterisk انتظار دارد، انتقال Registrar به Kamailio باید با دقت انجام شود.

دو Kamailio چگونه Location کاربران را Share می‌کنند؟

یکی از روش‌ها:

dmq_usrloc

است.

این Module رکوردهای User Location را از طریق:

DMQ

بین Kamailioها Replicate می‌کند.

چرا این مهم است؟

Phone ممکن است REGISTER خود را به Kamailio-01 بفرستد.

تماس ورودی بعدی ممکن است از Kamailio-02 وارد شود.

Node دوم باید بداند User در چه Contactی قابل دسترسی است.

DMQ Network را Private نگه دارید

Replication داخلی نباید بدون نیاز روی اینترنت عمومی قابل دسترسی باشد.

بهتر است Kamailioها یک شبکه خصوصی مخصوص:

🔹 DMQ

🔹 Database

🔹 Monitoring

داشته باشند.

مرحله بعدی: Load Balancing چند Asterisk

فرض کنیم سه Application Node داریم.

Asterisk-01  10.20.10.11:5060
Asterisk-02  10.20.10.12:5060
Asterisk-03  10.20.10.13:5060

Dispatcher برای این کار ساخته شده است

در Kamailio می‌توان این Nodeها را داخل یک Dispatcher Set قرار داد.

مثال:

1 sip:10.20.10.11:5060 0 0 duid=ast01;weight=50;rweight=50
1 sip:10.20.10.12:5060 0 0 duid=ast02;weight=50;rweight=50
1 sip:10.20.10.13:5060 0 0 duid=ast03;weight=50;rweight=50

کدام الگوریتم Dispatcher؟

چند انتخاب مهم داریم.

Algorithm کاربرد
4 Round Robin ساده
5 Hash روی Authorization Username
9 Weight-based
10 Call Load Distribution
11 Relative Weight / Congestion
13 Latency Optimized

برای Application Pool، Algorithm 10 جذاب است

Algorithm 10 تعداد Callهای مرتبط با هر Destination را با یک ساختار سبک مبتنی بر Call-ID دنبال می‌کند.

در نتیجه Node با تعداد تماس کمتر شانس بیشتری برای تماس جدید دارد.

برای فعال‌شدن این الگوریتم:

modparam("dispatcher", "ds_hash_size", 9)

لازم است.

نمونه Selection

if (is_method("INVITE") && !has_totag()) {

    if (!ds_select_dst("1", "10")) {
        send_reply("503", "No Asterisk Available");
        exit;
    }

    t_on_failure("ASTERISK_FAILOVER");
    t_relay();
    exit;
}

این فقط Skeleton آموزشی است؛ Production Route باید Authentication، NAT، Route Set، ACL و Transaction Logic کامل داشته باشد.

Call Load را باید هنگام Reply و BYE هم Update کنیم

برای Algorithm 10 فقط انتخاب Destination کافی نیست.

وقتی INVITE با 2xx تأیید می‌شود، State باید Confirm شود و هنگام BYE یا CANCEL Load آزاد شود.

از:

ds_load_update()
ds_load_unset()

برای این کار استفاده می‌شود.

اگر BYE هیچ‌وقت نرسید چه؟

Kamailio برای Call Load Hash زمان Expire دارد.

مثلاً:

modparam("dispatcher", "ds_hash_expire", 7200)

Default مستند فعلی نیز 7200 ثانیه است.

این مقدار باید با Duration واقعی تماس‌های شما بررسی شود.

Health Check روی Asteriskها

Load Balancing بدون Health Check خطرناک است.

اگر Asterisk-02 Down شود، Kamailio باید آن را از Selection خارج کند.

نمونه:

modparam("dispatcher", "ds_ping_method", "OPTIONS")
modparam("dispatcher", "ds_ping_interval", 10)
modparam("dispatcher", "ds_probing_mode", 1)
modparam("dispatcher", "ds_probing_threshold", 2)
modparam("dispatcher", "ds_inactive_threshold", 2)

این تنظیمات چه می‌کنند؟

`ds_ping_interval` هر ۱۰ ثانیه Health Probe ارسال می‌کند.

`ds_probing_mode=1` تمام Gatewayها را Probe می‌کند.

`ds_probing_threshold=2` اجازه می‌دهد چند Failure قبل از Inactive شدن رخ دهد.

`ds_inactive_threshold=2` نیز برای بازگرداندن Node چند پاسخ موفق می‌خواهد.

مقادیر مثال هستند و باید با SLA و Network شما تنظیم شوند.

چرا با اولین Packet Loss سرور را Down نکنیم؟

اگر یک OPTIONS به‌علت Packet Loss گم شود و Node فوراً Down شود، ممکن است Flapping ایجاد کنید.

یعنی Backend دائماً:

UP → DOWN → UP → DOWN

شود.

Threshold کوچک اما غیرصفر معمولاً رفتار پایدار‌تری دارد.

Failover INVITE چگونه انجام می‌شود؟

اگر Asterisk انتخاب‌شده پاسخ نداد، Destination بعدی را امتحان می‌کنیم.

failure_route[ASTERISK_FAILOVER] {

    if (t_is_canceled()) {
        exit;
    }

    if (t_check_status("408|500|502|503|504")) {

        if (ds_next_dst()) {
            t_on_failure("ASTERISK_FAILOVER");
            t_relay();
            exit;
        }
    }
}

هر 503 را به معنی Crash ندانید

503 می‌تواند به معنی:

🔹 Overload

🔹 Maintenance

🔹 Downstream Failure

باشد.

Policy Failover و Policy Disabled کردن دائمی Node را از هم جدا طراحی کنید.

Media را از Asterisk جدا کنیم

حالا RTPengine وارد معماری می‌شود.

فرض کنیم دو Media Node داریم:

RTPengine-01 10.20.20.11:2223
RTPengine-02 10.20.20.12:2223

Kamailio می‌تواند چند RTPengine داشته باشد

نمونه:

modparam("rtpengine", "rtpengine_sock",
"1 == udp:10.20.20.11:2223=1 udp:10.20.20.12:2223=1")

ساختار دقیق Config را با نسخه Module و Syntax مستند همان Release بررسی کنید؛ مفهوم اصلی این است که چند RTPengine در یک Set قرار می‌گیرند و Weight می‌گیرند.

Selection RTPengine باید در طول تماس ثابت بماند

این نکته حیاتی است.

نباید Offer روی RTPengine-01 ایجاد شود ولی Answer همان Dialog به RTPengine-02 برود.

Media Session State باید به Node صحیح همان تماس برگردد.

RTPengine Offer و Answer

در مسیر INVITE دارای SDP:

rtpengine_offer()

و در پاسخ حاوی SDP:

rtpengine_answer()

استفاده می‌شود.

در بسیاری از Routing Scriptها `rtpengine_manage()` می‌تواند Logic را ساده‌تر کند.

بعد از BYE Media Session را پاک کنید

rtpengine_delete()

Session را آزاد می‌کند.

چرا Media Layer را جدا Scale کنیم؟

Kamailio ممکن است میلیون‌ها SIP Message را با CPU نسبتاً کم Route کند، اما RTPengine با:

🔹 هزاران Packet در ثانیه

🔹 Encryption

🔹 WebRTC

🔹 Transcoding

درگیر است.

بنابراین ظرفیت موردنیاز این دو لایه یکسان نیست.

مثال Scale مستقل

ممکن است معماری شما این باشد:

2 x Kamailio
3 x Asterisk
4 x RTPengine

یا برعکس.

تعداد Nodeها باید از Benchmark واقعی بیاید، نه از نسبت ثابت.

Database در این معماری چه چیزی را نگه می‌دارد؟

باید دو نوع State را از هم جدا کنیم.

Configuration State

مثل:

🔹 User

🔹 Extension

🔹 Password Hash

🔹 Route

🔹 Queue Configuration

🔹 Caller ID

Runtime State

مثل:

🔹 Contact فعلی User

🔹 SIP Dialog

🔹 Media Session

🔹 Queue Agent State

🔹 Active Call

Shared Database به معنی Shared Runtime State نیست

این یکی از بزرگ‌ترین اشتباه‌ها در معماری HA است.

ممکن است سه Asterisk به یک Database مشترک وصل باشند، اما اگر تماس فعال روی Asterisk-01 بوده و آن Node Crash کند، صرف وجود Database تماس فعال را به Asterisk-02 منتقل نمی‌کند.

Memory، Channel، RTP State و Application State روی Node اول بوده‌اند.

Asterisk Realtime برای چه چیزی خوب است؟

PJSIP Realtime اجازه می‌دهد Objectهایی مانند:

🔹 Endpoint

🔹 Auth

🔹 AOR

🔹 Identify

🔹 Contact

در Database ذخیره شوند.

این قابلیت برای Shared Configuration بسیار مفید است.

آیا همه Asteriskها باید از یک DB بخوانند؟

اگر Backendها Configuration مشابه دارند، بله؛ می‌توانید Realtime را برای منابع مشترک استفاده کنید.

اما Database باید خودش HA باشد.

یک Database روی همان Asterisk قرار ندهید

اگر تمام سه Asterisk به Database موجود روی Asterisk-01 وابسته باشند، خرابی Node اول عملاً همه Backendها را ناقص می‌کند.

Database باید Failure Domain جدا داشته باشد.

معماری Database پیشنهادی

مثلاً:

Kamailio / Asterisk
        |
   DB Endpoint
        |
   +----+----+
   |         |
 DB-01     DB-02
 Primary   Replica

یا Cluster متناسب با Database انتخابی.

Kamailio خودش db_cluster دارد

ماژول:

db_cluster

می‌تواند چند Database Connection را پشت یک Cluster URL قرار دهد.

برای Read می‌تواند:

🔹 Serial

🔹 Round Robin

و برای Write حتی Parallel Policy داشته باشد.

اما db_cluster خودش Database Replication نیست

این نکته مهم است.

اگر دو Database مستقل و ناسازگار داشته باشید، صرف Parallel Write از Kamailio آن‌ها را به یک Cluster Consistent واقعی تبدیل نمی‌کند.

Replication، Conflict Handling و Consistency باید در Database Architecture نیز طراحی شوند.

DNS هم باید HA باشد

اگر کل SIP Infrastructure شما به:

sip.example.com

وابسته است ولی فقط یک Authoritative DNS Server دارید، یک SPOF جدید ساخته‌اید.

حداقل دو DNS Node یا DNS Provider Redundant استفاده کنید.

TTL خیلی بالا Failover را کند می‌کند

اگر Record یک ساعت Cache شود، تغییر Emergency DNS ممکن است یک ساعت یا بیشتر برای برخی Clientها باقی بماند.

TTL کوتاه‌تر انعطاف بیشتری دارد، اما Query Load و Cache Behavior نیز باید در نظر گرفته شود.

TTL صفر هم راه‌حل جادویی نیست

Client، Resolver و SIP Deviceها همیشه DNS را دقیقاً مطابق انتظار شما Cache نمی‌کنند.

پس DNS Emergency Failover باید قبل از Production با Deviceهای واقعی تست شود.

حالا سناریوهای خرابی را بررسی کنیم

یک معماری HA فقط با دیاگرام زیبا سنجیده نمی‌شود.

باید بدانیم وقتی اجزا واقعاً خراب شدند چه رخ می‌دهد.

سناریو ۱: Asterisk-02 کاملاً Down می‌شود

وضعیت:

Kamailio        UP
Asterisk-01     UP
Asterisk-02     DOWN
Asterisk-03     UP
RTPengine       UP

Dispatcher با OPTIONS باید Node را Inactive کند.

تماس‌های جدید به 01 و 03 می‌روند.

اما تماس‌های فعال روی Asterisk-02 معمولاً قطع می‌شوند.

چرا تماس فعال منتقل نمی‌شود؟

چون Asterisk دارای:

🔹 Channel State

🔹 Dialplan State

🔹 Bridge State

🔹 Application State

بوده است.

Kamailio نمی‌تواند این State را ناگهان داخل Asterisk دیگری بسازد.

هدف HA در این لایه چیست؟

معمولاً:

کاهش زمان اختلال تماس‌های جدید

نه تضمین انتقال زنده هر تماس موجود.

سناریو ۲: Kamailio-01 Down می‌شود

تماس‌های جدید باید از:

🔹 DNS SRV

🔹 VIP

🔹 L4 Load Balancer

به Kamailio-02 برسند.

تماس فعال چه می‌شود؟

اگر Dialog Route Set شامل Kamailio-01 باشد، Request بعدی مثل BYE یا re-INVITE ممکن است به Node ازکارافتاده برود.

پس Failover تماس فعال در Edge به نوع Transport، DNS، Record-Route و State Replication شما بستگی دارد.

HA تماس جدید بسیار ساده‌تر از Mid-Dialog Failover است.

سناریو ۳: RTPengine-01 Down می‌شود

Kamailio باید برای Sessionهای جدید RTPengine-02 را انتخاب کند.

اما تماس‌هایی که Media آن‌ها روی RTPengine-01 بوده معمولاً صدا را از دست می‌دهند.

Redis می‌تواند به RTPengine کمک کند

RTPengine می‌تواند Call State را در Redis ذخیره کند.

در Startup نیز Stateهای قبلی را Restore کند.

قابلیت‌هایی مثل:

--redis
--redis-write
--redis-subscribe
--active-switchover

برای Persistence و Takeover وجود دارند.

اما Redis مساوی Failover بدون قطعی نیست

برای انتقال واقعی Media باید موارد زیر هم درست باشند:

🔹 IP Routing

🔹 Advertised Address

🔹 Interface Alias

🔹 SRTP State

🔹 Network Reachability

بنابراین Redis بخشی از HA است، نه کل HA.

سناریو ۴: Database اصلی قطع می‌شود

اثر آن بستگی دارد چه چیزی از DB خوانده می‌شود.

ممکن است تماس‌های فعال ادامه پیدا کنند، چون State آن‌ها در Memory است.

اما عملیات جدید مثل:

🔹 Authentication

🔹 Endpoint Lookup

🔹 Routing Query

🔹 CDR Write

ممکن است Fail شود.

DB HA باید جداگانه تست شود

فقط داشتن Replica کافی نیست.

باید واقعاً Database Primary را خاموش کنید و ببینید:

Application چه مدت طول می‌کشد تا به Node جایگزین متصل شود؟

سناریو ۵: Redis قطع می‌شود

اگر Redis فقط برای RTPengine Persistence استفاده شود، Media Sessionهای موجود ممکن است روی Node فعلی ادامه پیدا کنند؛ اما State جدید برای Recovery ذخیره نمی‌شود.

اگر سرویس‌های دیگر نیز به Redis وابسته‌اند، اثر متفاوت است.

Dependency Map را از قبل بنویسید.

سناریو ۶: یک دیتاسنتر کامل قطع می‌شود

این سناریو از خرابی یک Server جدی‌تر است.

اگر Kamailio، Asterisk، RTPengine و Database Backup همه در یک Datacenter باشند، چندسروره بودن شما در برابر قطع کامل آن مرکز داده کمکی نمی‌کند.

Multi-Region واقعی یعنی Failure Domain مستقل

مثلاً:

Region A
Kamailio-A
Asterisk-A1/A2
RTPengine-A

Region B
Kamailio-B
Asterisk-B1/B2
RTPengine-B

Media را بین قاره‌ها بی‌دلیل جابه‌جا نکنید

اگر User و PBX هر دو در Region A هستند، فرستادن RTP از Region B فقط Latency و Jitter اضافه می‌کند.

SIP و Media Region Selection بهتر است هماهنگ باشند.

Geo DNS برای Multi-Region

می‌توانید کاربر را به Region نزدیک‌تر هدایت کنید.

اما Geo DNS نیز Health State و Cache محدودیت‌های خودش را دارد.

برای سرویس حساس، DNS باید فقط یکی از لایه‌های Failover باشد.

سناریو ۷: یک Network Link بین Kamailio و Asterisk قطع می‌شود

ممکن است هر دو Server کاملاً سالم باشند اما Route شبکه بین آن‌ها خراب باشد.

OPTIONS Health Check باید این وضعیت را از دید Kamailio Down تشخیص دهد.

Health Check باید مسیر واقعی سرویس را بسنجد، نه فقط وضعیت Process.

سناریو ۸: Asterisk Process سالم است ولی Database خراب است

SIP OPTIONS شاید همچنان 200 OK بگیرد.

پس Dispatcher Backend را Healthy می‌داند.

ولی تماس واقعی ممکن است در Dialplan Fail شود.

Health Check چندسطحی لازم است

سه سطح Monitoring مفید است:

سطح ۱: Network Reachability

سطح ۲: SIP OPTIONS

سطح ۳: Synthetic Call Test

در Synthetic Test واقعاً یک تماس آزمایشی دوره‌ای ایجاد می‌شود تا Routing، Dialplan و Media بررسی شوند.

Monitoring معماری باید چه چیزهایی را ببیند؟

لایه Metric مهم
Kamailio SIP CPS، Transactions، 4xx/5xx، Dispatcher State، Registrations
Asterisk Active Channels، Calls، CPU، Queue، ARI/AMI Health
RTPengine Sessions، PPS، Bandwidth، Packet Loss، Jitter
Database Connections، Replication Lag، Query Latency، Disk
DNS Resolution، TTL، Authoritative Health
Network Latency، Loss، Jitter، Route Changes

Logها را مرکزی کنید

وقتی شش یا ده Node دارید، SSH زدن به تک‌تک Serverها برای پیدا کردن یک Call مشکل‌ساز مناسب نیست.

Logهای:

🔹 Kamailio

🔹 Asterisk

🔹 RTPengine

🔹 Database

را به یک Log Platform مرکزی ارسال کنید.

Call-ID بهترین کلید Correlation است

وقتی یک تماس از:

Kamailio → Asterisk → RTPengine

عبور می‌کند، Call-ID را در Logهای مختلف قابل جست‌وجو نگه دارید.

این کار Troubleshooting را بسیار سریع‌تر می‌کند.

Tracing SIP را هم جدا داشته باشید

برای Production می‌توانید HEP/HOMER یا راهکار مشابه برای ذخیره SIP Trace در نظر بگیرید.

هدف این است که بتوانید بدون فعال‌کردن Debug سنگین روی تمام Nodeها، Flow تماس را ببینید.

امنیت در معماری چندلایه

جداکردن سرویس‌ها به معنی اضافه‌شدن Network Interface و Port بیشتر است.

اگر Firewall درست طراحی نشود، Scale کردن می‌تواند Attack Surface را افزایش دهد.

Internet فقط باید Edge را ببیند

یک طراحی مناسب:

Internet
   |
Kamailio
   |
Private Network
   |
Asterisk / DB / RTP Control

Asterisk فقط از Kamailio SIP بگیرد

روی Firewall Asteriskها، Source SIP را به IPهای Kamailio محدود کنید.

اگر Carrier نباید مستقیم به Asterisk برسد، Port Public آن را اصلاً باز نکنید.

RTPengine Control Port خصوصی باشد

NG Control Protocol را فقط برای Kamailio/OpenSIPS مجاز کنید.

Media UDP Port Range طبیعتاً باید از Endpointهای لازم قابل دسترسی باشد، اما Control Port نباید Public باشد.

Database فقط از Application Network قابل دسترسی باشد

پورت MySQL/PostgreSQL را برای اینترنت عمومی باز نکنید.

حتی Admin Access Database بهتر است از VPN یا Management Network انجام شود.

TLS کجا قرار می‌گیرد؟

یک معماری متداول:

Phone
  |
SIP TLS
  |
Kamailio
  |
Private SIP
  |
Asterisk

در محیط حساس می‌توانید Internal TLS هم داشته باشید.

SRTP کجا Terminate می‌شود؟

اگر RTPengine Media Edge است، می‌تواند DTLS-SRTP یا SRTP را Terminate و در سمت Backend Profile دیگری تولید کند.

اما این تصمیم باید با Security Policy و Compliance هماهنگ باشد، چون Media در Relay قابل پردازش می‌شود.

Maintenance بدون Downtime چگونه انجام شود؟

یکی از بزرگ‌ترین مزایای Scale-out همین است.

Maintenance Asterisk

مرحله ۱: Node را از Dispatcher خارج کنید.

مرحله ۲: تماس جدید به آن ندهید.

مرحله ۳: Active Callها را Drain کنید.

مرحله ۴: Upgrade/Restart.

مرحله ۵: Health Check.

مرحله ۶: Node را دوباره وارد Pool کنید.

Maintenance RTPengine

همان منطق:

Session جدید به Node ندهید، Media Sessionهای قبلی تمام شوند و سپس سرویس Update شود.

Maintenance Kamailio

Traffic ورودی را به Edge دیگر منتقل کنید، Registration و تماس‌های جدید را بررسی کنید و سپس Node را Upgrade کنید.

Rolling Upgrade بسازید

در معماری چندنودی هرگز همه Nodeها را هم‌زمان Update نکنید.

مدل مناسب:

Drain Node 1
Upgrade
Test
Return to Pool

Drain Node 2
Upgrade
Test
Return to Pool

برای Version Compatibility Matrix داشته باشید

قبل از Upgrade ثبت کنید:

🔹 Kamailio Version

🔹 Asterisk Version

🔹 RTPengine Version

🔹 Database Version

🔹 OS Version

و این ترکیب را ابتدا روی Staging آزمایش کنید.

برای Production فعلی چه نسخه‌ای انتخاب کنیم؟

در زمان نگارش:

Kamailio: 6.1.5 Stable

Asterisk: 22.11.0 LTS Stable

RTPengine: برای Featureهای جدید شاخه mr26.2 قابل بررسی است؛ برای محیط محافظه‌کارانه شاخه LTS `.5` را نیز بررسی کنید.

Asterisk 24 را صرفاً به دلیل شماره بزرگ‌تر برای Production انتخاب نکنید؛ در تاریخ بررسی مقاله هنوز Pre-release است.

Capacity Planning را چگونه انجام دهیم؟

برای هر Layer Benchmark جدا داشته باشید.

Kamailio

معیار اصلی:

🔹 SIP Requests/sec

🔹 CPS

🔹 TLS Connections

🔹 Registration Count

Asterisk

معیار اصلی:

🔹 Concurrent Calls

🔹 CPS

🔹 Queue Load

🔹 Dialplan/API Processing

🔹 Recording

RTPengine

معیار اصلی:

🔹 Concurrent Media Sessions

🔹 Network PPS

🔹 Bandwidth

🔹 SRTP/WebRTC Percentage

🔹 Transcoding Sessions

یک عدد «تماس هم‌زمان» برای کل معماری کافی نیست

ممکن است:

Kamailio هنوز 80 درصد ظرفیت آزاد داشته باشد،

Asterisk 50 درصد CPU داشته باشد،

ولی RTPengine به سقف Network PPS برسد.

Capacity Planning باید Bottleneck هر Layer را جدا ببیند.

Load Test را مرحله‌ای انجام دهید

مثلاً:

25 CPS
50 CPS
100 CPS
150 CPS
200 CPS

و در هر مرحله Call Duration را هم افزایش دهید.

Test Profileهای مختلف بسازید

Profile A: SIP Signaling بدون Media سنگین

Profile B: RTP/G.711 بدون Transcoding

Profile C: WebRTC + Opus + DTLS-SRTP

Profile D: Recording

Profile E: Transcoding

Winner و Bottleneck ممکن است در هر Profile متفاوت باشد.

Failure Injection را جزو تست قرار دهید

هنگام Load Test عمداً:

🔹 یک Asterisk را خاموش کنید.

🔹 یک Kamailio را Restart کنید.

🔹 یک RTPengine را قطع کنید.

🔹 Database Primary را Fail کنید.

🔹 Packet Loss مصنوعی ایجاد کنید.

معماری HA باید در شرایط واقعی آزمایش شود.

جدول سناریوهای خرابی

خرابی تماس جدید تماس فعال راهکار
یک Asterisk به Node دیگر Route می‌شود معمولاً تماس همان Node قطع می‌شود Dispatcher + Health Check
یک Kamailio Edge دوم باید بگیرد Mid-dialog ممکن است متاثر شود SRV/VIP/L4 + State Design
یک RTPengine Media Node دیگر انتخاب می‌شود Media Session روی Node خراب ممکن است قطع شود RTPEngine Set + Redis/HA Design
DB Primary بسته به Query ممکن است Fail شود بسیاری از تماس‌های موجود ادامه می‌یابند DB Replication/Failover
DNS Node Resolver باید DNS دیگر را ببیند معمولاً تاثیری روی Media موجود ندارد Authoritative DNS Redundancy
Datacenter کامل Region دوم تماس‌های Region از دست‌رفته غالباً قطع می‌شوند Multi-Region Architecture

RPO و RTO برای VoIP هم تعریف کنید

فقط Backup کافی نیست.

RTO یعنی سرویس بعد از خرابی چه مدت می‌تواند Down باشد.

RPO یعنی چه مقدار Data Loss قابل قبول است.

برای مثال:

آیا از دست رفتن ۱۰ دقیقه CDR قابل قبول است؟

آیا Configuration جدید داخلی‌ها باید فوراً Replica شود؟

آیا Voicemail و Recording باید خارج از Region دوم نیز Backup شوند؟

Backup چه چیزهایی را شامل شود؟

🔹 Kamailio Config

🔹 Dispatcher Data

🔹 Asterisk Config

🔹 Database

🔹 Recording

🔹 TLS Certificate

🔹 Firewall Policy

🔹 DNS Configuration

Configuration as Code ارزش زیادی دارد

بهتر است Configهای:

🔹 Kamailio

🔹 Asterisk

🔹 RTPengine

🔹 Firewall

در Git یا سیستم Version Control نگه‌داری شوند.

در نتیجه اگر Node جدید لازم شد، Configuration آن از حافظه Administrator ساخته نمی‌شود.

Automation اضافه کنید

برای بیش از چند Node استفاده از:

🔹 Ansible

🔹 Terraform

🔹 CI/CD Configuration

مدیریت نسخه‌ها و Rollback را ساده‌تر می‌کند.

Rollback را قبل از Upgrade طراحی کنید

اگر Kamailio 6.1.5 Upgrade شد و مشکل خاصی با Script شما پیدا شد، باید بدانید چطور به Release قبلی برگردید.

همین موضوع برای Asterisk و RTPengine هم صدق می‌کند.

از Upgrade هم‌زمان سه Layer خودداری کنید

اگر در یک Maintenance Window:

Kamailio + Asterisk + RTPengine

همه تغییر کنند و بعد تماس خراب شود، پیدا کردن عامل اصلی بسیار دشوار است.

تغییرها را مرحله‌ای انجام دهید.

Minimum Production Architecture پیشنهادی

برای پروژه‌ای که واقعاً HA برایش مهم است، یک نقطه شروع منطقی:

2 x Kamailio
2-3 x Asterisk
2 x RTPengine
2 x Database Node
2 x DNS Endpoint / redundant provider
1 x Monitoring platform

است.

این اعداد قانون نیستند؛ معماری نهایی باید از SLA و Load Test بیاید.

آیا همه این‌ها را روی VPS اجرا کنیم؟

برای بسیاری از پروژه‌ها بله.

اما بهتر است Failure Domainها را جدا کنید.

مثلاً اگر همه VPSها روی یک Physical Host باشند، خرابی Host تمام Cluster شما را یکجا از بین می‌برد.

از Provider درباره Anti-Affinity سؤال کنید

اگر سرویس برایتان حیاتی است، Nodeهای HA بهتر است تا حد امکان روی Host یا Zoneهای متفاوت باشند.

HA نرم‌افزاری بدون HA زیرساختی ناقص است.

Network Quality برای RTP مهم‌تر از RAM اضافه است

Media Node ممکن است RAM آزاد زیادی داشته باشد اما Packet Loss یا Jitter کیفیت تماس را خراب کند.

برای RTPengine به:

🔹 Packet Loss پایین

🔹 Jitter پایین

🔹 CPU پایدار

🔹 Network PPS مناسب

نیاز دارید.

چه زمانی این معماری بیش از حد پیچیده است؟

اگر ۲۰ داخلی و یک SIP Trunk دارید، راه‌اندازی:

دو Kamailio + سه Asterisk + دو RTPengine + Database Cluster

احتمالاً هیچ توجیه عملی ندارد.

یک Asterisk یا PBX درست کانفیگ‌شده ساده‌تر و قابل نگهداری‌تر است.

چه زمانی این معماری ارزش دارد؟

🔹 Hosted PBX

🔹 سرویس VoIP چندشرکتی

🔹 Contact Center بزرگ

🔹 Voice API Platform

🔹 WebRTC Service

🔹 Voice AI

🔹 Carrier Interconnect

🔹 سامانه با SLA بالا

چک‌لیست ساخت معماری مرحله‌به‌مرحله

مرحله ۱: Peak CPS و Concurrent Call را اندازه بگیرید.

مرحله ۲: مشخص کنید Registrar کجا باشد.

مرحله ۳: دو Kamailio Edge طراحی کنید.

مرحله ۴: DNS SRV یا VIP را انتخاب کنید.

مرحله ۵: DMQ/usrloc Replication را در صورت Registrar بودن Kamailio فعال کنید.

مرحله ۶: Asterisk Pool را بسازید.

مرحله ۷: Dispatcher Health Check را فعال کنید.

مرحله ۸: Load Distribution را Benchmark کنید.

مرحله ۹: RTPengine Pool را اضافه کنید.

مرحله ۱۰: NAT و SDP Rewrite را تست کنید.

مرحله ۱۱: WebRTC/SRTP را در صورت نیاز تست کنید.

مرحله ۱۲: Database HA را مستقل طراحی کنید.

مرحله ۱۳: Monitoring و Central Logging بسازید.

مرحله ۱۴: Failure Injection انجام دهید.

مرحله ۱۵: Rolling Upgrade و Rollback را مستند کنید.

پرسش‌های رایج

معماری VoIP مقیاس‌پذیر چیست؟

معماری‌ای است که Signaling، منطق تماس، Media و Data را تا حد ممکن از هم جدا می‌کند تا ظرفیت با اضافه‌کردن Node افزایش پیدا کند و خرابی یک Server کل سرویس را متوقف نکند.

Kamailio در معماری چندسروره چه نقشی دارد؟

Kamailio معمولاً SIP Edge، Registrar، Load Balancer، NAT Signaling Layer و Security Proxy است و تماس‌های جدید را بین Asteriskها Route می‌کند.

Asterisk چه کاری انجام می‌دهد؟

Asterisk Application Server تماس است و Dialplan، IVR، Queue، Voicemail، Recording و Integrationهای ARI/AMI را اجرا می‌کند.

RTPengine چرا لازم است؟

RTPengine Media را از Signaling جدا می‌کند و برای NAT، WebRTC، SRTP، ICE، Media Topology Hiding و Scale مستقل RTP استفاده می‌شود.

آیا DNS SRV برای HA کافی است؟

خیر. SRV برای معرفی چند SIP Server و Priority/Weight مفید است، اما Health Check لحظه‌ای، Cache Behavior و Failover Session را به‌تنهایی حل نمی‌کند.

چطور تماس‌ها بین چند Asterisk تقسیم می‌شوند؟

Kamailio Dispatcher می‌تواند از الگوریتم‌هایی مانند Round Robin، Weight، Call Load یا Latency-aware برای انتخاب Backend استفاده کند.

اگر یک Asterisk وسط تماس Crash کند، تماس به Node دیگر منتقل می‌شود؟

معمولاً خیر. تماس‌های جدید Failover می‌شوند، اما State تماس فعال روی Asterisk قبلی بوده و انتقال زنده آن ساده نیست.

اگر RTPengine خراب شود چه می‌شود؟

تماس‌های جدید می‌توانند به Media Node دیگری بروند، اما تماس‌های فعال روی Node خراب ممکن است Media خود را از دست بدهند. Redis و طراحی Active Switchover می‌توانند Recovery پیشرفته‌تری فراهم کنند ولی تضمین Failover بدون وقفه نیستند.

آیا Database مشترک باعث HA کامل Asterisk می‌شود؟

خیر. Database می‌تواند Configuration را Share کند، اما Channel، Dialog و Runtime Call State هنوز روی Asterisk مربوطه قرار دارند.

آیا Kamailio و RTPengine را روی یک VPS نصب کنیم؟

برای Lab یا بار کم ممکن است، اما در Production پرترافیک جداسازی Signaling و Media امکان Scale و Monitoring مستقل‌تری می‌دهد.

چند Kamailio برای Production لازم است؟

اگر High Availability واقعاً نیاز است، یک Kamailio کافی نیست. حداقل دو Edge Node نقطه شروع منطقی‌تری است، اما معماری نهایی به SLA و Traffic بستگی دارد.

برای این معماری VPS ایران مناسب است؟

اگر کاربران و SIP Provider عمدتاً داخل ایران هستند، قرارگیری SIP و Media Node نزدیک کاربران می‌تواند Latency را کاهش دهد. برای کاربران چندمنطقه‌ای معماری Multi-Region مناسب‌تر است.

جمع‌بندی

معماری VoIP مقیاس‌پذیر با Kamailio، Asterisk و RTPengine زمانی موفق است که هر Component مسئولیت مشخصی داشته باشد.

Kamailio باید Signaling Edge را مدیریت کند، Asterisk منطق تماس را اجرا کند و RTPengine مسئول Media باشد.

اما Scale-out فقط اضافه‌کردن Node نیست. DNS، Registrar State، Dispatcher، Database، Media Session، Monitoring و Failure Domain همگی باید Redundant باشند.

در طراحی مناسب، خرابی یک Asterisk نباید تماس‌های جدید کل سامانه را متوقف کند؛ خرابی یک Kamailio نباید تمام SIP Endpoint را از دسترس خارج کند و خرابی یک RTPengine نباید Media Sessionهای جدید را متوقف کند.

در مقابل، باید واقع‌بین بود: HA تماس جدید بسیار ساده‌تر از Failover بدون وقفه تماس فعال است. اگر Asterisk یا RTPengine وسط تماس Crash کند، حفظ کامل همان Session به طراحی State و Network بسیار پیشرفته‌تری نیاز دارد.

بهترین معماری آنی نیست که بیشترین تعداد Server را داشته باشد؛ معماری درست، معماری‌ای است که Failure Scenarioهای آن از قبل شناخته، آزمایش و مانیتور شده باشند.

منابع و مستندات
نسخه‌های روز، Dispatcher، DNS SRV، Database Cluster، Asterisk Realtime، RTPengine و سناریوهای HA این مقاله با مستندات رسمی پروژه‌ها تا ۱۷ اکتبر ۲۰۲۶ بررسی شده‌اند.
Kamailio
مرجع آخرین نسخه Stable شاخه 6.1، تاریخ انتشار و سازگاری Config و Database Schema در نسخه 6.1.5
Load Balancing
مرجع Round Robin، Weight، Call Load، Latency-aware Routing، OPTIONS Probe، ds_load_update و Backend Failover
Registrar HA
مرجع Replication رکوردهای User Location بین چند Kamailio با DMQ برای معماری Registrar چندنودی
Database HA
مرجع چند اتصال Database، Read/Write Policy، Failover Connection و Cluster URL در Kamailio
Asterisk LTS
مرجع Asterisk 22.11.0 به‌عنوان آخرین نسخه پایدار LTS فعلی و وضعیت نسخه‌های پشتیبانی‌شده
Asterisk Database
مرجع ذخیره Endpoint، Auth، AOR، Identify و Contactهای PJSIP در Backend Database
RTPengine
مرجع Releaseهای جدید mr26.2.1.5 و شاخه LTS mr13.5.1.30 در اکتبر ۲۰۲۶
Media HA
مرجع Redis Persistence، Session Restore، Active Switchover، Interface Alias و Failover State در Media Layer
DNS SIP
مرجع استاندارد DNS Resolution و Failover برای SIP Serverها
DNS SRV
مرجع Priority و Weight در SRV Record و انتخاب چند Server برای یک سرویس
زیرساخت پیشنهادی ایرانیکاسرور برای VoIP چندسروره

قبل از انتقال تماس‌های اصلی، Cluster را روی چند VPS مستقل بسازید و عمداً خرابش کنید

برای معماری Kamailio + Asterisk + RTPengine، مهم‌تر از تعداد Core این است که Nodeها شبکه پایدار، IP ثابت، منابع قابل پیش‌بینی و امکان جداسازی Failure Domain داشته باشند. Media Node نیز باید Packet Loss و Jitter پایینی داشته باشد.

می‌توانید ابتدا دو Kamailio، دو Asterisk و دو RTPengine آزمایشی روی سرورهای مجازی ایرانیکاسرور راه‌اندازی کنید، DNS و Private Network را تنظیم کنید و سپس با SIPp تماس ایجاد کنید. بعد یک Node را عمداً خاموش کنید و بررسی کنید تماس‌های جدید، Media و Registration دقیقاً چگونه Failover می‌شوند.

مشاوره معماری Kamailio، Asterisk و RTPengine: 021-91302467

اشتراک‌گذاری مقاله
گفت‌وگو درباره آموزش

دیدگاه‌ها (۰)

هنوز دیدگاهی ثبت نشده است.

دیدگاه یا سؤال خود را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *