Appodeal ist ein Unternehmen mit ca. 100 Mitarbeitern, die in Moskau, San Francisco, Barnaul, Luzk, Kirow, Barcelona und seit Juni 2018 auch in Minsk arbeiten.
Wir monetarisieren mobile Apps, indem wir Anzeigen für Benutzer schalten. Wir haben mit der Werbemediation begonnen, aber der Technologie-Stack wächst ständig, sodass auch andere Produkte aus der Ad Tech-Branche zur Mediation hinzugefügt wurden.

Für diejenigen, die mit Ad Tech nicht vertraut sind, ist dies der Arbeitsbereich von Technologieunternehmen, die im Bereich Werbung tätig sind. Wenn Sie jemandem sagen, dass Sie im Bereich der mobilen Werbung arbeiten, reagieren die Leute oft mit Skepsis - anscheinend fällt Ihnen die nervige Werbung „Azino Three Axes“ ein. Tatsächlich ist dies nur die Spitze des Eisbergs, und all diese „wilde“ Werbung hat nichts mit dem echten Werbegeschäft zu tun.
Und das mobile Segment, in dem wir tätig sind, ist dem Segment der Werbung im Web längst entwachsen:

Warum Anzeigen in Apps integrieren?
Natürlich werden viele Ressourcen für die Erstellung von Anwendungen aufgewendet - und die Ersteller / Eigentümer möchten, dass sich Zeit und Mühe auszahlen. Besitzer von mobilen Anwendungen, die ihre Anwendung im App Store / Google Play veröffentlichen, werden als Publisher oder Publisher bezeichnet. Publisher wenden unterschiedliche Monetarisierungsmodelle an, von In-App-Käufen bis hin zur Monetarisierung von Werbung. Von all diesen Methoden kann der Benutzer jedoch nur mit letzterer nicht für die Nutzung der Anwendung bezahlen - und dies bietet die größte Abdeckung für das Publikum.
Ja, wenn zu viel Werbung vorhanden ist, wird dies alle stören und die Benutzerbindung beeinträchtigen. Was natürlich niemand braucht. Daher versuchen sie immer, Werbung mit Bedacht zu integrieren, um das maximale Geld für ihre Anwendung zu verdienen und gleichzeitig den Nutzern keinen Cent abzunehmen.
Wie funktioniert es
Sobald der Verlag beschließt, durch Werbung Geld zu verdienen, kommt er zu dem Unternehmen, das ihm diese Aufgabe so einfach wie möglich machen kann. Wie passiert das mit Appodeal? Nach der Registrierung auf der Website integrieren wir seine Anwendung in unseren Service. Dies erfolgt über das Client-SDK, das die Anwendung mit dem Serverteil verbindet und über die API mit dem Serverteil kommuniziert.
Wenn Sie die Details minimieren, wird das Ziel der Interaktion auf zwei Stufen reduziert:
a. Bestimmen Sie, welche Anzeige gerade geschaltet werden soll.
b. Senden Sie Informationen darüber, welche Werbung gezeigt wurde und welche nicht, und zeigen Sie sie in Statistiken an.
Derzeit bedient Appodeal mehrere tausend aktive Anwendungen, die ungefähr 400 bis 450 Millionen Anzeigenimpressionen pro Tag liefern und als Antwort auf etwa 1 Milliarde Anfragen an Werbenetzwerke (die die Anbieter von Werbung sind) eingehen. Damit dies funktioniert, bedienen unsere Server etwa 125.000 Anfragen pro Sekunde, d. H. ungefähr 10,8 Milliarden Anfragen pro Tag.

Worauf baut das alles auf?
Wir verwenden verschiedene Technologien, um Geschwindigkeit, Zuverlässigkeit und gleichzeitig Flexibilität bei Entwicklung und Support zu gewährleisten. Im Moment schreiben wir Code in den folgenden Sprachen:
- / Ruby / Ruby on Rails + React.JS (Front-End) /: Es gibt immer noch einen großen Teil der API und des gesamten Webparts, den Benutzer und unsere Mitarbeiter sehen
- / GoLang /: Verarbeitung großer Mengen von Statistikdaten und nicht nur
- / Scala /: Echtzeitverarbeitungsanforderungen für die Arbeit mit Datenaustauschbörsen unter Verwendung des RTB-Protokolls (mehr dazu am Ende des Artikels)
- / Elixir / Phoenix /: Eher der experimentelle Teil. Erstellen einiger Mikrodienste zur Verarbeitung einiger Statistiken und APIs.

Warum ist es ursprünglich Ruby und Ruby on Rails?
Appodeal konkurriert in seinem Segment mit sehr großen Akteuren, sodass Sie sich schnell an Marktveränderungen anpassen müssen. Oft fühlt sich dies wie eine Veränderung der Räder eines Autos bei einer Geschwindigkeit von 100 km / h an. Ruby on Rails ermöglichte es uns, dem Rennen standzuhalten und auf dem Markt Fuß zu fassen, um in seinem Segment führend zu sein. Die Hauptvorteile von Rails sind unserer Meinung nach:
- Eine große Anzahl qualifizierter Entwickler
- Tolle Community. Eine Vielzahl vorgefertigter Lösungen und Bibliotheken
- Die Geschwindigkeit, mit der neue Funktionen eingeführt und alte geändert / gelöscht werden

Von den offensichtlichen Minuspunkten:
- Die Leistung ist insgesamt schlecht. Dies wirkt sich auch auf das Fehlen von JIT (im Moment) und das Fehlen der Fähigkeit zur Parallelisierung des Codes aus (wenn Sie JRuby nicht berücksichtigen). Bis zu einem gewissen Grad bleibt dies erträglich, da der Engpass normalerweise die Datenbank und der Cache sind. Was wir auf dem Bild von NewRelic sehen:

- Schienenmonolithe sind auf Microservices nicht sehr gut geschnitten - sie sind von einem hohen Grad an Konnektivität zwischen Geschäftslogik und Datenzugriffslogik (ActiveRecord) betroffen.
Wie werden die Daten gespeichert?
Wir haben viele Daten. Sehr. Wir sprechen über Milliarden / Zehn / Hunderte von Milliarden von Aufzeichnungen. Da die Daten völlig unterschiedlich sind, speichern wir sie auf unterschiedliche Weise. Es sollte in der Architektur niemals auf eine Lösung beschränkt sein, die angeblich universell ist. Die Praxis zeigt, dass es zum einen in Highload praktisch keine universellen Lösungen gibt. Universalität bedeutet durchschnittliche (oder deutlich unterdurchschnittliche) Indikatoren für Zugriff / Lesegeschwindigkeit / Datenspeichergröße als Gebühr für diese Vielseitigkeit. Zweitens müssen Sie ständig etwas Neues ausprobieren, experimentieren und nach nicht trivialen Lösungen für die Aufgaben suchen. Gesamt:
- / PostgreSQL /: Wir lieben Postgre. Wir halten es derzeit für die beste OLTP-Speicherlösung. Dort werden Daten zu Benutzern, Anwendungen, Werbekampagnen usw. gespeichert. Wir verwenden die Replikation des Primärreplikats. Wir machen Backups nur in den Weihnachtsferien, weil dies für Weicheier ist (ein Witz).
- / VerticaDB /: Spaltenorientierte Datenbank. Wir speichern Milliarden von Statistikdatensätzen. Kurz gesagt, Vertika galt einige Zeit als die beste OLAP-Lösung zum Speichern von Analysen. Der Hauptnachteil ist der enorme (individuelle) Preis für die Lizenz.
- / ClickHouse /: Auch eine spaltenorientierte Datenbank. Wechseln Sie schrittweise mit VerticaDB dorthin. Wir betrachten derzeit die beste OLAP-Lösung. Keinen Cent wert. Es funktioniert sehr schnell und zuverlässig. Das Haupt-Minus ist, dass die Daten nicht gelöscht und aktualisiert werden können (wir werden in einem separaten Artikel darüber sprechen, wenn jemand interessiert ist).

Nichts! Wie ist es unmöglich, Daten zu löschen und zu ändern ?!
- / Aerospike /: Unserer Meinung nach der schnellste NoSQL-Schlüsselwertspeicher. Es gibt eine Reihe von Minuspunkten, aber im Allgemeinen sind wir zufrieden. Es gibt sogar eine Vergleichstabelle für Aerospike auf ihrer Leistungsseite mit anderen Lösungen: [Wann wird die Aerospike NoSQL-Datenbank verwendet? Redis] (https://www.aerospike.com/when-to-use-aerospike-vs-redis/)
- / Redis /: Über "Radieschen", denke ich, macht es keinen Sinn, es separat zu erzählen. Paradoxerweise ist sein Hauptvorteil die Benutzerfreundlichkeit und das Einfädeln, wodurch Rennbedingungen vermieden werden, beispielsweise wenn mit gewöhnlichen Zählern gearbeitet wird.
- / Druid /: Wir verwenden für große Datenmengen in Arbeit mit RTB-Börsen. Tatsächlich spielt er größtenteils mit ClickHouse auf demselben Feld, aber in der Vergangenheit konnten wir noch nicht zu einem Instrument wechseln.

Ein solches Set mag überladen erscheinen, aber erstens ist Appodeal ein großes Konglomerat aus mehreren Entwicklungsteams und mehreren Projekten innerhalb eines. Und zweitens sind dies die harten Realitäten der Ad-Tech - wir sind nicht die einzigen, die einen mehrstöckigen Stack in einem Unternehmen verwenden.
Wie folgen Sie dem?
Da Datenströme groß sind, müssen sie in die Warteschlange gestellt werden, um sie zu verarbeiten. Als Warteschlange verwenden wir Kafka. Dies ist eine großartige zuverlässige Lösung in Scala, die uns noch nie gescheitert ist.
Die einzige Voraussetzung für den Benutzer in diesem Fall ist, dass er Zeit hat, die ständig wachsende Warteschlange schneller zu harken, als sie wächst. Eine einfache und offensichtliche Regel. Daher verwenden wir für diese Zwecke hauptsächlich GoLang. Dies negiert jedoch nicht die Tatsache, dass der RAM auf diesem Server reichlich vorhanden sein sollte.
Um all diese Wirtschaft zu überwachen, müssen Sie buchstäblich alles hintereinander überwachen und delegieren. Dafür verwenden wir:
- / NewRelic /: Eine bewährte Lösung, die sich perfekt in Ruby on Rails- und GoLang-Mikrodienste integrieren lässt. Das einzige Minus von NewRelic ist der Preis. Daher ist NewRelic nicht überall bei uns. Zum größten Teil versuchen wir, es durch unsere eigenen von Hand gesammelten Metriken zu ersetzen - wir setzen sie in Grafana ein.
- / Statsd + Grafana /: Eine gute Sache zum Sammeln Ihrer Metriken. Mit dem einzigen Minus, dass Sie alles selbst konfigurieren und die NewRelic-Funktionalität sofort „wiederholen“ müssen.
- / ElasticSearch + Fluentd + Kibana /: In den Protokollen setzen wir alles in eine Reihe. Von langsamen PostgreSQL-Abfragen bis zu einigen Rails-Systemnachrichten. Mit einer auf ElasticSearch basierenden Lösung wie Kibana können Sie alle Protokolle bequem an einem Ort sammeln und dann nach den erforderlichen Nachrichten suchen.
- / Airbrake /: Hierbei ist das Sammeln von Fehlern zusammen mit Message Stacktrace'ami obligatorisch. Wir ziehen derzeit mit Airbrake zu einer der kostenlosen Lösungen aus. Aus einem Grund wieder Preise.

Sie müssen verstehen, dass eine ordnungsgemäß konstruierte Überwachung Ihre Augen und Ohren sind. Blind unmöglich zu arbeiten. Sie müssen sehen, was zu einem bestimmten Zeitpunkt auf Ihren Servern geschieht. Die Stabilität und Zuverlässigkeit Ihres Produkts hängt daher weitgehend davon ab, wie kompetent Sie ein System zum Sammeln und Anzeigen von Metriken erstellen.
Apropos Zuverlässigkeit: Wir enthalten übrigens mehrere Staging-Server für die Vorab-Einführung und Überprüfung von Releases, die wir unter Last stabil halten und einen Teil des tatsächlichen Datenverkehrs dort duplizieren. Jede Woche synchronisieren wir Datenbanken zwischen Produktion und Staging. Dies gibt uns eine Art „Spiegel“, mit dem wir die Dinge testen können, die lokal nicht verifiziert werden können, und Probleme auf der Ebene der Lasttests identifizieren können.
Ist es wirklich so kompliziert?
Es stellt sich so heraus. Wie Elon Musk in seinem Buch schrieb: „Die besten Köpfe meiner Generation sind damit beschäftigt, Menschen dazu zu bringen, auf Anzeigen zu klicken“, sagte mir Jeff Hammerbacher, ein Facebook-Ingenieur. "Horror ..." Eine kurze Liste dessen, was Appodeal tut:
- Wir sind in zwei Dutzend Werbenetzwerke und Agenturen integriert. Im automatischen Modus registrieren wir Anwendungen in diesen Netzwerken und konfigurieren verschiedene Parameter, damit diese Netzwerke mit maximaler Leistung arbeiten. Nicht jedes Netzwerk verfügt über entsprechende APIs. Irgendwo muss man dies mit Robotern tun.
- Jedes Netzwerk zahlt den Benutzern Einnahmen für Impressionen, die empfangen, nach verschiedenen Parametern aufgeschlüsselt und verarbeitet werden müssen. Dies geschieht ohne Unterbrechung. Wieder irgendwo von Robotern.
- Um dem Nutzer ein maximales Einkommen zu bieten, „lassen“ wir die Gitter miteinander konkurrieren und bauen aus Werbeangeboten den sogenannten „Wasserfall“. Der Wasserfall basiert auf verschiedenen Indikatoren, z. B. eCPM (Durchschnittspreis pro 1000 Impressionen), die wir auf verschiedene Weise vorhersagen. Je höher das Werbeangebot im Wasserfall ist, desto höher prognostizieren wir den Preis dafür. Dieser Wasserfall wird so oft wie nötig auf dem Gerät angeboten. Wie Sie vielleicht erraten haben, interessiert eine Werbung, auf die niemand klickt und die nur jeden nervt, niemanden. Die Ausnahme ist nur die sogenannte. "Branded" -Bannerwerbung von Coca-Cola, Pepsi und anderen Unternehmensriesen, die es gewohnt sind, immer und überall über sich selbst zu sprechen.
- Ein Teil dieser Interaktion basiert auf dem sogenannten RTB-Protokoll (Real-Time Bidding):

In diesem Fall werden die sogenannten Bieter online bei einer Auktion miteinander gehandelt, um das Recht zu erhalten, ihre Anzeigen auf dem ausgewählten Gerät zu schalten. Ein sehr interessanter Punkt, der eines separaten Artikels würdig ist. Viele Börsen, wie z. B. Google AdExchange, legen einen engen Rahmen für die Serverantwortzeit fest (z. B. 50 ms), was ein Problem der Leistungssteigerung darstellt. Im Falle des Ungehorsams - eine Geldstrafe von Tausenden von Dollar. Genau das macht der in Scala geschriebene Kernel in Verbindung mit Druid.
Jeder Jäger möchte wissen, wo der Fasan sitzt, und unsere Kunden (wie wir) möchten wissen, wem die Anzeige wann und warum gezeigt wurde. Daher müssen wir alle vorhandenen Datenhaufen in die Warteschlange stellen (Kafka), schrittweise verarbeiten und zur OLAP-Datenbank (ClickHouse) hinzufügen. Viele Leute denken, dass PostgreSQL diese Aufgabe nicht schlechter bewältigen wird als alle „Hipster“ -Lösungen, aber das ist nicht so. PostgreSQL ist gut, aber die klassische Lösung zum Erstellen von Indizes für die Datenzugriffsgeschwindigkeit funktioniert nicht mehr, wenn die Anzahl der zu filternden und zu sortierenden Felder 10 überschreitet und sich die Menge der gespeicherten Daten 1 Milliarde Datensätzen nähert. Sie haben einfach nicht genug Speicher, um alle diese Indizes zu speichern, oder Sie haben Probleme beim Aktualisieren dieser Indizes. In jedem Fall können Sie nicht die gleiche Leistung erzielen wie spaltenorientierte Lösungen für analytische Abfragen.
Fazit
In diesem Artikel habe ich versucht, zumindest kurz zu beschreiben, was wir tun, wie wir Daten speichern und verarbeiten. Teilen Sie uns in den Kommentaren mit, welchen Stapel Sie verwenden, stellen Sie Fragen und fordern Sie neue Artikel an - wir teilen Ihnen gerne unsere Erfahrungen mit.