Apgūstiet Python `asyncio` zema līmeņa tīklošanu. Šis dziļais ieskats aptver Transportus un Protokolus ar praktiskiem piemēriem augstas veiktspējas, pielāgotu tīkla lietotņu izveidei.
Demistificējam Python `asyncio` Transportu: Dziļš ieskats zema līmeņa tīklošanā
Mūsdienu Python pasaulē asyncio
ir kļuvis par augstas veiktspējas tīkla programmēšanas stūrakmeni. Izstrādātāji bieži sāk ar tā skaistajiem augsta līmeņa API, izmantojot async
un await
ar tādām bibliotēkām kā aiohttp
vai FastAPI
, lai ar ievērojamu vieglumu izveidotu atsaucīgas lietojumprogrammas. StreamReader
un StreamWriter
objekti, ko nodrošina tādas funkcijas kā asyncio.open_connection()
, piedāvā brīnišķīgi vienkāršu, secīgu veidu, kā apstrādāt tīkla I/O. Bet ko darīt, ja abstrakcijas nepietiek? Ko darīt, ja jums jāievieš sarežģīts, stāvokļa pārvaldošs vai nestandarta tīkla protokols? Ko darīt, ja jums jāizspiež katra pēdējā veiktspējas lāse, tieši kontrolējot pamata savienojumu? Šeit slēpjas asyncio
tīklošanas iespēju patiesais pamats: zema līmeņa Transporta un Protokola API. Lai gan tas sākotnēji var šķist biedējoši, saprotot šo jaudīgo duetu, jūs atverat jaunu kontroles un elastības līmeni, ļaujot jums izveidot praktiski jebkuru tīkla lietojumprogrammu, kādu vien varat iedomāties. Šis visaptverošais ceļvedis atklās abstrakcijas slāņus, izpētīs Transportu un Protokolu simbiotiskās attiecības un iepazīstinās jūs ar praktiskiem piemēriem, lai jūs varētu apgūt zema līmeņa asinhrono tīklošanu Pythonā.
asyncio
tīklošanas divas sejas: Augsta līmeņa pret zemu līmeni
Pirms iedziļināsimies zema līmeņa API, ir svarīgi saprast to vietu asyncio
ekosistēmā. asyncio
gudri nodrošina divus atšķirīgus tīkla sakaru slāņus, katru pielāgotu dažādiem lietošanas gadījumiem.
Augsta līmeņa API: Plūsmas (Streams)
Augsta līmeņa API, ko parasti dēvē par "Plūsmām", ir tas, ar ko lielākā daļa izstrādātāju saskaras vispirms. Kad izmantojat asyncio.open_connection()
vai asyncio.start_server()
, jūs saņemat StreamReader
un StreamWriter
objektus. Šī API ir paredzēta vienkāršībai un lietošanas ērtumam.
- Imperatīvais stils: Tas ļauj jums rakstīt kodu, kas izskatās sekvenčuāls. Jūs
await reader.read(100)
, lai iegūtu 100 baitus, pēc tamwriter.write(data)
, lai nosūtītu atbildi. Šisasync/await
paraugs ir intuitīvs un viegli saprotams. - Ērti palīgrīki: Tas nodrošina metodes, piemēram,
readuntil(separator)
unreadexactly(n)
, kas apstrādā bieži sastopamus ietīšanas uzdevumus, atbrīvojot jūs no manuālas buferu pārvaldības. - Ideāli lietošanas gadījumi: Ideāli piemērots vienkāršiem pieprasījumu-atbildes protokoliem (piemēram, pamata HTTP klientam), līniju balstītiem protokoliem (piemēram, Redis vai SMTP) vai jebkurai situācijai, kurā sakari notiek paredzamā, lineārā plūsmā.
Tomēr šī vienkāršība nāk ar kompromisu. Plūsmu balstīta pieeja var būt mazāk efektīva ļoti konkrētiem, notikumu vadītiem protokoliem, kur nepamatoti ziņojumi var pienākt jebkurā laikā. Sekvenčuālais await
modelis var apgrūtināt vienlaicīgu lasīšanu un rakstīšanu vai sarežģītu savienojuma stāvokļu pārvaldību.
Zema līmeņa API: Transporti un Protokoli
Šis ir pamata slānis, uz kura faktiski ir balstīta augsta līmeņa Plūsmu API. Zema līmeņa API izmanto dizaina paraugu, kas balstīts uz diviem atšķirīgiem komponentiem: Transportiem un Protokoliem.
- Notikumu vadīts stils: Tā vietā, lai jūs izsauktu funkciju datu iegūšanai,
asyncio
izsauc metodes jūsu objektā, kad notiek notikumi (piemēram, tiek izveidots savienojums, tiek saņemti dati). Šī ir uz atzvanu balstīta pieeja. - Uzdevumu atdalīšana: Tas skaidri atdala "ko" no "kā". Protokols nosaka, ko darīt ar datiem (jūsu lietojumprogrammas loģika), savukārt Transports apstrādā, kā dati tiek sūtīti un saņemti tīklā (I/O mehānisms).
- Maksimāla kontrole: Šī API sniedz jums smalku kontroli pār buferēšanu, plūsmas kontroli (pretspiedienu) un savienojuma dzīves ciklu.
- Ideāli lietošanas gadījumi: Būtiski pielāgotu bināro vai teksta protokolu ieviešanai, augstas veiktspējas serveru izveidei, kas apkalpo tūkstošiem pastāvīgu savienojumu, vai tīkla sistēmu un bibliotēku izstrādei.
Padomājiet par to šādi: Plūsmu API ir kā ēdienu komplektu pasūtīšana. Jūs saņemat iepriekš sadalītas sastāvdaļas un vienkāršu recepti. Transporta un Protokola API ir kā pavāram profesionālā virtuvē ar svaigām sastāvdaļām un pilnīgu kontroli pār katru procesa posmu. Abi var radīt lielisku ēdienu, bet pēdējais piedāvā bezgalīgu radošumu un kontroli.
Galvenie komponenti: Detalizētāks skats uz Transportiem un Protokoliem
Zema līmeņa API jauda rodas no elegantās mijiedarbības starp Protokolu un Transportu. Tie ir atšķirīgi, bet neatdalāmi partneri jebkurā zema līmeņa asyncio
tīkla lietojumprogrammā.
Protokols: Jūsu lietojumprogrammas smadzenes
Protokols ir klase, ko jūs rakstāt. Tā mantojas no asyncio.Protocol
(vai kādas no tās variācijām) un satur vienas tīkla savienojuma stāvokli un loģiku. Jūs paši neinstancējat šo klasi; jūs to nodrošat asyncio
(piemēram, loop.create_server
), un asyncio
katram jaunam klienta savienojumam izveido jaunu jūsu protokola instanci.
Jūsu protokola klase ir definēta ar virkni notikumu apstrādātāju metožu, kuras notikumu cikls izsauc dažādos savienojuma dzīves cikla punktos. Svarīgākās ir:
connection_made(self, transport)
Izsaukta precīzi vienu reizi, kad ir veiksmīgi izveidots jauns savienojums. Šī ir jūsu ieejas punkts. Tas ir brīdis, kad jūs saņemat transport
objektu, kas attēlo savienojumu. Jums vienmēr jāsaglabā atsauce uz to, parasti kā self.transport
. Tā ir ideāla vieta, lai veiktu jebkuru inicializāciju, kas attiecas uz savienojumu, piemēram, buferu iestatīšanu vai attālinātās adreses reģistrēšanu.
data_received(self, data)
Jūsu protokola sirds. Šī metode tiek izsaukta ikreiz, kad no savienojuma otra gala tiek saņemti jauni dati. data
arguments ir bytes
objekts. Ir svarīgi atcerēties, ka TCP ir plūsmas protokols, nevis ziņojumu protokols. Viens jūsu lietojumprogrammas loģiskais ziņojums var tikt sadalīts vairākos data_received
izsaukumos, vai arī vairāki mazi ziņojumi var tikt apvienoti vienā izsaukumā. Jūsu kodam ir jāapstrādā šī buferēšana un parsēšana.
connection_lost(self, exc)
Izsaukta, kad savienojums ir aizvērts. Tas var notikt vairāku iemeslu dēļ. Ja savienojums ir aizvērts tīri (piemēram, otra puse to aizver, vai jūs izsaucat transport.close()
), exc
būs None
. Ja savienojums ir aizvērts kļūdas dēļ (piemēram, tīkla kļūme, atiestatīšana), exc
būs izņēmuma objekts, kas detalizēti apraksta kļūdu. Šī ir jūsu iespēja veikt tīrīšanu, reģistrēt atvienošanos vai mēģināt atkārtoti savienoties, ja veidojat klientu.
eof_received(self)
Šis ir smalkāks atzvanu. Tas tiek izsaukts, kad otra puse signalizē, ka vairs nesūtīs datus (piemēram, izsaucot shutdown(SHUT_WR)
POSIX sistēmā), bet savienojums joprojām var būt atvērts, lai jūs varētu sūtīt datus. Ja no šīs metodes atgriežat True
, transports tiks aizvērts. Ja atgriežat False
(noklusējums), jūs pats atbildat par transporta aizvēršanu vēlāk.
Transports: Komunikācijas kanāls
Transports ir objekts, ko sniedz asyncio
. Jūs to neradāt; jūs to saņemat protokola connection_made
metodē. Tas darbojas kā augsta līmeņa abstrakcija virs pamata tīkla ligzdas un notikumu cikla I/O grafiku. Tā galvenais uzdevums ir apstrādāt datu sūtīšanu un savienojuma kontroli.
Ar transportu jūs mijiedarbojaties, izmantojot tā metodes:
transport.write(data)
Galvenā metode datu sūtīšanai. data
ir jābūt bytes
objektam. Šī metode nav bloķējoša. Tā nesūta datus nekavējoties. Tā vietā tā ievieto datus iekšējā rakstīšanas buferī, un notikumu cikls tos sūta pa tīklu pēc iespējas efektīvāk fonā.
transport.writelines(list_of_data)
Efektīvāks veids, kā vienlaicīgi ierakstīt bytes
objektu secību buferī, potenciāli samazinot sistēmas izsaukumu skaitu.
transport.close()
Šī uzsāk ievērojamu izslēgšanu. Transports vispirms iztukšos visus datus, kas palikuši tā rakstīšanas buferī, un pēc tam aizvērs savienojumu. Pēc close()
izsaukšanas vairs nevar rakstīt datus.
transport.abort()
Šī veic cieto izslēgšanu. Savienojums tiek aizvērts nekavējoties, un jebkuri dati, kas gaida rakstīšanas buferī, tiek izmesti. Tas būtu jāizmanto ārkārtas apstākļos.
transport.get_extra_info(name, default=None)
Ļoti noderīga metode introspekcijai. Jūs varat iegūt informāciju par savienojumu, piemēram, attālās adreses ('peername'
), pamata ligzdas objektu ('socket'
) vai SSL/TLS sertifikāta informāciju ('ssl_object'
).
Simbiotiskā attiecība
Šī dizaina skaistums ir skaidrā, cikliskā informācijas plūsma:
- Iestatīšana: Notikumu cikls pieņem jaunu savienojumu.
- Instancēšana: Cikls izveido jūsu
Protocol
klases instanci unTransport
objektu, kas attēlo savienojumu. - Saistīšana: Cikls izsauc
your_protocol.connection_made(transport)
, saistot abus objektus. Jūsu protokols tagad spēj sūtīt datus. - Datu saņemšana: Kad dati pienāk tīkla ligzdā, notikumu cikls pamostas, nolasa datus un izsauc
your_protocol.data_received(data)
. - Apstrāde: Jūsu protokola loģika apstrādā saņemtos datus.
- Datu sūtīšana: Pamatojoties uz savu loģiku, jūsu protokols izsauc
self.transport.write(response_data)
, lai nosūtītu atbildi. Dati tiek buferēti. - Fona I/O: Notikumu cikls apstrādā nebloķējošu buferēto datu sūtīšanu pa transportu.
- Izslēgšana: Kad savienojums beidzas, notikumu cikls izsauc
your_protocol.connection_lost(exc)
galīgai tīrīšanai.
Praktiska piemēra izveide: Echo serveris un klients
Teorija ir lieliska, bet labākais veids, kā saprast Transportus un Protokolus, ir kaut ko uzbūvēt. Izveidosim klasisku echo serveri un atbilstošu klientu. Serveris pieņems savienojumus un vienkārši nosūtīs atpakaļ visus datus, ko tas saņem.
Echo servera ieviešana
Vispirms definēsim mūsu servera protokolu. Tas ir ievērojami vienkāršs, parādot galvenos notikumu apstrādātājus.
import asyncio
class EchoServerProtocol(asyncio.Protocol):
def connection_made(self, transport):
# Tiek izveidots jauns savienojums.
# Iegūst attālās adreses informāciju reģistrēšanai.
peername = transport.get_extra_info('peername')
print(f"Connection from: {peername}")
# Saglabā transportu vēlākai lietošanai.
self.transport = transport
def data_received(self, data):
# Dati tiek saņemti no klienta.
message = data.decode()
print(f"Data received: {message.strip()}")
# Echo atpakaļ klientam.
print(f"Echoing back: {message.strip()}")
self.transport.write(data)
def connection_lost(self, exc):
# Savienojums ir aizvērts.
print("Connection closed.")
# Transports tiek automātiski aizvērts, nav nepieciešams izsaukt self.transport.close() šeit.
async def main_server():
# Iegūst atsauci uz notikumu ciklu, jo plānojam serveri palaist neierobežoti ilgi.
loop = asyncio.get_running_loop()
host = '127.0.0.1'
port = 8888
# `create_server` korutīna izveido un startē serveri.
# Pirmais arguments ir protocol_factory, izsaucams, kas atgriež jaunu protokola instanci.
# Mūsu gadījumā vienkārši klases `EchoServerProtocol` nodošana darbojas.
server = await loop.create_server(
lambda: EchoServerProtocol(),
host,
port)
addrs = ', '.join(str(sock.getsockname()) for sock in server.sockets)
print(f'Serving on {addrs}')
# Serveris darbojas fonā. Lai galvenā korutīna paliktu dzīva,
# mēs varam gaidīt kaut ko, kas nekad nebeidzas, piemēram, jaunu Future.
# Šajā piemērā mēs vienkārši darbināsim to "mūžīgi".
async with server:
await server.serve_forever()
if __name__ == "__main__":
try:
# Lai palaistu serveri:
asyncio.run(main_server())
except KeyboardInterrupt:
print("Server shut down.")
Šajā servera kodā loop.create_server()
ir galvenais. Tas pievienojas norādītajai hostam un portam un norāda notikumu ciklam sākt klausīties jaunus savienojumus. Katram ienākošajam savienojumam tas izsauc mūsu protocol_factory
(lambda: EchoServerProtocol()
funkcija), lai izveidotu jaunu protokola instanci, kas veltīta konkrētajam klientam.
Echo klienta ieviešana
Klienta protokols ir nedaudz sarežģītāks, jo tam ir jāpārvalda savs stāvoklis: kādu ziņojumu sūtīt un kad tā darbs tiek uzskatīts par "pabeigtu". Izplatīts paraugs ir izmantot asyncio.Future
vai asyncio.Event
, lai signalizētu par pabeigšanu atpakaļ galvenajai korutīnai, kas startēja klientu.
import asyncio
class EchoClientProtocol(asyncio.Protocol):
def __init__(self, message, on_con_lost):
self.message = message
self.on_con_lost = on_con_lost
self.transport = None
def connection_made(self, transport):
self.transport = transport
print(f"Sending: {self.message}")
self.transport.write(self.message.encode())
def data_received(self, data):
print(f"Received echo: {data.decode().strip()}")
def connection_lost(self, exc):
print("The server closed the connection")
# Signalizē, ka savienojums ir zudis un uzdevums ir pabeigts.
self.on_con_lost.set_result(True)
def eof_received(self):
# Tas var tikt izsaukts, ja serveris nosūta EOF pirms aizvēršanas.
print("Received EOF from server.")
async def main_client():
loop = asyncio.get_running_loop()
# `on_con_lost` future tiek izmantota, lai signalizētu klienta darba pabeigšanu.
on_con_lost = loop.create_future()
message = "Hello World!"
host = '127.0.0.1'
port = 8888
# `create_connection` izveido savienojumu un saista protokolu.
try:
transport, protocol = await loop.create_connection(
lambda: EchoClientProtocol(message, on_con_lost),
host,
port)
except ConnectionRefusedError:
print("Connection refused. Is the server running?")
return
# Gaida, kamēr protokols signalizē, ka savienojums ir zudis.
try:
await on_con_lost
finally:
# Nodrošina transporta ievērojamu aizvēršanu.
transport.close()
if __name__ == "__main__":
# Lai palaistu klientu:
# Vispirms palaidiet serveri vienā terminālā.
# Pēc tam palaidiet šo skriptu citā terminālā.
asyncio.run(main_client())
Šeit loop.create_connection()
ir klienta sānu atbilstība create_server
. Tas mēģina izveidot savienojumu ar doto adresi. Ja tas ir veiksmīgi, tas instancē mūsu EchoClientProtocol
un izsauc tā connection_made
metodi. on_con_lost
Future izmantošana ir kritisks paraugs. main_client
korutīna await
šo future, efektīvi apturot savu izpildi, līdz protokols signalizē, ka tā darbs ir pabeigts, izsaucot on_con_lost.set_result(True)
no connection_lost
.
Papildu koncepcijas un reālās pasaules scenāriji
Echo piemērs aptver pamatus, taču reālās pasaules protokoli reti ir tik vienkārši. Apskatīsim dažas papildu tēmas, ar kurām jūs neizbēgami saskarsities.
Ziņojumu ietīšanas un buferēšanas apstrāde
Viena vissvarīgākā koncepcija, ko apgūt pēc pamatiem, ir tā, ka TCP ir baita plūsma. Nav ietverta "ziņojumu" robežu. Ja klients nosūta "Hello" un pēc tam "World", jūsu servera data_received
var tikt izsaukta vienu reizi ar b'HelloWorld'
, divas reizes ar b'Hello'
un b'World'
, vai pat vairākas reizes ar nepilnīgiem datiem.
Jūsu protokols ir atbildīgs par "ietīšanu" – šo baita plūsmu atjaunošanu jēgpilnos ziņojumos. Izplatīta stratēģija ir izmantot delimiters, piemēram, jaunu rindiņu rakstzīmi (
).
Šeit ir modificēts protokols, kas buferē datus, līdz tas atrod jaunu rindiņu, apstrādājot vienu rindiņu vienlaicīgi.
class LineBasedProtocol(asyncio.Protocol):
def __init__(self):
self._buffer = b''
self.transport = None
def connection_made(self, transport):
self.transport = transport
print("Connection established.")
def data_received(self, data):
# Pievieno jaunus datus iekšējam buferim
self._buffer += data
# Apstrādā tik daudz pilnu rindiņu, cik mums ir buferī
while b'\n' in self._buffer:
line, self._buffer = self._buffer.split(b'\n', 1)
self.process_line(line.decode().strip())
def process_line(self, line):
# Šeit ir jūsu lietojumprogrammas loģika vienam ziņojumam
print(f"Processing complete message: {line}")
response = f"Processed: {line}\n"
self.transport.write(response.encode())
def connection_lost(self, exc):
print("Connection lost.")
Plūsmas kontroles (pretspiediena) pārvaldīšana
Kas notiek, ja jūsu lietojumprogramma raksta datus uz transportu ātrāk, nekā tīkls vai attālais gala punkts to var apstrādāt? Dati uzkrājas transporta iekšējā buferī. Ja tas turpinās nekontrolēti, buferis var augt bezgalīgi, patērējot visu pieejamo atmiņu. Šī problēma ir pazīstama kā "pretspiediena" trūkums.
asyncio
nodrošina mehānismu tā apstrādei. Transports uzrauga savu bufera lielumu. Kad buferis pārsniedz noteiktu augstākās atzīmes slieksni, notikumu cikls izsauc jūsu protokola pause_writing()
metodi. Tas ir signāls jūsu lietojumprogrammai pārtraukt datu sūtīšanu. Kad buferis ir iztukšots zem zemākās atzīmes sliekšņa, cikls izsauc resume_writing()
, signalizējot, ka ir droši atsākt datu sūtīšanu.
class FlowControlledProtocol(asyncio.Protocol):
def __init__(self):
self._paused = False
self._data_source = some_data_generator() # Iedomājieties datu avotu
self.transport = None
def connection_made(self, transport):
self.transport = transport
self.resume_writing() # Sākt rakstīšanas procesu
def pause_writing(self):
# Transports buferis ir pilns.
print("Pausing writing.")
self._paused = True
def resume_writing(self):
# Transports buferis ir iztukšots.
print("Resuming writing.")
self._paused = False
self._write_more_data()
def _write_more_data(self):
# Šī ir mūsu lietojumprogrammas rakstīšanas cilpa.
while not self._paused:
try:
data = next(self._data_source)
self.transport.write(data)
except StopIteration:
self.transport.close()
break # Nav vairāk datu, ko sūtīt
# Pārbaudīt bufera lielumu, lai redzētu, vai mums vajadzētu nekavējoties apturēt
if self.transport.get_write_buffer_size() > 0:
self.pause_writing()
Ārpus TCP: Citi transporti
Lai gan TCP ir visizplatītākais lietošanas gadījums, Transporta/Protokola paraugs nav ierobežots ar to. asyncio
nodrošina abstraktus līdzekļus citiem sakaru veidiem:
- UDP: Savienojumu nepārvaldošiem sakariem izmantojiet
loop.create_datagram_endpoint()
. Tas nodrošinaDatagramTransport
, un jūs ieviestasyncio.DatagramProtocol
ar tādām metodēm kādatagram_received(data, addr)
unerror_received(exc)
. - SSL/TLS: Šifrēšanas pievienošana ir neticami vienkārša. Jūs nododat
ssl.SSLContext
objektuloop.create_server()
vailoop.create_connection()
.asyncio
automātiski apstrādā TLS roku spiešanu, un jūs saņemat drošu transportu. Jūsu protokola kodam nemaz nav jāmainās. - Apakšprocesi: Sakariem ar apakšprocesiem, izmantojot to standarta I/O caurules,
loop.subprocess_exec()
unloop.subprocess_shell()
var izmantot arasyncio.SubprocessProtocol
. Tas ļauj jums pārvaldīt apakšprocesus pilnīgi asinhronā, nebloķējošā veidā.
Stratēģiskais lēmums: Kad lietot Transportus pret Plūsmām
Ar diviem jaudīgiem API jūsu rīcībā, galvenais arhitektūras lēmums ir izvēlēties pareizo katram uzdevumam. Šeit ir ceļvedis, kas palīdzēs jums izlemt.
Izvēlieties Plūsmas (StreamReader
/StreamWriter
), ja...
- Jūsu protokols ir vienkāršs un balstīts uz pieprasījumu-atbildi. Ja loģika ir "nolasīt pieprasījumu, apstrādāt to, rakstīt atbildi", plūsmas ir ideālas.
- Jūs veidojat klientu labi zināmam, līniju balstītam vai fiksēta garuma ziņojumu protokolam. Piemēram, mijiedarbojoties ar Redis serveri vai vienkāršu FTP serveri.
- Jūs prioritizējat koda lasāmību un lineāru, imperatīvu stilu.
async/await
sintakse ar plūsmām bieži ir vieglāk saprotama izstrādātājiem, kuri ir jauni asinhronajā programmēšanā. - Ātra prototipēšana ir galvenā. Jūs varat ātri palaist vienkāršu klientu vai serveri ar plūsmām tikai ar dažām koda rindiņām.
Izvēlieties Transportus un Protokolus, ja...
- Jūs ieviešat sarežģītu vai pielāgotu tīkla protokolu no nulles. Tas ir galvenais lietošanas gadījums. Domājiet par protokoliem spēlēm, finanšu datu plūsmām, IoT ierīcēm vai peer-to-peer lietojumprogrammām.
- Jūsu protokols ir ļoti notikumu vadīts un nevis tīri pieprasījums-atbilde. Ja serveris var sūtīt nepamatotus ziņojumus klientam jebkurā laikā, uz atzvanu balstītais protokolu raksturs ir dabiskāks risinājums.
- Jums nepieciešama maksimāla veiktspēja un minimālas izmaksas. Protokoli nodrošina tiešāku ceļu uz notikumu ciklu, apejot dažus ar Plūsmu API saistītos papildu izdevumus.
- Jums ir nepieciešama smalka kontrole pār savienojumu. Tas ietver manuālu bufera pārvaldību, skaidru plūsmas kontroli (
pause/resume_writing
) un savienojuma dzīves cikla detalizētu apstrādi. - Jūs veidojat tīkla sistēmu vai bibliotēku. Ja jūs nodrošināt rīku citiem izstrādātājiem, Protokola/Transporta API izturīgais un elastīgais raksturs bieži ir pareizais pamats.
Secinājums: Apgūstot asyncio` pamatus
Python asyncio
bibliotēka ir slāņota dizaina šedevrs. Lai gan augsta līmeņa Plūsmu API nodrošina pieejamu un produktīvu sākumpunktu, tieši zema līmeņa Transporta un Protokola API ir asyncio
tīklošanas iespēju patiesais, jaudīgais pamats. Atdalot I/O mehānismu (Transportu) no lietojumprogrammas loģikas (Protokola), tā nodrošina izturīgu, mērogojamu un neticami elastīgu modeli sarežģītu tīkla lietojumprogrammu izveidei.
Šīs zema līmeņa abstrakcijas izpratne nav tikai akadēmisks vingrinājums; tā ir praktiska prasme, kas ļauj jums pāriet ārpus vienkāršiem klientiem un serveriem. Tā sniedz jums pārliecību, lai risinātu jebkuru tīkla protokolu, kontroli, lai optimizētu veiktspēju spiediena apstākļos, un spēju izveidot nākamās paaudzes augstas veiktspējas, asinhronos pakalpojumus Pythonā. Nākamreiz, saskaroties ar sarežģītu tīklošanas problēmu, atcerieties jaudu, kas slēpjas tieši zem virsmas, un nevilcinieties ķerties pie elegantā Transportu un Protokolu dueta.