Zum Inhalt springen
EuroVPSEuroVPS

Jede Ticket-Integration liefert doppelt. Bauen Sie sie dafür.

Webhooks wiederholen, Partner senden erneut, Netzwerke verlieren Antworten. So bauen Sie eine Ticket-Bridge, die signiert, idempotent, frei von Schleifen und auf eine Queue begrenzt ist, mit Code, den Sie wiederverwenden können.

Von EuroVPS Engineering

5 Min. Lesezeit
Every ticket integration delivers twice. Build it for that.

Die Anbindung Ihres Ticketsystems an das Portal eines Partners sieht nach einem Nachmittag Arbeit aus: ein Webhook, wenn sich etwas ändert, ein Aufruf ihrer API, wenn sie antworten. Die erste Demo funktioniert immer. Die Probleme beginnen in der dritten Woche, wenn ein Timeout den Absender zum Wiederholen bringt, ein Ticket dieselbe Antwort zweimal erhält und zwei Systeme um drei Uhr morgens anfangen, sich gegenseitig in einer Schleife zu antworten. In diesem Artikel geht es um die vier Eigenschaften, die das verhindern, unabhängig davon, welche Ticketplattformen an den beiden Enden stehen.

Gehen Sie von At-least-once-Zustellung aus

Jeder Absender, der wiederholt, kann dasselbe Ereignis mehr als einmal zustellen. Er hat keine Wahl: Wenn Ihr Server die Anfrage verarbeitet hat, die Antwort aber auf dem Rückweg verloren ging, sieht der Absender ein Timeout und muss es erneut versuchen. «Exactly once» gibt es in einem Netzwerk nicht. Was es gibt, ist At-least-once-Zustellung plus einen Empfänger, der dasselbe gefahrlos zweimal sehen kann.

Die erste Entwurfsregel lautet also: Jedes Ereignis trägt eine stabile, eindeutige Kennung, die der Absender wählt, und der Empfänger protokolliert die Kennungen, die er bereits angewendet hat.

CREATE TABLE applied_events (
  event_id    TEXT PRIMARY KEY,
  received_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
  ticket_ref  TEXT
);

Versuchen Sie bei jeder Zustellung zuerst, die ID einzufügen. Schlägt das Insert am Primärschlüssel fehl, haben Sie diese Arbeit bereits erledigt: Antworten Sie mit Erfolg und hören Sie auf. Dass Sie mit Erfolg antworten, ist wichtig. Antworten Sie mit einem Fehler, wiederholt der Absender weiter etwas, das Sie bereits angewendet haben.

Die Ereignis-ID muss zum Ereignis gehören, nicht zum Zustellversuch. Eine Antwort auf Ticket 4711 sollte eine ID tragen, die aus dieser Antwort abgeleitet ist, zum Beispiel die Transaktions-ID im Quellsystem, damit jede Wiederholung denselben Wert trägt.

Signieren Sie jede Zustellung, und prüfen Sie die Uhr

Signieren Sie jede Zustellung: ein HMAC über den rohen Body mit einem gemeinsamen Geheimnis, gesendet in einem Header, zusammen mit einem Zeitstempel, damit eine mitgeschnittene Anfrage nächste Woche nicht wieder eingespielt werden kann.

import hmac, hashlib, time

SECRET = load_secret()          # never in the code repository
MAX_SKEW = 300                  # seconds

def verify(raw_body: bytes, ts_header: str, sig_header: str) -> bool:
    ts = int(ts_header)
    if abs(time.time()-ts) > MAX_SKEW:
        return False
    signed = f"{ts}.".encode() + raw_body
    expected = hmac.new(SECRET, signed, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, sig_header)

Drei Details, die oft falsch gemacht werden. Signieren Sie die rohen Bytes, nicht ein erneut serialisiertes JSON-Objekt, denn zwei Bibliotheken serialisieren dasselbe Objekt nicht identisch. Vergleichen Sie mit einer Funktion in konstanter Zeit, nicht mit ==. Und halten Sie pro Partner ein eigenes Geheimnis, damit Sie eines rotieren können, ohne die anderen anzufassen.

Brechen Sie Schleifen absichtlich

Eine Bridge kopiert Antworten in beide Richtungen. Wenn System A seine Antworten an B weiterleitet und B seine Antworten an A, dann ist eine Antwort, die von B kam, aus Sicht von A eine neue Antwort auf das Ticket. Ohne Schutz geht sie direkt zurück. Dann macht B dasselbe.

Die Lösung ist, die Herkunft zu markieren und sie vor dem Weiterleiten zu prüfen:

  • Wenn Sie eine eingehende Antwort anwenden, halten Sie fest, dass sie vom Partner kam, zum Beispiel in einem Custom Field oder einem Attribut der Transaktion.
  • Ihr ausgehender Trigger überspringt jede Transaktion, die als vom Partner stammend markiert ist.
  • Tun Sie dasselbe auf der Partnerseite. Verlassen Sie sich nicht auf nur ein Ende.

Testen Sie es dann mit einem echten Ticket: Senden Sie von jeder Seite eine Antwort und prüfen Sie, dass jede auf der anderen Seite genau einmal erscheint.

Geben Sie dem Partner eine Queue und sonst nichts

Die eingehende Richtung bedeutet in der Regel, dass der Partner die API Ihres Ticketsystems aufruft. Geben Sie ihm ein eigenes Konto, nie ein gemeinsam genutztes Administrator-Token, und gewähren Sie Rechte nur auf einer einzigen Queue.

Im Request Tracker heißt das ein Benutzer ohne globale Rechte, und dann, nur auf der gemeinsamen Queue, nur die Rechte, die die Bridge braucht: typischerweise SeeQueue, ShowTicket, CreateTicket, ReplyToTicket und ModifyTicket. Lassen Sie ShowTicketComments weg, damit der Partner nie interne Kommentare lesen kann, und gewähren Sie nichts auf irgendeiner anderen Queue. Stellen Sie ein Auth-Token für diesen Benutzer aus und übergeben Sie es dem Partner.

Beweisen Sie dann den Geltungsbereich, statt ihm zu vertrauen:

# Should succeed: the shared queue
curl -s -o /dev/null -w '%{http_code}\n' \
  -H "Authorization: token $PARTNER_TOKEN" \
  https://rt.example.com/REST/2.0/queue/Partner-Shared

# Should be refused: any other queue
curl -s -o /dev/null -w '%{http_code}\n' \
  -H "Authorization: token $PARTNER_TOKEN" \
  https://rt.example.com/REST/2.0/queue/General

Ein Hinweis speziell zum Request Tracker: Läuft RT unter Apache mit mod_fcgid, wird der Header Authorization nicht an die Anwendung durchgereicht, sofern Sie nicht FcgidPassHeader Authorization in den Virtual Host eintragen. Anfragen mit Token schlagen dann als nicht authentifiziert fehl, obwohl das Token gültig ist. Das sollte man wissen, bevor man einen Abend damit verbringt.

Halten Sie Kommentare aus der Bridge heraus

Leiten Sie Antworten weiter. Leiten Sie nie Kommentare weiter. Ihre Ingenieure brauchen einen Ort, an dem sie «dieser Kunde hat das dreimal gefragt» schreiben können, ohne dass es im Portal von jemand anderem erscheint. Testen Sie es mit einem Kommentar, der eine offensichtliche Markierung enthält, und suchen Sie auf der Partnerseite danach.

Verwerfen Sie nie etwas stillschweigend

Wenn der Endpoint des Partners nicht erreichbar ist, müssen Ihre ausgehenden Zustellungen warten, nicht verschwinden:

  1. Wiederholen Sie mit exponentiellem Backoff und Jitter, für eine begrenzte Zeit.
  2. Parken Sie das Ereignis danach zusammen mit dem Fehler in einem Dead-Letter-Store.
  3. Durchsuchen Sie den Dead-Letter-Store nach Zeitplan und versuchen Sie es erneut.
  4. Alarmieren Sie einen Menschen, wenn etwas länger geparkt bleibt, als Sie tolerieren können.
  5. Protokollieren Sie jede Zustellung mit Ereignis-ID, Ticket, Statuscode und Dauer.

Führen Sie die Zustellung in einem Worker aus, nicht innerhalb der eigenen Anfrage des Ticketsystems. Ist der Partner langsam, sollten Ihre Mitarbeiter nicht darauf warten müssen, dass eine Seite gespeichert wird.

Zwei weitere defensive Gewohnheiten. Prüfen Sie Anhänge beim Testen auf beiden Seiten per Prüfsumme. «Sieht gleich aus» ist kein Test. Und begrenzen Sie die Größe dessen, was Sie annehmen: Ein in voller Auflösung in ein Ticket eingefügtes Inline-Bild kann um ein Vielfaches größer sein als der Text drumherum. Verkleinern Sie es oder legen Sie es gleich am Eingang getrennt ab, statt ein schweres Ticket jede Seite verlangsamen zu lassen, die es darstellt.

Eine Checkliste für Ihre eigene Bridge

  • Jedes Ereignis hat eine vom Absender gewählte ID, und der Empfänger protokolliert die angewendeten IDs.
  • Jede Anfrage ist über den rohen Body signiert, mit Zeitstempel und einem Geheimnis pro Partner.
  • Änderungen, die vom Partner stammen, sind markiert und werden nie zurückgesendet.
  • Das Token des Partners funktioniert auf einer Queue und wird auf jeder anderen abgewiesen, durch Test bewiesen.
  • Kommentare gehen nie hinüber. Antworten immer.
  • Wiederholungen, Dead Letters, Durchläufe und Alarme existieren, und jede Zustellung wird protokolliert.
  • Anhänge werden per Prüfsumme geprüft. Übergroße Inhalte werden beim Eintreffen behandelt.

Wir bauen und betreiben solche Bridges zwischen Request Tracker und Partnerportalen. Wenn Sie eine planen oder mit einer leben, die sich nicht richtig verhält, helfen wir gern.

Mit einem Ingenieur sprechen

Related

Verwandt: Managed Request Tracker mit Partner Bridges · Managed team chat auf Mattermost

Veröffentlicht am 9. Oktober 2026.

Alle Notizen aus der Praxis