{"id":36721,"date":"2019-10-31T22:13:20","date_gmt":"2019-10-31T19:13:20","guid":{"rendered":"https:\/\/prohoster.info\/blog\/kak-dark-razvertyvaet-kod-za-50-ms\/"},"modified":"2019-10-31T22:13:20","modified_gmt":"2019-10-31T19:13:20","slug":"kak-dark-razvertyvaet-kod-za-50-ms","status":"publish","type":"post","link":"https:\/\/prohoster.info\/de\/blog\/administrirovanie\/kak-dark-razvertyvaet-kod-za-50-ms","title":{"rendered":"Wie Dark Code in 50 ms bereitstellt","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><img decoding=\"async\" alt=\"Wie Dark Code in 50 ms bereitstellt\" src=\"\/wp-content\/uploads\/2019\/08\/c159a36eb52bf488f3a70ea511690366.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Je schneller der Entwicklungsprozess, desto schneller entwickelt sich das Technologieunternehmen.<\/p>\n<p><\/p>\n<p>Leider arbeiten moderne Anwendungen gegen uns \u2013 unsere Systeme m\u00fcssen in Echtzeit aktualisiert werden, ohne St\u00f6rungen oder Ausfallzeiten zu verursachen. Die Bereitstellung in solchen Systemen wird zu einer komplexen Aufgabe und erfordert komplexe Continuous Delivery-Pipelines, selbst in kleinen Teams.<\/p>\n<p><\/p>\n<p>Diese Pipelines haben typischerweise eine enge Anwendung, arbeiten langsam und sind unzuverl\u00e4ssig. Entwickler m\u00fcssen sie zun\u00e4chst manuell erstellen und dann verwalten, und Unternehmen stellen oft ganze DevOps-Teams daf\u00fcr ein.<\/p>\n<p><\/p>\n<p>Die Geschwindigkeit dieser Pipelines beeinflusst die Geschwindigkeit der Entwicklung. Bei den besten Teams dauert die Bereitstellung 5\u201310 Minuten, aber normalerweise dauert alles viel l\u00e4nger, und eine einzelne Bereitstellung ben\u00f6tigt mehrere Stunden.<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<p>Bei Dark dauert das 50 ms. <em>F\u00fcnfzig. Millisekunden<\/em>. Dark \u2014 <noindex><a rel=\"nofollow\" href=\"https:\/\/medium.com\/darklang\/the-design-of-dark-59f5d38e52d2\">ist eine umfassende L\u00f6sung mit Programmiersprache, Editor und Infrastruktur<\/a><\/noindex>, die speziell f\u00fcr Continuous Delivery entwickelt wurde, und alle Aspekte von Dark, einschlie\u00dflich der Sprache selbst, sind mit dem Ziel einer sicheren sofortigen Bereitstellung aufgebaut.<\/p>\n<p><\/p>\n<h3 id=\"pochemu-konveyery-nepreryvnoy-postavki-takie-medlennye\">Warum sind Continuous Delivery-Pipelines so langsam?<\/h3>\n<p><\/p>\n<p>Angenommen, wir haben eine Python-Webanwendung und wir haben bereits eine gro\u00dfartige und moderne Continuous Delivery-Pipeline erstellt. F\u00fcr einen Entwickler, der t\u00e4glich an diesem Projekt arbeitet, sieht die Bereitstellung einer geringf\u00fcgigen \u00c4nderung ungef\u00e4hr so aus:<\/p>\n<p><\/p>\n<h3 id=\"vnesenie-izmeneniy\">\u00c4nderungen vornehmen<\/h3>\n<p><\/p>\n<ul>\n<li>Neuen Branch in git erstellen<\/li>\n<li>\u00c4nderungen am Feature-Flag vornehmen<\/li>\n<li>Modultests zur \u00dcberpr\u00fcfung der \u00c4nderungen mit und ohne Feature-Flag<\/li>\n<\/ul>\n<p><\/p>\n<h3 id=\"pul-rekvest\">Pull-Request<\/h3>\n<p><\/p>\n<ul>\n<li>\u00c4nderungen committen<\/li>\n<li>\u00c4nderungen an das Remote-Repository auf github senden<\/li>\n<li>Pull-Request<\/li>\n<li>CI-Build wird automatisch im Hintergrund ausgef\u00fchrt<\/li>\n<li>Code-Review<\/li>\n<li>Weitere Reviews, falls erforderlich<\/li>\n<li>\u00c4nderungen mit dem Master-Branch mergen.<\/li>\n<\/ul>\n<p><\/p>\n<h3 id=\"ci-vypolnyaetsya-na-mastere\">CI wird am Master ausgef\u00fchrt<\/h3>\n<p><\/p>\n<ul>\n<li>Frontend-Abh\u00e4ngigkeiten \u00fcber npm installieren<\/li>\n<li>Ressourcen HTML+CSS+JS bauen und optimieren<\/li>\n<li>Frontend-modular und funktionale Tests durchf\u00fchren<\/li>\n<li>Python-Abh\u00e4ngigkeiten aus PyPI installieren<\/li>\n<li>Backend-modular und funktionale Tests durchf\u00fchren<\/li>\n<li>Integrationstests an beiden Enden<\/li>\n<li>Ressourcen des Frontends an das CDN senden<\/li>\n<li>Zusammenstellung des Containers f\u00fcr das Python-Programm<\/li>\n<li>Versand des Containers ins Registry<\/li>\n<li>Aktualisierung des Kubernetes-Manifests<\/li>\n<\/ul>\n<p><\/p>\n<h3 id=\"zamena-starogo-koda-novym\">Austausch von altem Code mit neuem<\/h3>\n<p><\/p>\n<ul>\n<li>Kubernetes startet mehrere Instanzen des neuen Containers<\/li>\n<li>Kubernetes wartet, bis die Instanzen betriebsbereit sind<\/li>\n<li>Kubernetes f\u00fcgt die Instanzen dem HTTP-Lastenausgleich hinzu<\/li>\n<li>Kubernetes wartet, bis die alten Instanzen nicht mehr verwendet werden<\/li>\n<li>Kubernetes stoppt die alten Instanzen<\/li>\n<li>Kubernetes wiederholt diese Vorg\u00e4nge, bis alle neuen Instanzen die alten ersetzt haben<\/li>\n<\/ul>\n<p><\/p>\n<h3 id=\"vklyuchenie-novogo-pereklyuchatelya-funkcii\">Aktivierung des neuen Funktionsschalters<\/h3>\n<p><\/p>\n<ul>\n<li>Neuer Code wird nur f\u00fcr sich selbst aktiviert, um sicherzustellen, dass alles in Ordnung ist<\/li>\n<li>Neuer Code wird f\u00fcr 10% der Benutzer aktiviert, betriebliche und gesch\u00e4ftliche Metriken werden verfolgt<\/li>\n<li>Neuer Code wird f\u00fcr 50% der Benutzer aktiviert, betriebliche und gesch\u00e4ftliche Metriken werden verfolgt<\/li>\n<li>Neuer Code wird f\u00fcr 100% der Benutzer aktiviert, betriebliche und gesch\u00e4ftliche Metriken werden verfolgt<\/li>\n<li>Schlie\u00dflich wiederholen Sie den gesamten Prozess, um den alten Code und den Schalter zu entfernen<\/li>\n<\/ul>\n<p><\/p>\n<p>Der Prozess h\u00e4ngt von den Tools, der Sprache und der Nutzung serviceorientierter Architekturen ab, sieht aber im Allgemeinen so aus. Ich habe Bereitstellungen mit Datenbankmigrationen nicht erw\u00e4hnt, da hierf\u00fcr eine gr\u00fcndliche Planung erforderlich ist, aber unten erfahren Sie, wie Dark damit umgeht.<\/p>\n<p><\/p>\n<p>Hier gibt es viele Komponenten, und viele davon k\u00f6nnen leicht verz\u00f6gern, fehlerhaft sein, zeitweilige Konflikte verursachen oder das Betriebssystem zum Absturz bringen.<\/p>\n<p><\/p>\n<p>Da diese Pipelines fast immer f\u00fcr einen speziellen Fall erstellt werden, ist es schwierig, sich auf sie zu verlassen. Viele haben Tage, an denen der Code nicht bereitgestellt werden kann, weil es Probleme mit dem Dockerfile gibt, eines der vielen Services ausgefallen ist oder der ben\u00f6tigte Spezialist im Urlaub ist.<\/p>\n<p><\/p>\n<p>Schlimmer noch, viele dieser Schritte leisten \u00fcberhaupt nichts N\u00fctzliches. Sie waren fr\u00fcher notwendig, als wir den Code direkt f\u00fcr die Benutzer bereitgestellt haben, aber jetzt haben wir Schalter f\u00fcr den neuen Code, und diese Prozesse haben sich getrennt. Letztendlich ist der Schritt, bei dem der Code bereitgestellt wird (alter wird durch neuen ersetzt), nun einfach ein zus\u00e4tzliches Risiko geworden.<\/p>\n<p><\/p>\n<p>Nat\u00fcrlich handelt es sich um eine sehr durchdachte Pipeline. Das Team, das sie erstellt hat, hat keine Zeit und kein Geld gescheut, um eine schnelle Bereitstellung zu gew\u00e4hrleisten. In der Regel sind Bereitstellungspipelines jedoch viel langsamer und unzuverl\u00e4ssiger.<\/p>\n<p><\/p>\n<h3 id=\"realizaciya-nepreryvnoy-postavki-v-dark\">Implementierung der kontinuierlichen Bereitstellung in Dark<\/h3>\n<p><\/p>\n<p>Die kontinuierliche Bereitstellung ist f\u00fcr Dark so wichtig, dass wir von Anfang an darauf abgezielt haben, die Zeit unter einer Sekunde zu halten. Wir haben alle Schritte der Pipeline \u00fcberpr\u00fcft, um alles \u00dcberfl\u00fcssige zu entfernen und den Rest zu optimieren. So haben wir die Schritte eliminiert.<\/p>\n<p><\/p>\n<blockquote><p>Jessie Frazelle (<noindex><a rel=\"nofollow\" href=\"https:\/\/twitter.com\/jessfraz\">Jessie Frazelle<\/a><\/noindex>) hat auf der Konferenz Future of Software Development in Reykjav\u00edk ein neues Wort, deployless (bereitstellungsfrei), erfunden.<\/p><\/blockquote>\n<p>Wir haben uns sofort entschieden, dass Dark auf dem Konzept \u00abdeployless\u00bb basieren wird (danke <noindex><a rel=\"nofollow\" href=\"https:\/\/twitter.com\/jessfraz\">Jessie Frazelle<\/a><\/noindex> f\u00fcr das Neologismus). Deployless bedeutet, dass jeder Code sofort bereitgestellt wird und bereit ist, in der Produktion verwendet zu werden. Nat\u00fcrlich \u00fcbersehen wir keinen fehlerhaften oder unvollst\u00e4ndigen Code (ich werde die Sicherheitsprinzipien unten beschreiben).<\/p>\n<p><\/p>\n<p>Bei der Pr\u00e4sentation von Dark wurden wir oft gefragt, wie wir es geschafft haben, die Bereitstellung so zu beschleunigen. Eine seltsame Frage. Die Leute denken wahrscheinlich, dass wir eine Supertechnologie erfunden haben, die den Code vergleicht, ihn kompiliert, in einen Container packt, eine virtuelle Maschine startet, den Container kalt startet und all das innerhalb von 50 ms. Das ist kaum m\u00f6glich. Aber wir haben eine spezielle Bereitstellungs-Engine entwickelt, die all das nicht ben\u00f6tigt.<\/p>\n<p><\/p>\n<p>Dark f\u00fchrt Interpretatoren in der Cloud aus. Angenommen, Sie schreiben Code in einer Funktion oder einem HTTP-Handler oder Event-Handler. Wir senden einen Diff an den abstrakten Syntaxbaum (die Code-Implementierung, die unser Editor und unsere Server intern verwenden) auf unsere Server und f\u00fchren diesen Code aus, wenn Anfragen eingehen. Daher sieht die Bereitstellung einfach aus wie ein bescheidener Datensatz in einer Datenbank \u2014 sofort und elementar. Die Bereitstellung erfolgt so schnell, weil sie das absolute Minimum umfasst.<\/p>\n<p><\/p>\n<p>In Zukunft planen wir, Dark zu einem Infrastruktur-Compiler zu machen, der die ideale Infrastruktur f\u00fcr hohe Leistung und Zuverl\u00e4ssigkeit von Anwendungen erstellt und startet. Die sofortige Bereitstellung wird nat\u00fcrlich nicht verschwinden.<\/p>\n<p><\/p>\n<h2 id=\"bezopasnoe-razvertyvanie\">Sichere Bereitstellung<\/h2>\n<p><\/p>\n<h3 id=\"strukturirovannyy-redaktor\">Strukturierter Editor<\/h3>\n<p><\/p>\n<p>Code in Dark wird im Dark-Editor geschrieben. Der strukturierte Editor erlaubt keine Syntaxfehler. Im Grunde gibt es in Dark nicht einmal einen Parser. Solange Sie Text eingeben, arbeiten wir direkt mit dem abstrakten Syntaxbaum (AST), wie <noindex><a rel=\"nofollow\" href=\"http:\/\/danmidwood.com\/content\/2014\/11\/21\/animated-paredit.html\">Paredit<\/a><\/noindex>, <noindex><a rel=\"nofollow\" href=\"https:\/\/ravichugh.github.io\/sketch-n-sketch\/\">Sketch-n-Sketch<\/a><\/noindex>, <noindex><a rel=\"nofollow\" href=\"https:\/\/gregoor.github.io\/tofu\/\">Tofu<\/a><\/noindex>, <noindex><a rel=\"nofollow\" href=\"https:\/\/www.facebook.com\/notes\/kent-beck\/prune-a-code-editor-that-is-not-a-text-editor\/1012061842160013\/\">Prune<\/a><\/noindex> und <noindex><a rel=\"nofollow\" href=\"https:\/\/www.jetbrains.com\/mps\/\">MPS<\/a><\/noindex>.<\/p>\n<p><\/p>\n<p>Jeder unvollst\u00e4ndige Code in Dark hat eine g\u00fcltige Ausf\u00fchrungssemantik, \u00e4hnlich wie <noindex><a rel=\"nofollow\" href=\"https:\/\/hazel.org\/\">typed holes in Hazel<\/a><\/noindex>Zum Beispiel, wenn Sie den Funktionsaufruf \u00e4ndern, speichern wir die alte Funktion, bis die neue einsatzbereit ist.<\/p>\n<p><\/p>\n<p>Jedes Programm in Dark hat seine eigene Bedeutung, daher st\u00f6rt unvollst\u00e4ndiger Code das Funktionieren des vollst\u00e4ndigen Codes nicht.<\/p>\n<p><\/p>\n<h3 id=\"rezhimy-redaktirovaniya\">Bearbeitungsmodi<\/h3>\n<p><\/p>\n<p>Sie schreiben Code in Dark in zwei F\u00e4llen. Erstens: Sie schreiben neuen Code und sind der einzige Benutzer. Zum Beispiel befindet es sich in REPL, und andere Benutzer haben niemals Zugriff darauf, oder es handelt sich um einen neuen HTTP-Routen, auf den Sie sich nirgendwo beziehen. Hier k\u00f6nnen Sie ohne Vorsichtsma\u00dfnahmen arbeiten, und so arbeiten Sie derzeit in Ihrer Entwicklungsumgebung.<\/p>\n<p><\/p>\n<p>Die zweite Situation: Der Code wird bereits verwendet. Wenn durch den Code Datenverkehr flie\u00dft (Funktionen, Ereignis-Handler, Datenbanken usw.), muss Vorsicht walten. Daher sperren wir den gesamten verwendeten Code und verlangen, dass strukturiertete Werkzeuge zum Bearbeiten verwendet werden. \u00dcber diese strukturierten Werkzeuge werde ich sp\u00e4ter sprechen: Funktionsumschalter f\u00fcr HTTP- und Ereignis-Handler, eine leistungsstarke Migrationplattform f\u00fcr Datenbanken und eine neue Versionierungsmethode f\u00fcr Funktionen und Typen.<\/p>\n<p><\/p>\n<h3 id=\"pereklyuchateli-funkciy\">Funktionsumschalter<\/h3>\n<p><\/p>\n<p>Eine der M\u00f6glichkeiten <noindex><a rel=\"nofollow\" href=\"https:\/\/medium.com\/darklang\/the-design-of-dark-59f5d38e52d2\">\u00fcberfl\u00fcssige Komplexit\u00e4t<\/a><\/noindex> in Dark zu beseitigen, besteht darin, mehrere Probleme mit einer einzigen L\u00f6sung zu l\u00f6sen. Funktionsumschalter f\u00fchren viele verschiedene Aufgaben aus: Ersetzen der lokalen Entwicklungsumgebung, Git-Branches, Bereitstellung von Code und nat\u00fcrlich die traditionelle langsame und kontrollierte Ver\u00f6ffentlichung neuen Codes.<\/p>\n<p><\/p>\n<p>Die Erstellung und Bereitstellung eines Funktionsumschalters erfolgt in unserem Editor in einem einzigen Schritt. Er schafft leeren Raum f\u00fcr neuen Code und bietet Steuerungselemente f\u00fcr den Zugriff auf alten und neuen Code sowie Schaltfl\u00e4chen und Befehle f\u00fcr einen schrittweisen \u00dcbergang zum neuen Code oder dessen Ausschluss.<\/p>\n<p><\/p>\n<p>Funktionsumschalter sind in die Sprache Dark integriert, und selbst unvollst\u00e4ndige Umschalter erf\u00fcllen ihren Zweck \u2013 wenn die Bedingung im Umschalter nicht erf\u00fcllt ist, wird der alte gesperrte Code ausgef\u00fchrt.<\/p>\n<p><\/p>\n<h3 id=\"sreda-razrabotki\">Entwicklungsumgebung<\/h3>\n<p><\/p>\n<p>Funktionsschalter ersetzen die lokale Entwicklungsumgebung. Heute haben Teams Schwierigkeiten, sicherzustellen, dass alle dieselben Versionen von Werkzeugen und Bibliotheken (Codeformatierungstools, Linter, Paketmanager, Compiler, Preprozessoren, Testwerkzeuge usw.) verwenden. Mit Dark m\u00fcssen keine Abh\u00e4ngigkeiten lokal installiert, lokale Docker-Installationen verwaltet oder andere Ma\u00dfnahmen ergriffen werden, um zumindest eine gewisse Gleichheit zwischen Entwicklungs- und Produktionsumgebung zu gew\u00e4hrleisten. <noindex><a rel=\"nofollow\" href=\"https:\/\/thenewstack.io\/honeycombs-charity-majors-go-ahead-test-in-production\/\">Angesichts der Tatsache, dass eine solche Gleichheit ohnehin unm\u00f6glich ist,<\/a><\/noindex>, werden wir nicht einmal so tun, als strebten wir danach.<\/p>\n<p><\/p>\n<p>Anstatt eine geklonte lokale Umgebung zu erstellen, schaffen Funktionsschalter in Dark eine neue Sandbox in der Produktion, die die Entwicklungsumgebung ersetzt. In Zukunft planen wir auch, Sandboxes f\u00fcr andere Teile der Anwendung (z. B. sofortige Datenbankklone) zu erstellen, obwohl dies derzeit nicht als besonders wichtig erscheint.<\/p>\n<p><\/p>\n<h3 id=\"vetki-i-razvertyvaniya\">Branches und Deployments<\/h3>\n<p><\/p>\n<p>Derzeit gibt es mehrere M\u00f6glichkeiten, neuen Code in die Systeme einzuf\u00fchren: Git-Branches, Deployment-Stufen und Funktionsschalter. Sie l\u00f6sen dasselbe Problem in verschiedenen Teilen des Workflows: Git \u2014 in den Phasen vor dem Deployment, Deployment \u2014 beim Wechsel von altem Code zu neuem, und Funktionsschalter \u2014 f\u00fcr die kontrollierte Einf\u00fchrung neuen Codes.<\/p>\n<p><\/p>\n<p>Der effektivste Weg sind Funktionsschalter (und gleichzeitig die einfachste L\u00f6sung zum Verstehen und Nutzen). Mit ihnen kann man auf die anderen beiden Methoden vollst\u00e4ndig verzichten. Besonders n\u00fctzlich ist es, das Deployment zu entfernen \u2013 wenn wir ohnehin Funktionsschalter verwenden, um Code zu aktivieren, dann schafft der Schritt, Server auf neuen Code umzuschalten, nur zus\u00e4tzliche Risiken.<\/p>\n<p><\/p>\n<p>Git ist schwierig zu nutzen, besonders f\u00fcr Anf\u00e4nger, was es stark einschr\u00e4nkt, aber es hat daf\u00fcr einige n\u00fctzliche Branches. Wir haben viele Nachteile von Git gegl\u00e4ttet. Dark wird in Echtzeit bearbeitet und bietet die M\u00f6glichkeit zur Zusammenarbeit im Stil von Google Docs, sodass man keinen Code senden muss und seltener Rebases und Merges durchf\u00fchren kann.<\/p>\n<p><\/p>\n<p>Funktionsschalter bilden die Grundlage f\u00fcr ein sicheres Deployment. Zusammen mit Instant Deployments erm\u00f6glichen sie ein schnelles Testen von Konzepten in kleinen, risikoarmen Fragmenten, anstatt eine gro\u00dfe \u00c4nderung anzuwenden, die das System zum Absturz bringen k\u00f6nnte.<\/p>\n<p><\/p>\n<h3 id=\"versionirovanie\">Versionskontrolle<\/h3>\n<p><\/p>\n<p>Zur \u00c4nderung von Funktionen und Typen verwenden wir die Versionskontrolle. Wenn Sie eine Funktion \u00e4ndern m\u00f6chten, erstellt Dark eine neue Version dieser Funktion. Dann k\u00f6nnen Sie diese Version \u00fcber den Schalter im HTTP-Handler oder in den Ereignissen aufrufen. (Wenn die Funktion tief im Aufrufgraphen liegt, wird w\u00e4hrenddessen f\u00fcr jede Funktion eine neue Version erstellt. Es mag \u00fcbertrieben erscheinen, aber Funktionen st\u00f6ren sich nicht, wenn Sie sie nicht verwenden; das werden Sie nicht einmal bemerken.)<\/p>\n<p><\/p>\n<p>Aus denselben Gr\u00fcnden versionieren wir auch Typen. \u00dcber unser System von Typen haben wir ausf\u00fchrlich berichtet <noindex><a rel=\"nofollow\" href=\"https:\/\/medium.com\/darklang\/real-problems-with-functional-languages-efe668c5264a\">in einem fr\u00fcheren Beitrag.<\/a><\/noindex>.<\/p>\n<p><\/p>\n<p>Dank der Versionskontrolle von Funktionen und Typen k\u00f6nnen Sie \u00c4nderungen schrittweise in die Anwendung einbringen. Sie k\u00f6nnen \u00fcberpr\u00fcfen, ob jeder einzelne Handler mit der neuen Version funktioniert, ohne sofort alle \u00c4nderungen in die Anwendungen einzubringen (aber wir haben Tools, um dies schnell zu tun, falls Sie es w\u00fcnschen).<\/p>\n<p><\/p>\n<p>Das ist viel sicherer als die vollst\u00e4ndige Bereitstellung aller \u00c4nderungen gleichzeitig, wie es derzeit der Fall ist.<\/p>\n<p><\/p>\n<h3 id=\"novye-versii-paketov-i-standartnaya-biblioteka\">Neue Versionen von Paketen und der Standardbibliothek<\/h3>\n<p><\/p>\n<p>Wenn Sie ein Paket in Dark aktualisieren, ersetzen wir nicht sofort die Verwendung jeder Funktion oder jedes Typs im gesamten Code. Das w\u00e4re unsicher. Der Code verwendet weiterhin die gleiche Version, die er verwendet hat, w\u00e4hrend Sie die Verwendung von Funktionen und Typen f\u00fcr jeden einzelnen Fall auf die neue Version mit Hilfe von Schaltern aktualisieren.<\/p>\n<p><\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/habrastorage.org\/webt\/rh\/t3\/4w\/rht34wyibolrgracbz88tnqqhg0.png\"><img decoding=\"async\" alt=\"Wie Dark Code in 50 ms bereitstellt\" src=\"\/wp-content\/uploads\/2019\/08\/54fdb566b4bcbc10e06e51c47a3820f0.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/a><\/noindex><br \/>\n<em>Screenshot eines Teils des automatischen Prozesses in Dark, der zwei Versionen der Funktion Dict::get zeigt. Dict::get_v0 gab den Typ Any zur\u00fcck (von dem wir uns distanzieren), w\u00e4hrend Dict::get_v1 den Typ Option zur\u00fcckgibt.<\/em><\/p>\n<p><\/p>\n<p>Wir bieten oft eine neue Funktion der Standardbibliothek an und schlie\u00dfen alte Versionen aus. Benutzer mit alten Versionen im Code behalten den Zugang zu ihnen, aber neue Benutzer k\u00f6nnen sie nicht erhalten. Wir planen, Tools bereitzustellen, um Benutzer von alten Versionen in einem Schritt auf neue zu migrieren, ebenfalls mit Funktionen-Schaltern.<\/p>\n<p><\/p>\n<p>Dark bietet auch die einzigartige M\u00f6glichkeit: Da wir Ihren Arbeitscode ausf\u00fchren, k\u00f6nnen wir neue Versionen selbst testen, indem wir die Ausgaben f\u00fcr neue und alte Anfragen vergleichen, um Sie \u00fcber \u00c4nderungen zu informieren. Schlie\u00dflich stellt ein Update der Pakete, das oft im Dunklen durchgef\u00fchrt wird (oder sorgf\u00e4ltige Sicherheitstests erfordert), ein wesentlich geringeres Risiko dar und kann automatisch erfolgen.<\/p>\n<p><\/p>\n<h3 id=\"novye-versii-dark\">Neue Versionen von Dark<\/h3>\n<p><\/p>\n<p>Der \u00dcbergang von Python 2 zu Python 3 zog sich \u00fcber ein ganzes Jahrzehnt und bleibt ein Problem. Da wir Dark f\u00fcr kontinuierliche Bereitstellung entwickeln, m\u00fcssen wir diese Sprach\u00e4nderungen ber\u00fccksichtigen.<\/p>\n<p><\/p>\n<p>Wenn wir kleine \u00c4nderungen an der Sprache vornehmen, erstellen wir eine neue Version von Dark. Der alte Code bleibt in der alten Version von Dark, w\u00e4hrend der neue Code in der neuen Version verwendet wird. F\u00fcr den \u00dcbergang zur neuen Version von Dark k\u00f6nnen Schalter oder Funktion-Versionen verwendet werden.<\/p>\n<p><\/p>\n<p>Dies ist besonders n\u00fctzlich, da Dark noch recht neu ist. Viele \u00c4nderungen in der Sprache oder Bibliothek k\u00f6nnten misslingen. Das schrittweise Versionieren der Sprache erm\u00f6glicht es uns, kleinere Aktualisierungen vorzunehmen, sodass wir uns nicht beeilen m\u00fcssen und viele Sprachentscheidungen aufschieben k\u00f6nnen, bis wir mehr Benutzer und damit mehr Informationen haben.<\/p>\n<p><\/p>\n<h3 id=\"migracii-baz-dannyh\">Datenbankmigrationen<\/h3>\n<p><\/p>\n<p>F\u00fcr eine sichere Migration von Datenbanken gibt es <noindex><a rel=\"nofollow\" href=\"http:\/\/www.brunton-spall.co.uk\/post\/2014\/05\/06\/database-migrations-done-right\/\">eine Standardformel<\/a><\/noindex>:<\/p>\n<p><\/p>\n<ul>\n<li>Den Code neu schreiben, um neue und alte Formate zu unterst\u00fctzen<\/li>\n<li>Alle Daten in das neue Format umwandeln<\/li>\n<li>Den alten Datenzugriff entfernen<\/li>\n<\/ul>\n<p><\/p>\n<p>Insgesamt zieht sich die Migration von Datenbanken und erfordert viele Ressourcen. Und wir haben veraltete Schemata, denn selbst einfache Aufgaben, wie das Umbenennen einer Tabelle oder einer Spalte, sind den Aufwand nicht wert.<\/p>\n<p><\/p>\n<p>Dark verf\u00fcgt \u00fcber eine effektive Plattform f\u00fcr die Migration von Datenbanken, die (so hoffen wir) den Prozess so stark vereinfacht, dass Sie keine Angst mehr davor haben werden. Alle Datenspeicher in Dark (Schl\u00fcssel-Wert-Paare oder permanente Hash-Tabellen) haben einen Typ. Um den Datenspeicher zu verschieben, weisen Sie ihm einfach einen neuen Typ und eine R\u00fcckfall- und Rollback-Funktion zu, um die Werte zwischen zwei Typen umzuwandeln.<\/p>\n<p><\/p>\n<p>Der Zugang zu Datenbanken in Dark erfolgt \u00fcber versionierte Variablenamen. Beispielsweise wird das Datenbank-Repository Users zun\u00e4chst Users-v0 genannt. Wenn eine neue Version mit einem anderen Typ erstellt wird, \u00e4ndert sich der Name zu Users-v1. Wenn Daten \u00fcber Users-v0 gespeichert sind und Sie darauf \u00fcber Users-v1 zugreifen, wird die Rollforward-Funktion angewendet. Wenn Daten \u00fcber Users-v1 gespeichert wurden und Sie darauf \u00fcber Users-v0 zugreifen, wird die Rollback-Funktion angewendet.<\/p>\n<p><\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/habrastorage.org\/webt\/ui\/sl\/wd\/uislwdrfrvact0d1ts5icnk-4ka.png\"><img decoding=\"async\" alt=\"Wie Dark Code in 50 ms bereitstellt\" src=\"\/wp-content\/uploads\/2019\/08\/35743ba246f327ca9e8b71f0069a3800.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/a><\/noindex><br \/>\n<em>Der Bildschirm zur Migration der Datenbank mit den Feldnamen der alten Datenbank, den Rollforward- und Rollback-Ausdr\u00fccken sowie Anweisungen zur Aktivierung der Migration.<\/em><\/p>\n<p><\/p>\n<p>Verwenden Sie Feature-Schalter, um Aufrufe von Users-v0 an die Version Users-v1 weiterzuleiten. Dies kann nach einem HTTP-Handler auf einmal gemacht werden, um die Risiken zu minimieren, und die Schalter funktionieren f\u00fcr einzelne Benutzer, sodass Sie \u00fcberpr\u00fcfen k\u00f6nnen, ob alles wie erwartet funktioniert. Wenn keine Benutzer mehr bei Users-v0 sind, konvertiert Dark alle verbleibenden Daten im Hintergrund vom alten Format in das neue. Sie werden das nicht einmal bemerken.<\/p>\n<p><\/p>\n<h3 id=\"testirovanie\">Tests<\/h3>\n<p><\/p>\n<p>Dark ist eine <noindex><a rel=\"nofollow\" href=\"https:\/\/medium.com\/darklang\/real-problems-with-functional-languages-efe668c5264a\">funktionale Programmiersprache mit statischer Typisierung<\/a><\/noindex> und unver\u00e4nderlichen Werten, weshalb die Testfl\u00e4che wesentlich kleiner ist als bei objektorientierten Sprachen mit dynamischer Typisierung. Aber man muss trotzdem testen.<br \/>\nIn Dark f\u00fchrt der Editor automatisch Modultests im Hintergrund f\u00fcr den bearbeitbaren Code aus und f\u00fchrt standardm\u00e4\u00dfig diese Tests f\u00fcr alle Feature-Schalter durch. In Zukunft m\u00f6chten wir durch statische Typen automatisch Fuzzing des Codes durchf\u00fchren, um Bugs zu finden.<\/p>\n<p><\/p>\n<p>Dar\u00fcber hinaus f\u00fchrt Dark Ihre Infrastruktur in der Produktion aus, was neue M\u00f6glichkeiten er\u00f6ffnet. Wir speichern HTTP-Anfragen automatisch in der Dark-Infrastruktur (derzeit speichern wir alle Anfragen, m\u00f6chten aber sp\u00e4ter zu einer Auswahl \u00fcbergehen). Wir testen neuen Code anhand dieser Anfragen und f\u00fchren Modultests durch, und falls gew\u00fcnscht, k\u00f6nnen Sie interessante Anfragen leicht in Modultests umwandeln.<\/p>\n<p><\/p>\n<h3 id=\"ot-chego-my-izbavilis\">Wovon wir uns verabschiedet haben<\/h3>\n<p><\/p>\n<p>Da wir kein Deployment haben, sondern Feature-Schalter, bleiben etwa 60 % der Deployment-Pipeline au\u00dfen vor. Wir ben\u00f6tigen keine Git-Branches oder Pull-Requests, keine Erstellung von Backend-Ressourcen und Containern, kein Versand von Ressourcen und Containern in Registries oder Deployment-Schritte in Kubernetes.<\/p>\n<p><\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/habrastorage.org\/webt\/gc\/9e\/g-\/gc9eg-szouq0dtrxxr8jd6c6dyo.jpeg\"><img decoding=\"async\" alt=\"Wie Dark Code in 50 ms bereitstellt\" src=\"\/wp-content\/uploads\/2019\/08\/d584b13a1f91e9eef1e2e40c25e90052.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/a><\/noindex><br \/>\n<em>Vergleich der Standard-Pipeline f\u00fcr kontinuierliche Lieferung (links) und der Dunkel-Pipeline (rechts). In der Dunkel-Pipeline besteht die Lieferung aus 6 Schritten und einem Zyklus, w\u00e4hrend die traditionelle Version 35 Schritte und 3 Zyklen umfasst.<\/em><\/p>\n<p><\/p>\n<p>In der Dunkel-Pipeline gibt es insgesamt 6 Schritte und 1 Zyklus (Schritte, die mehrmals wiederholt werden), w\u00e4hrend die moderne Pipeline f\u00fcr kontinuierliche Lieferung aus 35 Schritten und 3 Zyklen besteht. In Dunkel werden die Tests automatisch gestartet, und Sie sehen das sogar nicht; Abh\u00e4ngigkeiten werden automatisch installiert; alles, was mit Git oder Github zu tun hat, ist nicht mehr notwendig; das Erstellen, Testen und Versenden von Docker-Containern ist nicht erforderlich; das Bereitstellen in Kubernetes ist nicht mehr n\u00f6tig.<\/p>\n<p><\/p>\n<p>Selbst die verbleibenden Schritte in Dunkel sind einfacher geworden. Da Funktionstasten mit einer einzigen Aktion gesteuert werden k\u00f6nnen, muss man nicht ein zweites Mal die gesamte Bereitstellungspipeline durchlaufen, um alten Code zu entfernen.<\/p>\n<p><\/p>\n<p>Wir haben unser Bestes getan, um die Bereitstellung von Code zu vereinfachen, indem wir Zeit und Risiken der kontinuierlichen Lieferung reduziert haben. Au\u00dferdem haben wir die Aktualisierung von Paketen, Datenbankmigrationen, Tests, Versionsverwaltung, Abh\u00e4ngigkeitsmanagement, Konsistenz zwischen Entwicklungs- und Produktionsumgebung und schnelle sowie sichere Version-Upgrades des Codes erheblich vereinfacht.<\/p>\n<p><\/p>\n<p>Ich beantworte Fragen dazu auf <noindex><a rel=\"nofollow\" href=\"https:\/\/news.ycombinator.com\/item?id=20394166\">HackerNews<\/a><\/noindex>.<\/p>\n<p><\/p>\n<p>Um mehr \u00fcber die Dunkel-Pipeline zu erfahren, lesen Sie <noindex><a rel=\"nofollow\" href=\"https:\/\/medium.com\/darklang\/the-design-of-dark-59f5d38e52d2\">den Artikel \u00fcber Dunkel<\/a><\/noindex>, <noindex><a rel=\"nofollow\" href=\"https:\/\/twitter.com\/darklang?source=post_page---------------------------\">folgen Sie uns auf Twitter<\/a><\/noindex> (oder auf <noindex><a rel=\"nofollow\" href=\"https:\/\/twitter.com\/paulbiggar?source=post_page---------------------------\">mich<\/a><\/noindex>) oder <noindex><a rel=\"nofollow\" href=\"https:\/\/darklang.com\/subscribe?source=post_page---------------------------\">melden Sie sich f\u00fcr die Beta-Version an und erhalten Sie Benachrichtigungen \u00fcber die n\u00e4chsten Beitr\u00e4ge<\/a><\/noindex>. Wenn Sie im September zur StrangeLoop fahren, <noindex><a rel=\"nofollow\" href=\"https:\/\/darklang.com\/launch\">kommen Sie zu unserem Launch<\/a><\/noindex>.<\/p>\n<p>Quelle: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/southbridge\/blog\/462027\/\">habr.com<\/a><\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u0427\u0435\u043c \u0431\u044b\u0441\u0442\u0440\u0435\u0435 \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438, \u0442\u0435\u043c \u0431\u044b\u0441\u0442\u0440\u0435\u0435 \u0440\u0430\u0437\u0432\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u0430\u044f \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u044f. \u041a \u0441\u043e\u0436\u0430\u043b\u0435\u043d\u0438\u044e, \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442 \u043f\u0440\u043e\u0442\u0438\u0432 \u043d\u0430\u0441 \u2014 \u043d\u0430\u0448\u0438 \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0442\u044c\u0441\u044f \u0432 \u0440\u0435\u0436\u0438\u043c\u0435 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0438 \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u043d\u0438\u043a\u043e\u043c\u0443 \u043d\u0435 \u043c\u0435\u0448\u0430\u0442\u044c \u0438 \u043d\u0435 \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u0442\u044c \u043a \u043f\u0440\u043e\u0441\u0442\u043e\u044f\u043c \u0438 \u043f\u0435\u0440\u0435\u0440\u044b\u0432\u0430\u043c. \u0420\u0430\u0437\u0432\u0435\u0440\u0442\u044b\u0432\u0430\u043d\u0438\u0435 \u0432 \u0442\u0430\u043a\u0438\u0445 \u0441\u0438\u0441\u0442\u0435\u043c\u0430\u0445 \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f \u0441\u043b\u043e\u0436\u043d\u043e\u0439 \u0437\u0430\u0434\u0430\u0447\u0435\u0439 \u0438 \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0441\u043b\u043e\u0436\u043d\u044b\u0445 \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d\u043e\u0432 \u043d\u0435\u043f\u0440\u0435\u0440\u044b\u0432\u043d\u043e\u0439 \u043f\u043e\u0441\u0442\u0430\u0432\u043a\u0438 \u0434\u0430\u0436\u0435 \u0432 \u043c\u0430\u043b\u0435\u043d\u044c\u043a\u0438\u0445 \u043a\u043e\u043c\u0430\u043d\u0434\u0430\u0445. [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":27506,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-36721","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.1.1 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u0427\u0435\u043c \u0431\u044b\u0441\u0442\u0440\u0435\u0435 \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438, \u0442\u0435\u043c \u0431\u044b\u0441\u0442\u0440\u0435\u0435.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/de\/blog\/administrirovanie\/kak-dark-razvertyvaet-kod-za-50-ms\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.1.1\" \/>\n\t\t<meta property=\"og:locale\" content=\"de_DE\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47\u041a\u0430\u043a Dark \u0440\u0430\u0437\u0432\u0435\u0440\u0442\u044b\u0432\u0430\u0435\u0442 \u043a\u043e\u0434 \u0437\u0430 50 \u043c\u0441 | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u0427\u0435\u043c \u0431\u044b\u0441\u0442\u0440\u0435\u0435 \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438, \u0442\u0435\u043c \u0431\u044b\u0441\u0442\u0440\u0435\u0435.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/de\/blog\/administrirovanie\/kak-dark-razvertyvaet-kod-za-50-ms\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2019-10-31T19:13:20+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2019-10-31T19:13:20+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47Wie Dunkel Code in 50 ms bereitstellt | ProHoster","description":"Je schneller der Entwicklungsprozess, desto schneller.","canonical_url":"https:\/\/prohoster.info\/de\/blog\/administrirovanie\/kak-dark-razvertyvaet-kod-za-50-ms","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"de_DE","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47\u041a\u0430\u043a Dark \u0440\u0430\u0437\u0432\u0435\u0440\u0442\u044b\u0432\u0430\u0435\u0442 \u043a\u043e\u0434 \u0437\u0430 50 \u043c\u0441 | ProHoster","og:description":"\u0427\u0435\u043c \u0431\u044b\u0441\u0442\u0440\u0435\u0435 \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438, \u0442\u0435\u043c \u0431\u044b\u0441\u0442\u0440\u0435\u0435.","og:url":"https:\/\/prohoster.info\/de\/blog\/administrirovanie\/kak-dark-razvertyvaet-kod-za-50-ms","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2019-10-31T19:13:20+00:00","article:modified_time":"2019-10-31T19:13:20+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"36721","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":"2026-01-22 04:34:22","breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-03-01 01:40:22","updated":"2026-01-22 04:34:22","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/posts\/36721","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/comments?post=36721"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/posts\/36721\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/media\/27506"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/media?parent=36721"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/categories?post=36721"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/tags?post=36721"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}