no schema che osserviamo costantemente: un'azienda sottoscrive un contratto per 100 SMS al secondo, configura la sua applicazione per raggiungere il limite e ne riceve solo dodici. La larghezza di banda è sufficiente. Il protocollo SMSC è corretto. Nessuno è stato limitato. Il traffico è semplicemente lentissimo e il primo istinto è sempre quello di dare la colpa al percorso. Quasi mai è il percorso il problema. È la finestra temporale.
SMPP è un protocollo asincrono che la maggior parte delle integrazioni esegue accidentalmente in modo sincrono. Capire il perché è ciò che fa la differenza tra pagare per la velocità di trasmissione e riceverla effettivamente.
Che cos'è effettivamente la finestra
La finestra rappresenta il numero di PDU che potresti aver inviato ma non ancora confermato, in un singolo bind, in un dato momento. Inviando un submit_sm, il SMSC risponde con un submit_sm_resp, ma il SMPP non richiedeva mai di attendere tale risposta prima di inviare il messaggio successivo. La finestra indica quanto in anticipo è consentito eseguire l'operazione.
Con una finestra di 1, invii, attendi, ricevi, invii di nuovo. La tua velocità di trasmissione è ora limitata dal tempo di andata e ritorno, non da quanto concordato commercialmente. Con un tempo di andata e ritorno di 40 ms, si tratta di 25 messaggi al secondo, indipendentemente da quanto stabilito dal contratto. Con una finestra di 10, ne hai dieci in transito contemporaneamente e lo stesso collegamento trasporta circa dieci volte il traffico sulla stessa connessione.
La dimensione della finestra è il fattore determinante principale per la velocità di trasmissione ottenuta da un'associazione, ed è l'impostazione che più spesso viene lasciata al valore predefinito della libreria, limitando silenziosamente l'integrazione ben al di sotto della velocità concordata.
Perché così tante librerie ne scelgono una come predefinita?
Una finestra di 1 è il valore predefinito sicuro per un autore di librerie. Non richiede stato di correlazione, gestione dei timeout o riordino: ogni richiesta ha esattamente una risposta in sospeso, quindi un client inesperto può trattare SMPP come richiesta/risposta senza mai notare la differenza. Funziona, è facile da capire ed è lento. Molte librerie client SMPP vengono distribuite in questo modo e il valore non viene mai riconsiderato perché apparentemente non presenta problemi: i messaggi arrivano, ma non rapidamente.
I numeri di sequenza sono ciò che rende possibile una finestra
Ogni PDU SMPP contiene un sequence_number nella sua intestazione di 16 ottetti. Quando più richieste vengono inviate simultaneamente, questo numero è l'unico elemento che collega ogni submit_sm_resp all'submit_sm che l'ha generata. Non è garantito che le risposte arrivino nell'ordine in cui sono state inviate le richieste, quindi un client che utilizza una finestra di elaborazione superiore a 1 deve mantenere una mappa dei numeri di sequenza in sospeso e farli corrispondere all'arrivo.
Due regole sono fondamentali. Non riutilizzare mai un numero di sequenza mentre è ancora in corso: una risposta tardiva a un numero riciclato verrà attribuita al messaggio sbagliato. E imposta sempre un timeout per le voci: se non arriva mai una risposta, lo slot deve essere rilasciato, altrimenti la finestra effettiva si riduce a zero nel corso della sessione, il che produce il fastidioso sintomo di un blocco che inizia rapidamente e si aggrava nel corso delle ore.
È possibile osservare questo processo campo per campo nel nostro simulatore di sessione SMPP: mostra il valore sequence_number nell'intestazione di ogni PDU e quale risposta corrisponde a quale richiesta.
Le dimensioni della finestra e i TPS sono limiti diversi
Questi due concetti vengono costantemente confusi. TPS è un limite di velocità imposto dall'operatore: invii al secondo, misurati in un intervallo di tempo. L'intervallo SMPP è un limite di concorrenza configurabile: PDU in sospeso in un dato istante. Interagiscono, ma non rappresentano lo stesso numero.
La relazione è approssimativamente: TPS raggiungibili ≈ finestra ÷ tempo di andata e ritorno. Una finestra di 10 con un tempo di andata e ritorno di 50 ms fornisce circa 200 TPS. Se l'operatore impone un limite di 100, si raggiungerà il limite e si riceverà ESME_RTHROTTLED per l'eccesso. Se l'operatore consente 500 e la finestra è di 10, non si raggiungeranno mai 500, indipendentemente dalla quantità di traffico offerto: si è limitati dalla concorrenza, non dalla velocità.
| Finestra | Andata e ritorno | Soffitto | Sintomo |
|---|---|---|---|
| 1 | 40 ms | ~25 TPS | La tariffa concordata non è mai stata raggiunta; il collegamento sembra inattivo |
| 10 | 40 ms | ~250 TPS | Adatto alla maggior parte dei mittenti aziendali |
| 50 | 40 ms | ~1.250 TPS | Solo se l'operatore ha dato il suo consenso; altrimenti, aspettati una limitazione della velocità. |
| 10 | 250 ms | ~40 TPS | Limitato dalla latenza: alza la finestra o avvicinati |
Lettura corretta di ESME_RTHROTTLED
ESME_RTHROTTLED (0x00000058) significa che è stata superata la frequenza di invio concordata. Non si tratta di un rifiuto del messaggio né di un errore di routing. La risposta corretta è quella di rimandare l'invio e riprovare: considerarlo come permanente significa scartare silenziosamente un traffico che l'operatore avrebbe accettato un attimo dopo.
È anche il segnale che la finestra temporale è ormai troppo ampia per la velocità di elaborazione che si sta mantenendo. Se l'aumento della finestra ha causato una limitazione della velocità anziché un aumento della velocità di trasmissione, il vincolo si è spostato dalla concorrenza al contratto, e la discussione successiva sarà di natura commerciale anziché tecnica.
enquire_link: l'altro motivo per cui i legami muoiono
Un bind che non invia nulla appare identico a un bind la cui connessione TCP si è interrotta silenziosamente: i timeout NAT e i firewall stateful interrompono le sessioni inattive senza avvisare nessuna delle due parti. Il messaggio enquire_link ogni 30-60 secondi dimostra che il socket è ancora utilizzabile in entrambe le direzioni. Se si perde la finestra temporale prevista dall'operatore, il messaggio SMSC interromperà la connessione, solitamente nel momento meno opportuno.
Invia enquire_link sulla stessa connessione utilizzata per l'invio, rispondi prontamente all'enquire_link dell'SMSC e considera una risposta mancante come una sessione interrotta: unbind, riconnettiti e riprendi. Un client che continua a inviare dati a un socket semiaperto produce il classico problema in cui tutto sembra a posto ma non viene consegnato nulla.
Come dimensionare una finestra nella pratica
- Misura il tempo di andata e ritorno sul bind che usi effettivamente, non dal tuo laptop. Invia un singolo messaggio con una finestra di 1 e un intervallo di tempo compreso tra submit_sm e submit_sm_resp.
- Dividete il numero di transazioni al secondo (TPS) previste dal contratto per il numero di messaggi al secondo consentiti da un singolo scambio di messaggi. Il quoziente risultante rappresenta la finestra temporale minima utilizzabile.
- Aggiungi un margine di sicurezza: arrotonda per eccesso e poi aggiungi circa il 50%, perché il tempo di andata e ritorno non è costante e una finestra dimensionata esattamente in base alla media avrà prestazioni inferiori in corrispondenza della mediana.
- Aumenta gradualmente, non in un colpo solo, e fai attenzione a ESME_RTHROTTLED. Il primo rallentamento prolungato ti indica qual è il vero limite dell'operatore.
- Conferma il valore con l'operatore. Alcuni SMSC impongono una finestra massima per ogni associazione e, se superata, mettono in coda o scartano silenziosamente la richiesta.
- Solo allora, e non prima, si può considerare un secondo bind. I bind multipli moltiplicano la concorrenza, ma moltiplicano anche i modi in cui una sessione può fallire.
Quando più vincoli battono una finestra più grande
Esiste un limite alla quantità di traffico che una connessione TCP può gestire. Oltre qualche centinaio di PDU in sospeso, le modalità di errore diventano problematiche: un singolo problema di socket si trascina via tutto il traffico, il blocco in testa alla coda diventa evidente e il ripristino dopo un'interruzione implica la riproduzione di un grande set di dati in transito. La maggior parte degli operatori preferisce avere diversi blocchi di dimensioni moderate piuttosto che uno enorme, e molti, se interrogati, vi diranno qual è la configurazione che preferiscono.
Suddividere per classe di traffico anziché in modo arbitrario. Mantenere i codici di accesso monouso, che richiedono tempi rapidi, separati dal marketing di massa significa che un'ondata di marketing non può ritardare l'emissione di un codice di accesso: una decisione che, in realtà, riguarda il prodotto e quindi la capacità di elaborazione.
Una lista di controllo prima di dare la colpa al percorso
- Qual è la finestra configurata e qualcuno l'ha impostata intenzionalmente?
- I numeri di sequenza in sospeso sono scaduti e rilasciati?
- Il programma enquire_link è in esecuzione all'intervallo previsto dall'operatore?
- Le risposte ESME_RTHROTTLED vengono ritentate con un ritardo (backoff) o considerate come errori?
- Il tempo di andata e ritorno misurato corrisponde a quello che avevi previsto quando hai dimensionato la finestra?
- Le ricevute (deliver_sm) vengono confermate tempestivamente? Anche un flusso di ricevute non confermato può bloccare la sessione.
Domande frequenti
Qual è una buona dimensione per una finestra SMPP?
Non esiste un valore universale, perché quello corretto dipende dal tempo di andata e ritorno e dalla tariffa contrattualizzata. Un buon punto di partenza per il traffico aziendale è 10, quindi aumentatelo fino a raggiungere il TPS contrattualizzato o a visualizzare ESME_RTHROTTLED. Calcolando il valore come TPS contrattualizzato × tempo di andata e ritorno, più circa il 50% di margine, la maggior parte delle integrazioni si avvicina al risultato desiderato al primo tentativo.
Una finestra più grande aumenta la mia velocità di trasmissione senza limiti?
No. Una volta che la finestra è sufficientemente ampia da raggiungere il limite di velocità dell'operatore, ulteriori aumenti producono ESME_RTHROTTLED anziché un maggior numero di messaggi. La finestra elimina un collo di bottiglia dovuto alla concorrenza; non può innalzare un limite commerciale.
Perché la mia velocità di trasmissione dati diminuisce nel corso delle ore anziché immediatamente?
Questo è il sintomo classico di numeri di sequenza in sospeso che non vengono mai scaduti. Ogni risposta mancante consuma in modo permanente uno slot della finestra, quindi la finestra effettiva si riduce nel corso della sessione fino a quando il bind si comporta come se la finestra fosse 1. Il rilascio degli slot al timeout risolve il problema.
Il codice ESME_RTHROTTLED rappresenta un guasto permanente?
No, e trattarlo come tale comporta una perdita di traffico. Significa che hai superato la velocità concordata in quel preciso istante. Fai un passo indietro, riprova con lo stesso messaggio e, se la limitazione della velocità persiste, riduci la finestra temporale o rinegozia la velocità.
Con quale frequenza devo inviare enquire_link?
L'intervallo di 30-60 secondi è quello usuale e il valore esatto deve corrispondere a quello previsto dall'operatore. Lo scopo è dimostrare che una sessione TCP potenzialmente inattiva è ancora attiva in entrambe le direzioni prima che un NAT o un firewall la interrompa silenziosamente.
Devo usare un unico grande rilegatura o diverse rilegature più piccole?
Diversi collegamenti di dimensioni moderate sono generalmente più salutari di un unico collegamento molto grande, perché un guasto del socket comporta una perdita di capacità limitata anziché totale. Suddividere per classe di traffico — codici di accesso critici in termini di tempo separati da quelli di massa — in modo che un picco di traffico di marketing non possa ritardare un codice di accesso.
La finestra temporale influisce anche sulle ricevute di consegna?
Sì, nella direzione opposta. Il protocollo SMSC invia le ricevute deliver_sm e, se la tua applicazione è lenta a restituire deliver_sm_resp, il flusso di ricevute si blocca. Su un transceiver bind, questa congestione può influire sull'intera sessione, quindi conferma le ricevute tempestivamente anche se le elabori in modo asincrono.
Dove posso osservare questo comportamento senza collegarmi a un vero dispositivo SMSC?
Il nostro simulatore di sessione SMPP esegue un'intera sessione SMPP 3.4 nel browser — binding, submit, la ricevuta di consegna asincrona, enquire_link e unbind — e mostra i campi di ogni PDU mappati sugli ottetti effettivi sulla rete. Non viene stabilita alcuna connessione e non viene inviato nulla.
La versione breve
Se un binding non offre prestazioni ottimali, controllate la finestra temporale prima di controllare la rete. SMPP è asincrono per impostazione predefinita e la maggior parte delle integrazioni lo esegue in modo sincrono per errore. Dimensionate la finestra temporale in base al tempo di andata e ritorno misurato e alla velocità concordata, impostate un timeout per i numeri di sequenza, assicuratevi che enquire_link sia corretto e riprovate ESME_RTHROTTLED con un margine di sicurezza. Questa sequenza risolve la maggior parte dei problemi di throughput senza che nessuno debba modificare il percorso.
