Dette er en artikkel fra Python-verdenen, men den er fortsatt relevant for hele programmeringsfeltet, selv om multitråding lar oss behandle forespørsler raskere, men det finnes også et tak, grønne (mikrotråd) tråder er løsningen.
Multitrådet programvareutvikling løser et stort antall problemer, spesielt for nettverkssentrerte applikasjoner som krever krevende ytelse for å svare raskt på brukerne. Dessverre er ikke multitråding nok til å løse storskalaFelles traséseksuelle problemer.
Å løse disse problemene krever endring av programmeringsmodeller, ved bruk av asynkrone hendelser og callback-baserte mekanismer. Hos Druva laget vi et python-bibliotek kalt Dhaga for å løse storskalaFelles trasé, mens programmeringsmodellen ikke krever betydelige endringer.
Programvareutviklere bor i énFelles traséverden. Tråder er førsteklasses borgere i dag, spesielt under utvikling, spesielt når applikasjonen din utfører intensive nettverksoperasjoner, som inSync-systemet (nettverkssikkerhetssynkroniseringsprodukt) som Druva. Multitråding hjelper flyten av programmeringskode for nettverksoperasjoner enkel og ordnet. Når applikasjonen vår trenger ytelsesforbedringer eller forbedringer, kan den forbedresElastisitet, kan vi øke antall tråder.
Men når det gjelder tusenvis av skalaerFelles traséforespørsler, tråder er ikke nok.
Vi fant at multithreading har følgende ulemper: 1. InSync-systemets klient må sikkerhetskopiere et stort antall filer til serveren via nettverks-RPC-kall. En typisk måte for utviklere å få ting til å gå raskere på, er å bruke tråder. Imidlertid øker ytelsen som multitråding gir kostnadene for minne og CPU; Utviklere må opprettholde en balanse mellom hastighet og trådantall.
2. Våre servere må håndtere mellom inSync-systemet og tusenvis av kunderFelles traséTilkoblinger og varsler. For å håndtere tilkoblinger effektivt bruker vi tråder for å håndtere forespørsler. Men det økende antallet inSync-systemkunder betyr også at vi må fortsette å øke antallet tråder, noe som bruker mye serverminne og CPU.
3. Webserveren vår må håndtere tusenvis av parallelle HTTP-forespørsler. Mesteparten av arbeidet ligger på nettverkssoklene som mottar og sender data og sender dem videre til backenden av inSync-systemet. Gjør at de fleste tråder venter på nettverksoperasjoner. Årsaken til C10K-problemet, når det er tusenvis av synkrone forespørsler til webserveren, er det ganske uskalerbart å generere en tråd for hver forespørsel (Scale).
Begrensninger ved asynkrone rammeverk Mange asynkrone rammeverk, inkludert Twisted, Tornado Tornado og asyncore, kan hjelpe utviklere med å bevege seg bort fra de populære måtene å bruke tråder på. Disse rammeverkene er avhengige av ikke-blokkerende sokler og callback-mekanismer (lignende Node.js). Hvis vi bruker disse rammeverkene som de er, må hoveddelene av vår Druva-kode refaktoreres. Det er ikke det vi ønsker å gjøre. Refaktorering av kode øker utviklings- og testsykluser, noe som hindrer oss i å oppfylle skaleringskravene våre. Siden flere deler av produktet må være massive, må hver av oss refaktorere dem – derav innsatsen med å doble eller trippele.
For å unngå å endre så mye kode, måtte vi gå bort fra å bruke det eksisterende rammeverket direkte. Heldigvis fant vi noen nyttige verktøy.
Fordi vi ønsker å kontrollere kjøringen av kode på nettverks-I/O, trenger vi en måte å dele en tråd inn i mikrotråder. Vi finnerGrønnunge。 Den gir en ikke-implisitt mikrotråd-planlegging kalt co-routine coroutine. Med andre ord. Det er nyttig når du vil kontrollere koden din som kjører. Du kan bygge mikrotråder for tilpassede tidsplaner fordi du kan kontrollere når greenlets gir pauser. Dette er perfekt for oss fordi det gir oss full kontroll over planleggingen av koden vår.
Tornado er et enkelt, ikke-blokkerende webserverrammeverk skrevet i Python designet for å håndtere tusenvis av asynkrone forespørsler. Vi bruker kjernekomponenten, IOLoop IOStream. IOLoop er en ikke-blokkerende socket I/O-hendelsessløyfe; Den bruker epoll (på Linux) eller køer (BSD og Mac OS X), ellers velg (på Windows) hvis de er tilgjengelige. IOStream tilbyr ikke-blokkerende sokler, som praktisk emballasje for lesing og skriving. Vi delegerer alle socket-operasjoner til Tornado og bruker deretter callbacks for å utløse kodeoperasjoner som fullføres (banq-merknad: veldig likt Node.js mekanismen).
Det er en god start, men vi trenger mer. Hvis vi bruker modulen ovenfor direkte i koden vår, må mye av RPC-koden vår endres, planlegge RPC gjennom greenlets, sørge for at greenlets ikke blokkeres (hvis greenlets blir tett, vil det tette hele tråden og alle de andre), håndtere callback-funksjoner fra tornado.
Vi trenger en abstraksjon for å håndtere og organisere greenlets for å unngå å tette dem med eksterne kall, og denne abstraksjonen kan være enormt skalerbar utover tråder. Denne abstraksjonen er Dhaga, som gjør det mulig å programmere applikasjonskodens flyt som en tradisjonell synkron sekvens, men utførelsen er asynkron.
Dhaga (fra hindi, som betyr tråd) er et utførelsesrammeverk for en lettvektstråd som vi abstraherer. Dhaga-klassen er avledet fra greenlets og bruker stack switching for å utføre flere kodeflyter i en enkelt operativsystemtråd. Tråder i ett operativsystem kjører flere dhagaser ved hjelp av samarbeidsplanlegging. Når en dhaga venter (hovedsakelig på at et RPC-kall skal komme tilbake), gir den kontroll til foreldrenivået (dvs. kjøringskonteksten til OS-tråden som opprettet den). Foreldrenivået planlegger deretter en ny dhaga for å være klar til å kjøre. RPC-kallet vil bli sendt til tornadoens webserver for å skrive Socketen asynkront, og deretter registrere en callback når den returnerer, og når denne RPC-en returnerer, vil den ventende dhagaen bli lagt til i kjørbare køen og deretter plukket opp av foreldretråden. (Banq-notat: likt node.js prinsippet)
Vi kan bruke Dhaga i stedet for tråder for operasjoner med høy forsinkelse, og vi bruker 512 dhagas i en enkelt tråd når antallet tråder øker utover en rimelig grense for gjennomstrømning.
|