Forum » Programiranje » Kako masovno pingat?
Kako masovno pingat?
ragezor ::
Recimo da nadzorujes dosti naprav in jih moras vskao minuto pingat, da preveris, ce so zive.
sem napisal en test na hitrico:
in ugotovil, da mi v multithreading nacinu prikazuje napacen ping.
zdaj pa nevem kako bi to resil?
niti ne vem tocno kje je problem. a je problem na ravni OSa, ker pac pingas full naenkrat. ali je problem v python threadih? glede na to, da ne pinga python proces se nagibam k temu, da je kriv OS.
sem napisal en test na hitrico:
import subprocess from threading import Thread import Queue q = Queue.Queue() def ping(): p = subprocess.Popen(["ping", "-c", "3", '8.8.8.8'], stdout=subprocess.PIPE, stderr=subprocess.PIPE).stdout.read() return float(p.split('=')[-1].split('/')[-3]) def ping_multi_threaded(q): q.put(ping()) def ping_single_threaded(l): l.append(ping()) for i in range(1000): Thread(target=ping_multi_threaded, args=(q,)).start() multi = [] while len(multi) < 1000: multi.append(q.get()) single = [] for i in range(10): ping_single_threaded(single) print 'Single threaded avg:', sum(single)/float(len(single)) print 'Multi threaded avg:', sum(multi)/float(len(multi))
$ python ping-test.py Single threaded avg: 13.9988 Multi threaded avg: 24.27617
in ugotovil, da mi v multithreading nacinu prikazuje napacen ping.
zdaj pa nevem kako bi to resil?
niti ne vem tocno kje je problem. a je problem na ravni OSa, ker pac pingas full naenkrat. ali je problem v python threadih? glede na to, da ne pinga python proces se nagibam k temu, da je kriv OS.
- spremenil: ragezor ()
videc ::
Zakaj ne uporabiš kakšen nadzorni sistem, ki ima to vgrajeno? Plus nadzor še nad kakšnimi storitvami, itd.
Invictus ::
ker gradim nadzorni sistem
Uporabiš Icingo, pa jo lahko razvijaš dalje.
Drugače pa poglej tudi broadcast ping ...
"Life is hard; it's even harder when you're stupid."
http://goo.gl/2YuS2x
http://goo.gl/2YuS2x
ragezor ::
Pri lokalnih IPjih je se vecja razlika
$ python ping-test.py
Single threaded avg: 0.1873
Multi threaded avg: 5.6735
zaenrkat problem resujem s tem, da z randomom porazdelim zacetke pinganja po celotni minuti
def ping_multi_threaded(q):
time.sleep(random.random() * 60)
q.put(ping())
je pa se vedno razlika 0.5 ms
$ python ping-test.py
Single threaded avg: 0.2054
Multi threaded avg: 0.71255
bom pogledal broadcast ping
$ python ping-test.py
Single threaded avg: 0.1873
Multi threaded avg: 5.6735
zaenrkat problem resujem s tem, da z randomom porazdelim zacetke pinganja po celotni minuti
def ping_multi_threaded(q):
time.sleep(random.random() * 60)
q.put(ping())
je pa se vedno razlika 0.5 ms
$ python ping-test.py
Single threaded avg: 0.2054
Multi threaded avg: 0.71255
bom pogledal broadcast ping
AndrejO ::
niti ne vem tocno kje je problem. a je problem na ravni OSa, ker pac pingas full naenkrat. ali je problem v python threadih? glede na to, da ne pinga python proces se nagibam k temu, da je kriv OS.
Problem je v tvoji kodi. Pretiravaš s številom niti in sam sebi "ubiješ" računalnik. Uporabi multiprocessing.Pool in omeji število procesov na malo bolj zdravo količino, ne pa 1000 njih. Ko si že pri stvari, pa lako tudi kodo nekoliko polepšaš.
V razmislek pa poskusi ugotoviti kaj se zgodi z I/O podsistemom na računalniku, ko poskušaš sočasno zagnati 1000 kopij istega programa, ki nekaj meri in želi biti na 1ms natančen. Hmm.... misliš, da to morda kaj vpliva na timing?
videc ::
+1 na tole in komentar o Icingi. Če ti sama Icinga ni tako všeč razmisli o OMD.
niti ne vem tocno kje je problem. a je problem na ravni OSa, ker pac pingas full naenkrat. ali je problem v python threadih? glede na to, da ne pinga python proces se nagibam k temu, da je kriv OS.
Problem je v tvoji kodi. Pretiravaš s številom niti in sam sebi "ubiješ" računalnik. Uporabi multiprocessing.Pool in omeji število procesov na malo bolj zdravo količino, ne pa 1000 njih. Ko si že pri stvari, pa lako tudi kodo nekoliko polepšaš.
V razmislek pa poskusi ugotoviti kaj se zgodi z I/O podsistemom na računalniku, ko poskušaš sočasno zagnati 1000 kopij istega programa, ki nekaj meri in želi biti na 1ms natančen. Hmm.... misliš, da to morda kaj vpliva na timing?
terryww ::
pri takem številu niti se ti splača razmislit o korutinah
It is the night. My body's weak.
I'm on the run. No time to sleep.
I'm on the run. No time to sleep.
ragezor ::
niti ne vem tocno kje je problem. a je problem na ravni OSa, ker pac pingas full naenkrat. ali je problem v python threadih? glede na to, da ne pinga python proces se nagibam k temu, da je kriv OS.
Problem je v tvoji kodi. Pretiravaš s številom niti in sam sebi "ubiješ" računalnik. Uporabi multiprocessing.Pool in omeji število procesov na malo bolj zdravo količino, ne pa 1000 njih. Ko si že pri stvari, pa lako tudi kodo nekoliko polepšaš.
V razmislek pa poskusi ugotoviti kaj se zgodi z I/O podsistemom na računalniku, ko poskušaš sočasno zagnati 1000 kopij istega programa, ki nekaj meri in želi biti na 1ms natančen. Hmm.... misliš, da to morda kaj vpliva na timing?
Jaz pac moram pobrati 1000 pingov v eni minuti. Ce bom pobiral zaporedoma, mi v eni minuti ne bo nikoli uspelo. Kot kaze preprosto OS ne utegne poschedulati pravocasno vseh pingov, da bi tocno zmerilo. Kot sem rekel, trenutno startam vse threade naenkrat in potem jih sleepam za random amount, da ne poklicejo vse naenkrat pinga. Torej bi jih lahko poklical tudi dosti vec, ce bi mel zadosti rama. Sem probal narediti tudi pool threadov. Manj thread workerjev, dlje casa traja pobiranje, bolj natancno je. Ampak potem pridem spet do tega, da je enako kot ce threade sleepam (ok, manj thread overheada je).
Korutine spet zmanjsajo overhead threadov ampak ne resujejo problema.
Ocitno bo pac potrebno paziti na obremenitev kompa, ki pinga. Ampak vedno sem mislil, da ce lahko routerji predelajo gigabajte paketkov na sekundo, bo mrezna na kompu ze pohendlala 1000 ping paketkov na easy. Izkaze se, da ping ni nekaj kar bi ICMP protokol podpiral, ampak se cas ocitno meri na aplikacijskem nivoju (sem bolj networking noob).
Verjetno bi za bolj ucinkovit ping moral napisati C program, ki opravi vse pinge, preko enega procesa in enega raw socketa. Potem bi mogoce bilo kaj bolje.
Isotropic ::
nagios?
ce se gres pa NIH, si pa še svoj .net stack napiši. :)
sem bral enkrat na redditu o eni firmi, k je mela nekaj takega :)
ce se gres pa NIH, si pa še svoj .net stack napiši. :)
sem bral enkrat na redditu o eni firmi, k je mela nekaj takega :)
Zgodovina sprememb…
- spremenil: Isotropic ()
AndrejO ::
Jaz pac moram pobrati 1000 pingov v eni minuti. Ce bom pobiral zaporedoma, mi v eni minuti ne bo nikoli uspelo. Kot kaze preprosto OS ne utegne poschedulati pravocasno vseh pingov, da bi tocno zmerilo.
Ne izgovarjaj se na OS, če si si za svojo rešitev izbral neprimerno orodje in določil slabo arhitekturo.
ragezor ::
Zato pa je tema tule, da lahko predlagas boljse toole in arhitekture.
Tvoj predlog glede poolov pa na zalost ne deluje, kot sem ti razlozil zgoraj.
Tvoj predlog glede poolov pa na zalost ne deluje, kot sem ti razlozil zgoraj.
ragezor ::
Cenim tudi odgovore tip nagios, etc. Ampak predstavljajte si, da delam produkt, ki bo konkuriral nagiosu. Kako bi potem naredil bolje od njih :)
Isotropic ::
nagios je zastonj, raje nehaj nategovat kupca
NIH
NIH
Zgodovina sprememb…
- spremenil: Isotropic ()
terryww ::
no, če se nočeš igrat s korutinami najde gugl korak boljšo kodo (http://stackoverflow.com/questions/2122... oz če se greš industrijski monitoring so ideje razvite v https://github.com/robertdavidgraham/ma... verjetno kaj iščeš in s čim boš navdušil stranko
It is the night. My body's weak.
I'm on the run. No time to sleep.
I'm on the run. No time to sleep.
AndrejO ::
ragezor ::
Isotropic, zdi se mi, da bi ti koristilo malo manj poslovno gledati na svet. Mogoce bi imel vec veselja delati kake stvari cetudi ne prinasajo denarja?
terryww, ni vse kar najdes na stackoverflowu dobra koda. Za IO bound aplikacije je ustvarjanje procesov slaba izbira, ker sele pri procesih pa res dobis dosti overheada + ce procesi komunicirajo med sabo, morajo serializirati podatke, jih poslati in spet deserializirati. Pri threadih tega ni potrebno.
AndrejO, jezik bi se ze naucil, da bi napisal en mikro servis, ki bi pingal, ce bi v kakem jeziku obstajala kaksna dobra knjiznica posebej za to. Da bi pa sel pisat specializiran ping v Cju (gradnja paketkov, crcjanje, itd,..) pa glih nebi.
Cimvec seveda.
Cim manjse seveda :)
terryww, ni vse kar najdes na stackoverflowu dobra koda. Za IO bound aplikacije je ustvarjanje procesov slaba izbira, ker sele pri procesih pa res dobis dosti overheada + ce procesi komunicirajo med sabo, morajo serializirati podatke, jih poslati in spet deserializirati. Pri threadih tega ni potrebno.
AndrejO, jezik bi se ze naucil, da bi napisal en mikro servis, ki bi pingal, ce bi v kakem jeziku obstajala kaksna dobra knjiznica posebej za to. Da bi pa sel pisat specializiran ping v Cju (gradnja paketkov, crcjanje, itd,..) pa glih nebi.
Cimvec seveda.
Cim manjse seveda :)
AndrejO ::
Za IO bound aplikacije je ustvarjanje procesov slaba izbira, ker sele pri procesih pa res dobis dosti overheada
Pa kljub temu si izbral rešitev, ki počne ravno to: poskuša "na en mah" ustvariti 1000 procesov.
+ ce procesi komunicirajo med sabo, morajo serializirati podatke, jih poslati in spet deserializirati. Pri threadih tega ni potrebno.
Ta komunikacija je dejansko zelo poceni. Glede na to, da si pa izbral niti, pa je čudno, da si izbral tudi Python/CPython, ki ima GIL in znane omejitve pri večnitnih programih na večjedrnih računalnikih.
AndrejO, jezik bi se ze naucil, da bi napisal en mikro servis, ki bi pingal, ce bi v kakem jeziku obstajala kaksna dobra knjiznica posebej za to. Da bi pa sel pisat specializiran ping v Cju (gradnja paketkov, crcjanje, itd,..) pa glih nebi.
Če je v tebi res toliko programerja, da se bi lahko poljuben jezik na hitro naučil, potem ti je ta "specializiran ping" stvar nekaj uric. Ajde, popoldneva, če se šele učiš jezika.
Cimvec seveda.
Cim manjse seveda :)
Malo manj heca. Tile odgovori kažejo tvojo nepremišljenost, če ne kar neresnost. Če se igraš inženirja, potem se obnašaj kot inženir in določi vsaj osnovne kriterije, ki jih mora rešitev izpolniti. Do sedaj si določil samo enega. Torej lahko predvidim, da ti bo odgovor v zbirniku za MIPS verjetno ustrezen, če bo le dal od sebe 3000 QPS.
ragezor ::
Moja resitev ustvarja procese, ker je to bil najhitrejsi nacin implementacije in testiranje zadeve. Tudi python sem izbral zaradi tega, ker ga najbolj poznam in najlazje eksperimentiram.
GIL ne vpliva tukaj dosti na zadevo.
Najprej se delas norca, ker se mi zdi lahko nauciti en jezik za neko malo stvar, ki bi uporabljala neko knjiznico, kasneje se ti zdi cudno, da sem izbral python. A ti se za vsako stvar najprej pozanimas, kje se najhitreje naredi in se potem gres naucit jezik in potem se lotis zadeve? Se dobro, da projekti vsebujejo vedno samo en tip problemov, da lahko izberes potem jezik, ki je najboljsi za ta tip :)
Ja, osnovno uporabo jezika (in knjiznice) se je verjento hitreje nauciti, kot prestudirati par protokolov, razumeti algoritme in potem implementirati zadevo, ki bo performirala boljse kot zadeva, ki so jo verjetno napisali eksperti na podrocju.
Se vedno nobene pametne ideje ali namiga od tebe.
GIL ne vpliva tukaj dosti na zadevo.
Najprej se delas norca, ker se mi zdi lahko nauciti en jezik za neko malo stvar, ki bi uporabljala neko knjiznico, kasneje se ti zdi cudno, da sem izbral python. A ti se za vsako stvar najprej pozanimas, kje se najhitreje naredi in se potem gres naucit jezik in potem se lotis zadeve? Se dobro, da projekti vsebujejo vedno samo en tip problemov, da lahko izberes potem jezik, ki je najboljsi za ta tip :)
Ja, osnovno uporabo jezika (in knjiznice) se je verjento hitreje nauciti, kot prestudirati par protokolov, razumeti algoritme in potem implementirati zadevo, ki bo performirala boljse kot zadeva, ki so jo verjetno napisali eksperti na podrocju.
Se vedno nobene pametne ideje ali namiga od tebe.
terryww ::
terryww, ni vse kar najdes na stackoverflowu dobra koda. Za IO bound aplikacije je ustvarjanje procesov slaba izbira, ker sele pri procesih pa res dobis dosti overheada + ce procesi komunicirajo med sabo, morajo serializirati podatke, jih poslati in spet deserializirati. Pri threadih tega ni potrebno.
ah, ko ljudje niti tolko niso, da dobro pogledajo, če si že vzameš čas da jim odgovoriš...
- s primerom iz stackoverflowa sem ti želel nakazat kako, če že s threadi, ker ti zaženeš thread in v njem nov proces, skratka, kr nekaj
- ker so threadi v pythonu potratni, sploh 1k threadov, kot je AndrejO že večkrat opozoril, sem ti nakazal drugo alternativo - korutine (v pythonu maš greenlet lib ipd.), ki je ravno mišljen za take probleme
- za kaj bolj naprednega maš masscan in rešiš vse probleme
It is the night. My body's weak.
I'm on the run. No time to sleep.
I'm on the run. No time to sleep.
ragezor ::
ja razen mojega ocitno.
masscan ne pinga. pa kolko googlam okrog vsi uporabljajo ping za discovery, noben ne govori nic o tem, da lahko popinga dosti hostov naenkrat in ohrani natancnost.
za korutine sem ti povedal, da so kul, ampak ne resijo mojega problema, ker je krivo to, da klicem preveckrat ping program. zdaj ce to pocnem s threadi, procesi ali korutinami nima veze.
masscan ne pinga. pa kolko googlam okrog vsi uporabljajo ping za discovery, noben ne govori nic o tem, da lahko popinga dosti hostov naenkrat in ohrani natancnost.
za korutine sem ti povedal, da so kul, ampak ne resijo mojega problema, ker je krivo to, da klicem preveckrat ping program. zdaj ce to pocnem s threadi, procesi ali korutinami nima veze.
AndrejO ::
Moja resitev ustvarja procese, ker je to bil najhitrejsi nacin implementacije in testiranje zadeve. Tudi python sem izbral zaradi tega, ker ga najbolj poznam in najlazje eksperimentiram.
Ali lahko na podlagi tega sklepam, da bi ti Python kot jezik in okolje najbolj ustrezal, ker ga najbolje poznaš?
GIL ne vpliva tukaj dosti na zadevo.
Dejansko pomembno vpliva na zadevo. 1000 niti v Pythonu, ki se zaženejo sočasno in sočasno poskušajo opravljati delo, ima svojo ceno ravno zaradi GIL.
Najprej se delas norca, ker se mi zdi lahko nauciti en jezik za neko malo stvar, ki bi uporabljala neko knjiznico,
Ne delam se norca, temveč testiram tvoja stališča, da ugotovim kaj in kako si razmišljal, ko si se odločal. Eno je, da ti nekdo strese rešitev iz rokava, nekaj drugega pa potrebujem, če naj ti pomagam najti rešitev, ki bo ustreala tebi in tvojim potrebam.
kasneje se ti zdi cudno, da sem izbral python.
Znova testiram, ker navedeš eno stališče, hkrati pa tvoja izbira nakazuje, da si to storil v nasprotju s tem stališčem.
A ti se za vsako stvar najprej pozanimas, kje se najhitreje naredi in se potem gres naucit jezik in potem se lotis zadeve? Se dobro, da projekti vsebujejo vedno samo en tip problemov, da lahko izberes potem jezik, ki je najboljsi za ta tip :)
Na mojo srečo imam toliko let naskoka, da sem uporabljal že toliko programskih jezikov, da imam na voljo kar kontretno "orodjarno" za kar veliko različnih vrst problemov. In ja, tudi z vsem tem se mi ne zdi nič nezaslišanega pogledati tudi še neuporabljene jezike, da vidim, če bi s katerim drugim stvar opravil bolje in hitreje.
Ja, osnovno uporabo jezika (in knjiznice) se je verjento hitreje nauciti, kot prestudirati par protokolov, razumeti algoritme in potem implementirati zadevo, ki bo performirala boljse kot zadeva, ki so jo verjetno napisali eksperti na podrocju.
Pri konkretnem problemu na srečo ni niti hudih algoritmov, niti hudih protokolov.
Se vedno nobene pametne ideje ali namiga od tebe.
Saj bo, saj bo. Samo še malo podatkov mi daj, da ti bom lahko dal nekaj, kar si mislim, da ti bo koristilo bolj, kot pa samo "juhuhu, jaz pa lahko to naredim tako".
ragezor ::
kaksne podatke se torej rabis?
jaz vidim priblizno dve moznosti:
1. najdem nek tool ala masscan, sparsam output in ciao (al pa knjiznico, ki dela isto kot tool)
2. skopiram pure python implementacijo pinga jo probam razumeti in jo stweakam do zeljenih rezultatov. tukaj pa bo potem prislo v postev optimiziranje v stilu korutin in podobnih zadev. ce se izkaze, da je pretezko pac uporabljam to kar mam in zivim s kamnom v srcu, ker vem, da je moj ping verjetno napacen za kaksno milisekundo. ce se kdaj pojavi potreba, da bom moral pingati nenormalno veliko stevilo naprav se pa grem jokat oziroma si vzamem vec casa za resitev problema.
jaz vidim priblizno dve moznosti:
1. najdem nek tool ala masscan, sparsam output in ciao (al pa knjiznico, ki dela isto kot tool)
2. skopiram pure python implementacijo pinga jo probam razumeti in jo stweakam do zeljenih rezultatov. tukaj pa bo potem prislo v postev optimiziranje v stilu korutin in podobnih zadev. ce se izkaze, da je pretezko pac uporabljam to kar mam in zivim s kamnom v srcu, ker vem, da je moj ping verjetno napacen za kaksno milisekundo. ce se kdaj pojavi potreba, da bom moral pingati nenormalno veliko stevilo naprav se pa grem jokat oziroma si vzamem vec casa za resitev problema.
Ribič ::
Zakaj namesto python skripte ne uporabiš nmap skenerja?
# nmap -sP 192.168.1.0/24
Starting Nmap 6.40 ( http://nmap.org ) at 2015-04-24 23:09 CEST
Nmap scan report for ruter.localdomain (192.168.1.1)
Host is up (0.00053s latency).
Nmap scan report for 192.168.1.2
Host is up (0.0012s latency).
Nmap scan report for mojkomp.localdomain (192.168.1.100)
Host is up (0.00034s latency).
Nmap done: 256 IP addresses (3 hosts up) scanned in 2.92 seconds
Potem pa parsaš tale text z pythonom?
# nmap -sP 192.168.1.0/24
Starting Nmap 6.40 ( http://nmap.org ) at 2015-04-24 23:09 CEST
Nmap scan report for ruter.localdomain (192.168.1.1)
Host is up (0.00053s latency).
Nmap scan report for 192.168.1.2
Host is up (0.0012s latency).
Nmap scan report for mojkomp.localdomain (192.168.1.100)
Host is up (0.00034s latency).
Nmap done: 256 IP addresses (3 hosts up) scanned in 2.92 seconds
Potem pa parsaš tale text z pythonom?
AndrejO ::
kaksne podatke se torej rabis?
Potrdi ali ovrži moje predvidevanje, da ti bi Python najbolj ugajal.
Vsaj približno opredeli na kakšni strojni opremi želiš doseči 1000 naprav v 60s pri 3x ping za vsako. Je to nekaj tipa Raspberry PI ali nekaj tipa "namizni PC"?
1. najdem nek tool ala masscan, sparsam output in ciao (al pa knjiznico, ki dela isto kot tool)
Dokler boš operiral z "lansiram nov proces za vsako napravo posebej", boš vedno naletel na isto težavo. To je napačna smer, razen če boš našel aplikacijo, ki se bo obnašala kot tvoj "ping server", da jih boš lahko zagnal več hkrati nato pa komuniciral z njimi.
2. skopiram pure python implementacijo pinga jo probam razumeti in jo stweakam do zeljenih rezultatov.
Če želiš, ti lahko pomagam, da spišeš svojo implementacijo, ki bo tebi v celoti razumljiva, ker jo boš tako ali tako sam spisal. Z nekaj znanja konkkretna zadeva sploh ni zahtevna in tam, kjer se ti bo zatikalo, ti lahko pomagam vsaj jaz, verjetno pa tudi drugi.
tukaj pa bo potem prislo v postev optimiziranje v stilu korutin in podobnih zadev. ce se izkaze, da je pretezko pac uporabljam to kar mam in zivim s kamnom v srcu, ker vem, da je moj ping verjetno napacen za kaksno milisekundo.
Kakšno natančnost pa sploh pričakuješ? Glede na to, da bo tvoja (oz. "userland") meritev časa vedno podložna milosti celotnega sistema od gonilnika mrežne kartice naprej, kolikšno odstopanje ti je sprejemljivo? Kaj te tukaj sploh zanima? Dosegljivst naprave, dosegljivost z določenim RTT ali dejanski RTT?
ce se kdaj pojavi potreba, da bom moral pingati nenormalno veliko stevilo naprav se pa grem jokat oziroma si vzamem vec casa za resitev problema.
Osnove Pythona znaš, čez vikend lahko z nekaj malega pomoči ali pa tudi brez nje spišeš ta manjkajoči "ping", se naučiš kaj novega in greš z novo izkušnjo naprej.
ragezor ::
ja, python. PC racunalnik oziroma povprecen server.
Odstopanje mora biti manjse kot pri zdajsnjem pristopu. Nevem postaviti neke meje pri takih problemih, ker nikoli ne bo perfektno, ampak je pa fajn, da je cimboljse.
medtem casom sem ze raziskoval in zgleda je point v tem, da je tvoj program kar se da odziven na select()
bom jutri probal taktiko: 2 threada, en najprej ustvari vse paketke, potem jih pa zaporedoma poslje. drug thread pa v while zanki caka na select in shranjuje rezultate in timestampe nekam. ko je vsega konec se pa poracunajo zadeve.
edino ni mi jasno, ce lahko jaz posljem tri paketke do enega hosta naenkrat (z razlicnimi sequenci), ali moram cakati, da dobim prvi paketek nazaj in sele nato lahko naslednjega posljem. pomoje, da lahko vse naenkrat. ne vidim razloga zakaj nebi.
Odstopanje mora biti manjse kot pri zdajsnjem pristopu. Nevem postaviti neke meje pri takih problemih, ker nikoli ne bo perfektno, ampak je pa fajn, da je cimboljse.
medtem casom sem ze raziskoval in zgleda je point v tem, da je tvoj program kar se da odziven na select()
bom jutri probal taktiko: 2 threada, en najprej ustvari vse paketke, potem jih pa zaporedoma poslje. drug thread pa v while zanki caka na select in shranjuje rezultate in timestampe nekam. ko je vsega konec se pa poracunajo zadeve.
edino ni mi jasno, ce lahko jaz posljem tri paketke do enega hosta naenkrat (z razlicnimi sequenci), ali moram cakati, da dobim prvi paketek nazaj in sele nato lahko naslednjega posljem. pomoje, da lahko vse naenkrat. ne vidim razloga zakaj nebi.
AndrejO ::
ja, python. PC racunalnik oziroma povprecen server.
Odlično. Potem je Python več kot primeren in stvar je v njemu v celoti izvedljiva. Recimo v 200 vrsticah kode. Na hitro skupaj zmetana implementacija mi da na mojem prenosniku 1000 x 3 paketke na 8.8.8.8 v cca. 20s s 100 pomožnih procesov (multiprocessing).
Odstopanje mora biti manjse kot pri zdajsnjem pristopu. Nevem postaviti neke meje pri takih problemih, ker nikoli ne bo perfektno, ampak je pa fajn, da je cimboljse.
OK, to je tudi dosegljivo, če je omrežje na strani strežnika sposobno daljših poplav paketov brez njihovega odmetavanja.
medtem casom sem ze raziskoval in zgleda je point v tem, da je tvoj program kar se da odziven na select()
Select ni nikoli problematičen. Pomembno je, kaj boš zložil okoli njega.
bom jutri probal taktiko: 2 threada, en najprej ustvari vse paketke, potem jih pa zaporedoma poslje. drug thread pa v while zanki caka na select in shranjuje rezultate in timestampe nekam. ko je vsega konec se pa poracunajo zadeve.
Znova se boš zapletel v niti in GIL te bo ustavil. Če želiš v Python narediti dejansko več stvari vzporedno, potem je nujno, da uporabiš več procesov.
Poglej si multiprocessing.Pool, ki je ravno prava stvar za to, kar potrebuješ.
edino ni mi jasno, ce lahko jaz posljem tri paketke do enega hosta naenkrat (z razlicnimi sequenci), ali moram cakati, da dobim prvi paketek nazaj in sele nato lahko naslednjega posljem. pomoje, da lahko vse naenkrat. ne vidim razloga zakaj nebi.
Načeloma ne rabiš čakati, vendar razmisli kaj točno meriš. Povprečen RTT preko daljšega časa (recimo 5s) je nekaj čisto drugega, kot pa RTT treh zaporednih kratkih (cca. 40 bytov) paketkov. Če boš vse tri stlačil v isto milisekundo, ali potem dejansko rabiš pošiljati tri?
BigWhale ::
A ste vsi skupaj na glavo padl? :)
Klicat Popen in zaganjat externi proces je rahlo neproduktivno in trapasto. Poglej si gevent (http://www.gevent.org/) in prvo implementacijo icmp pinga, ki jo najdes za gevent, recimo tole https://github.com/mastahyeti/gping/blo...
Tole implementiras in bo stvar tridesetkrat bolj scalable in hitrejsa in bolj ucinkovita.
Klicanje zunanjih procesov je nekaj kar ne delas, ce lahko v native jeziku resis stvari, ker te sam klic zunanjega procesa kosta tolk I/Oja, da se ti tega v nobenem primeru ne splaca poceti.
p = subprocess.Popen(["ping", "-c", "3", '8.8.8.8'], stdout=subprocess.PIPE, stderr=subprocess.PIPE).stdout.read()
Klicat Popen in zaganjat externi proces je rahlo neproduktivno in trapasto. Poglej si gevent (http://www.gevent.org/) in prvo implementacijo icmp pinga, ki jo najdes za gevent, recimo tole https://github.com/mastahyeti/gping/blo...
Tole implementiras in bo stvar tridesetkrat bolj scalable in hitrejsa in bolj ucinkovita.
Klicanje zunanjih procesov je nekaj kar ne delas, ce lahko v native jeziku resis stvari, ker te sam klic zunanjega procesa kosta tolk I/Oja, da se ti tega v nobenem primeru ne splaca poceti.
Invictus ::
Najprej se vprašaj zakaj sploh rabiš odgovor 1000 pingov v minuti. Ko boš to vedel, bo vsae ostalo lažje.
Sam delam v nadzornih sistemih že zadnjih 12 let, pa vem da več kot en ping/device ne rabiš bolj pogosto kot na 15 minut.
Poleg tega so ponavadi bolj pomembni drugi parametri neke naprave in ne ping.
Sam delam v nadzornih sistemih že zadnjih 12 let, pa vem da več kot en ping/device ne rabiš bolj pogosto kot na 15 minut.
Poleg tega so ponavadi bolj pomembni drugi parametri neke naprave in ne ping.
"Life is hard; it's even harder when you're stupid."
http://goo.gl/2YuS2x
http://goo.gl/2YuS2x
BigWhale ::
Jaz pac moram pobrati 1000 pingov v eni minuti. Ce bom pobiral zaporedoma, mi v eni minuti ne bo nikoli uspelo. Kot kaze preprosto OS ne utegne poschedulati pravocasno vseh pingov, da bi tocno zmerilo.
Uhm.
Kaj tocno bos pa zvedel od 1000 pingov v eni minuti? Da imas 1000 naprav na katerih deluje TCP stack? :)
Spura ::
Lahko bi se naprave javljale nadzornemu serverju vsako minuto? In ce ze mores obratno, zakaj ne mores narest pac da se po 100 pingov naenkrat izvaja namesto 1000?
SeMiNeSanja ::
Isti pomislek, ki ga je napisal Invictus, sem imel tudi jaz, samo se nisem hotel vpletati, da me nebi kdo obsojal, da vlečem diskusijo na offtopic.
Ping je pri nadzoru naprav/omrežja razmeroma nepomemben podatek, pomemben postane le v primeru, da čez daljše časovno obdobje postane nenavadno visok. Za tako statistiko pa povsem zadošča, če na 5 min pošlješ par pingov in vzameš povprečje.
Bolj intenzivno pinganje pa potem uporabljaš, ko si že identificiral problematični node in ugotavlaš posledice določenih posegov na omrežju/napravah.
Vse kar gre preko tega pa je čisto nepotrebno floodanje omrežij, da bi pridobival podatke, ki jih ne bo nihče gledal.
Ping je pri nadzoru naprav/omrežja razmeroma nepomemben podatek, pomemben postane le v primeru, da čez daljše časovno obdobje postane nenavadno visok. Za tako statistiko pa povsem zadošča, če na 5 min pošlješ par pingov in vzameš povprečje.
Bolj intenzivno pinganje pa potem uporabljaš, ko si že identificiral problematični node in ugotavlaš posledice določenih posegov na omrežju/napravah.
Vse kar gre preko tega pa je čisto nepotrebno floodanje omrežij, da bi pridobival podatke, ki jih ne bo nihče gledal.
ragezor ::
pomisleki, glede gostote pinganja in ce se res rabi taka natancnost pri pinganju so valid, bolj se gre, da zadevi pridem do dna :)
poleg pinga se pobirajo se ostale informacije preko snmpja, http apija, ... zdaj pri ostalih stvareh lahko ustvarim threade/korutine in je vse kul (ker je zadeva IO bound). vec procesov, kot imas cpu corov je bolj kot ne nesmiselno (razen ce uporabljas non thread safe knjiznice).
torej ugotovimo, da imamo lahko zelo velik throughput brez problema.
pri pingu pa je dodatna zahteva se to, da se vrnjeni paketek cimprej po prejetju obdela in se shrani cas prejetja le tega. tu pa nastane problem, ker nisi ziher, kdaj bo tvoj proces schedulan, da bo pobral rezultate. recimo interupti bi bili en nacin. ko pride paketek se vedno switcha na proces, ki si shrani cas prejetja. to pa mislim, da se ne da narediti, ali?
sem si pogledal implementacijo pinga v pythonu.
https://github.com/CoreSecurity/impacke...
a bi slo odpreti samo en socket, v enem threadu filat noter paketke, v drugem pa jih samo prejemati. ampak nevem kako bi jih identificiral? ne razumem tocno tega, kaj se dogaja s checksumi in podatki, ki jih paketek drzi. pa kako vem, koliko byteov moram sprejemat. ker se bo nagrmadilo verjento vec paketkov zaporedoma bi jih rad jemal enega po enega.
poleg pinga se pobirajo se ostale informacije preko snmpja, http apija, ... zdaj pri ostalih stvareh lahko ustvarim threade/korutine in je vse kul (ker je zadeva IO bound). vec procesov, kot imas cpu corov je bolj kot ne nesmiselno (razen ce uporabljas non thread safe knjiznice).
torej ugotovimo, da imamo lahko zelo velik throughput brez problema.
pri pingu pa je dodatna zahteva se to, da se vrnjeni paketek cimprej po prejetju obdela in se shrani cas prejetja le tega. tu pa nastane problem, ker nisi ziher, kdaj bo tvoj proces schedulan, da bo pobral rezultate. recimo interupti bi bili en nacin. ko pride paketek se vedno switcha na proces, ki si shrani cas prejetja. to pa mislim, da se ne da narediti, ali?
sem si pogledal implementacijo pinga v pythonu.
https://github.com/CoreSecurity/impacke...
a bi slo odpreti samo en socket, v enem threadu filat noter paketke, v drugem pa jih samo prejemati. ampak nevem kako bi jih identificiral? ne razumem tocno tega, kaj se dogaja s checksumi in podatki, ki jih paketek drzi. pa kako vem, koliko byteov moram sprejemat. ker se bo nagrmadilo verjento vec paketkov zaporedoma bi jih rad jemal enega po enega.
Invictus ::
a bi slo odpreti samo en socket, v enem threadu filat noter paketke, v drugem pa jih samo prejemati. ampak nevem kako bi jih identificiral?
Identificiral jih boš po source IPju.
"Life is hard; it's even harder when you're stupid."
http://goo.gl/2YuS2x
http://goo.gl/2YuS2x
Randomness ::
pri pingu pa je dodatna zahteva se to, da se vrnjeni paketek cimprej po prejetju obdela in se shrani cas prejetja le tega. tu pa nastane problem, ker nisi ziher, kdaj bo tvoj proces schedulan, da bo pobral rezultate. recimo interupti bi bili en nacin. ko pride paketek se vedno switcha na proces, ki si shrani cas prejetja. to pa mislim, da se ne da narediti, ali?Mislim, da glede tega malo preveč kompliciraš. Schedulerju se res bolj težko izogneš. Možno je sicer povišati prioriteto procesa/threada/taska, vendar real-time garancij na OS-ih, na katerih teče Python, pač nimaš.
Randomness ::
pa kako vem, koliko byteov moram sprejemat. ker se bo nagrmadilo verjento vec paketkov zaporedoma bi jih rad jemal enega po enega.Saj drugače kot brati enega po enega tudi ne gre, to ni stream-oriented protocol tako kot TCP.
Randomness ::
ampak nevem kako bi jih identificiral?V icmp header zabašeš id in sequence number, ki ti poleg src adrese služita za identifikacijo.
Invictus ::
fajn bi bila moznost pinganja istega hosta naenkrat
Pa kaj misliš isti host večkrat zapovrstjo pingat?
Precej neuporabno za monitoring, pa še kak IDS/firewall te bo dal na črno listo spama ...
"Life is hard; it's even harder when you're stupid."
http://goo.gl/2YuS2x
http://goo.gl/2YuS2x
AndrejO ::
a bi slo odpreti samo en socket, v enem threadu filat noter paketke, v drugem pa jih samo prejemati. ampak nevem kako bi jih identificiral?
Identificiral jih boš po source IPju.
Identificiral jih boš po source IP, ID, zaporedni številki in vsebini katero moraš izbrati natančno za ta način.
fajn bi bila moznost pinganja istega hosta naenkrat
Pa kaj misliš isti host večkrat zapovrstjo pingat?
Precej neuporabno za monitoring, pa še kak IDS/firewall te bo dal na črno listo spama ...
S tem si predvidel naslednje okoliščine:
- za vsak host boš torej poslal samo en paket IN
- paketi na omrežju se vedno vrnejo v enakem zaporedju IN
- nikoli ne bo noben drug proces na računalniku istočasno tudi "pingal" isti host IN
- za vsak poslan paket boš vedno dobil natančno en paket v odgovor.
Vse tri izjave so v resničnem svetu neveljavne in bodo pripeljale do neveljavnih rezultatov.
Sicer pa ne pozabi, da uporabljaš "surov" dostop. Prejel boš veliko prometa, ki te niti najmanj ne briga.
AndrejO ::
Sicer pa tako... da ne bo preveč razmišljanja na suho. Tole načeloma deluje.
ping.py
pinger.py
ping.py
import os import select import socket import struct import time class Error(Exception): """Base error class for all ICMP exceptions.""" def __init__(self, msg="base ping error"): super(Exception, self).__init__(msg) class PingTimeout(Error): """Timeout waiting for ICMP Echo reply from destination.""" def __init__(self, msg="ping timeout"): super(PingTimeout, self).__init__(msg) class InvalidChecksum(Error): """Invalid ICMP packet checksum.""" def __init__(self, msg="invalid checksum"): super(InvalidChecksum, self).__init__(msg) class _ICMPEcho(object): """Encapsulation of ICMP Echo and Reply packets.""" def __init__(self, type, code, id, seq, data): self.type = type self.code = code self.id = id self.seq = seq self.data = data def pack(self): fmt = "!BBHHH%ds" % len(self.data) pkt = struct.pack(fmt, self.type, self.code, 0, self.id, self.seq, self.data) csum = _checksum(pkt) return struct.pack(fmt, self.type, self.code, csum, self.id, self.seq, self.data) @staticmethod def unpack(pkt, has_ip_hdr=False): if has_ip_hdr: hdr_size = (ord(pkt[0]) & 0xf) << 2 pkt = pkt[hdr_size:] (type, code, csum, id, seq, data) = struct.unpack("!BBHHH%ds" % (len(pkt) - 8), pkt) pktchk = struct.pack("!BBHHH%ds" % len(data), type, code, 0, id, seq, data) if csum != _checksum(pktchk): raise InvalidChecksum() return _ICMPEcho(type, code, id, seq, data) def _checksum(buf): """Calculate one's complement of one's complement of sum of 16-bit words.""" # If buffer length is odd, add 0 byte to it to even it out. if len(buf) & 1 == 1: buf = buf[:] + "\0" # Checksum loop calculates one's complement sum. 16-bit word is assumed # to be in network order. s = 0 for ii in range(0, len(buf), 2): # Get 16-bit word, network order. w = ord(buf[ii + 1]) + (ord(buf[ii]) << 8) # Add with carry. s += w s = (s & 0xffff) + (s >> 16) # Checksum is one's complement of one's complement sum. return s ^ 0xffff def ping(address, seq, timeout): """Send ICMP Echo request packet to address and wait for reply. Sends ICMP Echo request packet to address and waits for reply or timeout. Args: address: a string, address of host to ping. seq: an int, sequence number between 1 and 65535. timeout: a float, time to wait for echo reply reply in seconds. Returns: a float, time in seconds that it took to receive echo reply. Raises: PingTimeout: when echo reply isn't received within specified timeout. """ # Prepare ICMP Echo request packet. Discriminator is needed to avoid hitting # delayed packets in the same process, because processes could be reused. id = os.getpid() & 0xffff disc = "%f" % time.time() pkt = _ICMPEcho(8, 0, id, seq, disc) # Open socket and send prepared packet to destination address. s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_ICMP) s.sendto(pkt.pack(), (address, 0)) # Store the time when packet was delivered to the system (assumed sent). start = time.time() # Deadline is the value of time.time() until which to wait for matching # ICMP Reply packet to return. It's used to calculate select() timeout. deadline = start + timeout while timeout > 0.0: # Wait for an event on socket. ready = select.select([s], [], [], timeout) # If there's nothing to read, a timeout occured. if len(ready[0]) == 0: raise PingTimeout() # Store received time. If packet will match, this will be used to calculate RTT. received = time.time() pkt, src_addr = s.recvfrom(1528) # Short the loop if the packet is from the wrong address. if src_addr[0] != address: timeout = deadline - time.time() continue # Short the loop if packet doesn't match the one we have sent. pkt = _ICMPEcho.unpack(pkt, has_ip_hdr=True) if pkt.type != 0 or pkt.code != 0 or pkt.id != id or pkt.seq != seq or pkt.data != disc: timeout = deadline - time.time() continue # Calculate RTT and return it return received - start
pinger.py
import sys import time from multiprocessing import Pool import ping class Ping(object): def __init__(self, tries=3, interval=1.0, timeout=1.0): self.tries = tries self.interval = interval self.timeout = timeout def __call__(self, address): times = [] for seq in xrange(1, self.tries + 1): not_before = time.time() + self.interval try: times.append(ping.ping(address, seq, self.timeout)) except ping.PingTimeout: times.append(None) except Exception as e: return (address, e) # Wait if needed before moving to the next iteration. while seq < self.tries and time.time() < not_before: time.sleep(not_before - time.time()) # Return address and list of tries. return (address, times) def ping_all(addresses, processes=25): pool = Pool(processes=processes) ok, err = [], [] for res in pool.imap(Ping(), addresses, chunksize=10): if isinstance(res[1], Exception): err.append(res) elif not [x for x in res[1] if x]: err.append((res[0], Exception("host unreachable"))) else: ok.append(res) return ok, err def main(argv): addresses = ['127.0.0.1'] * 1000 start = time.time() ok, err = ping_all(addresses) end = time.time() if ok: print "Averages:" for result in ok: valid = [rtt for rtt in result[1] if rtt] success = len(valid) * 100 / len(result[1]) print " %s:\t%%/Avg/Min/Max: %3d%%/%f/%f/%f" % (result[0], success, sum(valid)/float(len(valid)), min(valid), max(valid)) if err: print "Errors:" for result in err: print " %s:\t%s" % result print "Time to execute all: %f" % (end - start) if __name__ == "__main__": sys.exit(main(sys.argv))
ragezor ::
lahko prosim se malo razlozis kaj se dogaja v pack() in unpack() ter kaj je type, code in id?
AndrejO ::
lahko prosim se malo razlozis kaj se dogaja v pack() in unpack()
Tukaj.
ter kaj je type, code in id?
Tukaj in tukaj.
Povezave pa zato, ker je nemogoče, da bi sam bolje povzel ali opisal kaj katera stvar počne (za modul struct) oziroma kako je sestavljena glava (za razlago tipa, kode in ostalih polj v ICMP Echo Request/Reply paketih).
ragezor ::
imel sem priloznost vec casa posvetiti temu problemu (natancnost pinga)
uporabil sem tole resitev: https://www.kernel.org/doc/Documentatio...
kolikor mi je znano se paketki timestampajo hardwerasko, ce je za to podpora, ce ne pa v kernelu. vsekakor boljse kot pa, ce bi timestampal v userlandu. ne vem kako podprta je zadeva, ampak delovalo je na vseh masinah kar sem jih sprobal.
okvirna implementacija v pythonu:
uporabil sem tole resitev: https://www.kernel.org/doc/Documentatio...
kolikor mi je znano se paketki timestampajo hardwerasko, ce je za to podpora, ce ne pa v kernelu. vsekakor boljse kot pa, ce bi timestampal v userlandu. ne vem kako podprta je zadeva, ampak delovalo je na vseh masinah kar sem jih sprobal.
okvirna implementacija v pythonu:
# kreiranje socketa in nastavitev opcije SO_TIMESTAMP # vrednost SO_TIMESTAMP je potrebno najti v kernel source kodi, ker je ni v socket modulu s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_ICMP) s.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1) s.setsockopt(socket.SOL_SOCKET, 29, 1) # SO_TIMESTAMP = 29 # ko je socket pripravljen za read dobimo paket v data in timestamp v ancilary messagu # python3.5 data, anc_msgs, msg_flags, address = s.recvmsg(65535, 65535) # nizje verzije pythona import socketextra data, anc_msgs, msg_flags, address = socketextra.recvmsg(s, 65535, 65535) # socketextra ima bug in vedno vrne None kot address # anc_msgs je lista sporocil, ki so toupli. vzamemo prvo sporocilo. # dokumentacija nam pove, da iscemo 3ji element v tuplu # 3ji element je v bistvu binary niz, ki predstavlja C struct in ga razpakiramo s struct.unpack seconds, microseconds = struct.unpack('ll', anc_msgs[0][2]) # pokalkuliramo, da dobimo unix timestamp recv_time = seconds + microseconds / 1000000.0
Zgodovina sprememb…
- spremenil: ragezor ()
Vredno ogleda ...
Tema | Ogledi | Zadnje sporočilo | |
---|---|---|---|
Tema | Ogledi | Zadnje sporočilo | |
» | Python primer async/awaitOddelek: Programiranje | 2129 (1235) | jype |
» | [Python3] Izvajanje ukazov po določenem časuOddelek: Programiranje | 1447 (1057) | noraguta |
» | Težave z Amisovim modemomOddelek: Pomoč in nasveti | 5372 (4954) | 111111111111 |
» | If stavek pingOddelek: Programiranje | 2060 (1525) | AndrejO |
» | Kateri programski jezik?Oddelek: Programiranje | 4545 (3158) | kopernik |