Miljon taotlust sekundis Pythoniga

Kas Pythoniga on võimalik tabada miljon taotlust sekundis? Ilmselt alles hiljuti.

Paljud ettevõtted rändavad Pythoni juurest ja teistest programmeerimiskeeltest eemale, et nad saaksid oma toimivust parandada ja serverihindu kokku hoida, kuid tegelikult pole seda vaja. Python võib olla selle töö jaoks õige tööriist.

Pythoni kogukond teeb viimasel ajal palju esinemist. CPython 3.6 suurendas tõlkide üldist jõudlust uue sõnastiku juurutamisega. CPython 3.7 saab olema veelgi kiirem tänu kiirema kõnekonventsiooni ja sõnastikuotsingu vahemälude kasutuselevõtule.

Numbrite purustamise ülesannete jaoks võite kasutada PyPyt koos selle õigeaegse koodi kompileerimisega. Võite käivitada ka NumPy testikomplekti, mis on nüüd C-laiendustega üldist ühilduvust parandanud. Selle aasta lõpus peaks PyPy vastama Python 3.5 nõuetele.

Kõik see suurepärane töö inspireeris mind uuendama ühes valdkonnas, kus Pythoni kasutatakse laialdaselt: veebi- ja mikroteenuste arendamisel.

Sisestage Japronto!

Japronto on uhiuus mikrotraamistik, mis on kohandatud teie mikroteenuste vajadustele. Selle põhieesmärkide hulka kuulub kiire , skaleeritav ja kerge olek . See võimaldab tänu asynciole teha nii sünkroonseid kui ka asünkroonseid programme . Ja see on häbematult kiire . Isegi kiiremini kui NodeJS ja Go.

Viga : Nagu kasutaja @heppu märgib, võib Go stdlib HTTP-server olla 12% kiirem, kui see graafik hoolikamalt kirjutades näitab. Go jaoks on olemas ka vinge fasthttp- server, mis on selles konkreetses võrdlusuuringus ilmselt ainult 18% aeglasem kui Japronto. Vinge! Lisateavet leiate artiklitest //github.com/squeaky-pl/japronto/pull/12 ja //github.com/squeaky-pl/japronto/pull/14.

Samuti näeme, et Meinheldi WSGI-server on peaaegu NodeJSi ja Go-ga võrdväärne. Hoolimata oma olemuselt blokeerivast kujundusest, on see suurepärane esineja võrreldes eelmise nelja, mis on asünkroonsed Pythoni lahendused. Nii et ärge kunagi usaldage kedagi, kes ütleb, et asünkroonsed süsteemid on alati kiiremad. Need on peaaegu alati samaaegsed, kuid selles on palju muud kui lihtsalt see.

Selle mikro-võrdlusuuringu tegin „Hello world! rakendus, kuid see näitab paljude lahenduste puhul selgelt serveriraamistiku üldkulusid.

Need tulemused saadi AWS c4.2xlarge eksemplaril, millel oli 8 VCPU-d, mis käivitati São Paulo piirkonnas vaikimisi jagatud üürimise ning HVM-i virtualiseerimise ja magnetmäluga. Masin töötas Ubuntu 16.04.1 LTS (Xenial Xerus) koos Linuxi 4.4.0–53-üldise x86_64-tuumaga. Operatsioonisüsteem teatas Xeon® CPU E5–2666 v3 @ 2.90GHz protsessorist. Kasutasin Python 3.6, mille koostasin värskelt selle lähtekoodist.

Aususe huvides olid kõik võistlejad (ka Go) ühe töötaja protsessis. Servereid testiti koormuse abil, kasutades ühte niiti, 100 ühendust ja 24 samaaegset (torujuhtmelist) päringut ühenduse kohta (2400 päringu kumulatiivne paralleelsus).

HTTP-ga torustik on siin ülioluline, kuna see on üks optimeeringutest, mida Japronto taotluste täitmisel arvesse võtab.

Enamik servereid täidab torujuhtmete klientide taotlusi samal viisil, nagu seda teeksid mittetorustavate klientide kliendid. Nad ei püüa seda optimeerida. (Tegelikult loobuvad Sanic ja Meinheld vaikselt ka torujuhtmete klientide päringutest, mis on HTTP 1.1 protokolli rikkumine.)

Lihtsamalt öeldes on pipelining tehnika, mille puhul klient ei pea ootama vastust, enne kui ta saab järgmise TCP-ühenduse kaudu päringuid saata. Suhtluse terviklikkuse tagamiseks saadab server tagasi mitu vastust samas järjekorras.

Optimeerimiste üksikasjad

Kui klient ühendab palju väikeseid GET-päringuid, on suur tõenäosus, et need saabuvad serveri poolel ühes TCP-paketis (tänu Nagle algoritmile), seejärel loetakse neid tagasi ühe süsteemikõnega .

Süsteemikõne tegemine ja andmete teisaldamine tuumaruumist kasutajaruumi on väga kulukas operatsioon võrreldes näiteks protsessori ruumi mälu teisaldamisega. Sellepärast on oluline teha võimalikult vähe süsteemikõnesid (kuid mitte vähem).

Kui Japronto saab andmeid ja edukalt korrastab mitmeid taotlusi välja, ta püüab täita kõik taotlused võimalikult kiiresti, liimi vastuseid tagasi õiges järjekorras, siis kirjuta tagasi üks süsteem kõne . Tegelikult võib kern aidata liimimisosa tänu IO-süsteemi kõnedele hajutada / koguda, mida Japronto veel ei kasuta.

Pange tähele, et see pole alati võimalik, kuna mõned taotlused võivad võtta liiga kaua aega ja nende ootamine suurendaks tarbetult latentsust.

Heuristika häälestamisel olge ettevaatlik ning arvestage süsteemikõnede maksumuse ja eeldatava taotluste täitmise ajaga.

Lisaks edasilükatud klientide kirjutamise viivitamisele on koodis ka mitmeid muid tehnikaid.

Japronto on kirjutatud peaaegu täielikult kirjas C. Parseri, protokolli, ühenduse koristaja, ruuteri, taotluse ja vastuse objektid on kirjutatud C laienditena.

Japronto üritab kõvasti oma sisestruktuuride Pythoni kolleegide loomist edasi lükata, kuni seda selgesõnaliselt küsitakse. Näiteks ei loo päisesõnastikku enne, kui seda vaates nõutakse. Kõik märgistuspiirid on juba enne tähistatud, kuid päisevõtmete normaliseerimine ja mitme str-objekti loomine toimub nende esmakordsel kasutamisel.

Japronto tugineb olekurea, päiste ja tükeldatud HTTP-sõnumi keha parsimisel suurepärasele picohttpparser C teegile. Picohttpparser kasutab otseselt tekstitöötlusjuhiseid, mis on leitud tänapäevastest SSE4.2 laiendusega protsessoritest (peaaegu kõigil 10-aastastel x86_64 protsessoritel on see olemas), et HTTP-märkide piirid kiiresti kokku sobitada. I / O-ga tegeleb super vinge uvloop, mis ise on libuvit ümbritsev ümbris. Kõige madalamal tasemel on see süsteem epoll-süsteemi kõnele, mis annab asünkroonseid teateid lugemis- ja kirjutamisvalmiduse kohta.

Python on prügikogutud keel, seetõttu tuleb suure jõudlusega süsteemide väljatöötamisel olla ettevaatlik, et mitte asjatult suurendada survet prügikogujale. Japronto sisekujundus püüab vältida võrdlustsükleid ja teha nii vähe eraldisi / jaotusi kui vaja. Ta teeb seda, jaotades mõned objektid eelnevalt nn areenidele. Samuti proovitakse Pythoni objekte tulevaste taotluste jaoks uuesti kasutada, kui neile enam ei viidata, selle asemel et neid ära visata.

Kõik eraldised tehakse 4KB kordajatena. Sisemised struktuurid on hoolikalt paigutatud, nii et sageli koos kasutatavad andmed oleksid mälus piisavalt lähedal, minimeerides vahemälu kasutamata jätmise võimalust.

Japronto üritab puhvrite vahel asjatult kopeerida ja teeb paljud toimingud kohapeal. Näiteks dekodeerib see protsendi enne ruuteri protsessis sobitamist.

Avatud lähtekoodiga kaastöötajad, saaksin kasutada teie abi.

Olen Japronto kallal töötanud pidevalt viimased 3 kuud - sageli nii nädalavahetustel kui ka tavalistel tööpäevadel. See oli võimalik ainult tänu sellele, et tegin oma tavapärasest programmeerija tööst pausi ja panustasin kõik oma jõupingutused sellesse projekti.

Ma arvan, et on aeg jagada oma töö vilju kogukonnaga.

Praegu rakendab Japronto üsna tugevat funktsioonide komplekti:

  • HTTP 1.x juurutamine koos tükeldatud üleslaadimiste toega
  • HTTP-torujuhtmete täielik tugi
  • Hoidke elus ühendusi seadistatava niidumasinaga
  • Sünkroonsete ja asünkroonsete vaadete tugi
  • Kahvlil põhinev kapten-mitme töötaja mudel
  • Koodide uuesti laadimise tugi muudatuste korral
  • Lihtne marsruutimine

Järgmisena tahaksin uurida veebipesasid ja voogesitada HTTP-vastuseid asünkroonselt.

Dokumenteerimise ja testimise osas tuleb teha palju tööd. Kui olete huvitatud aitamisest, võtke minuga otse Twitteris ühendust. Siin on Japronto GitHubi projektihoidla.

Samuti, kui teie ettevõte otsib Pythoni arendajat, kes on jõudlusfriik ja teeb ka DevOpsi, olen sellest valmis kuulma. Kaalun positsioone kogu maailmas.

Lõppsõnad

Kõik tehnikad, mida ma siin maininud olen, pole tegelikult Pythonile omased. Tõenäoliselt saab neid kasutada teistes keeltes, nagu Ruby, JavaScript või isegi PHP. Ka mina oleksin huvitatud sellise töö tegemisest, kuid seda ei juhtu kahjuks enne, kui keegi seda rahastada saab.

Tahaksin tänada Pythoni kogukonda nende pideva investeeringu eest jõudlustehnikasse. Nimelt Victor Stinner @VictorStinner, INADA Naoki @methane ja Yury Selivanov @ 1st1 ning kogu PyPy meeskond.

Pythoni armastuse pärast.