Re: [Python-de] select.epoll() vs async framework (PostgreSQL)
On 2018-01-19 16:09, Sven R. Kunze <srkunze@mail.de> wrote:
On 19.01.2018 06:47, Peter J. Holzer wrote:
Nein, aber die Idee ist nicht so absurd, wie Du glaubst.
(Abgesehen davon glaube ich nicht, dass Dein Vorposter das wollte. Für micht klingt das eher, als wollte er einen HTTP-Parser und/oder -Generator im Kernel haben (wobei mir nicht ganz klar ist, wozu) und sowas würde als Teil etwa einer Firewall- oder WebDAV-Komponente wenig Stirnrunzeln auslösen.)
Damit der konkrete Anwendungsfall klarer wird. Aufgabe war/ist es URLs asynchron zu callen und den Rückgabewert in eine DB zu schreiben (siehe erster Post dieses Threads).
Nun stellte sich leider heraus, dass eine URL zu requesten nicht wirklich einfach ist. Die Lib "requests" auf jeden Fall ist ziemlich blocking und insbesondere muss es mehrere blockierende Dinge nacheinander tun. Im einfachsten Fall: 1) DNS lookup 2) open connection 3) push request data on socket
Also einen HTTP-Client bzw. Proxy (nach außen soll er HTTP sprechen, zur Applikation (möglicherweise) etwas anderes).
Meine naive Lösungsvorstellung war: ein Socket, der genau alles das kann, was requests kann.
Du musst also "alles, wes requests kann" auf ein Protokoll abbilden. Wie wird dieses Protokoll aussehen? Da requests ein API für HTTP ist, würde ich annehmen, dass man natürlicherweise entweder bei HTTP oder etwas sehr ähnlichem landet (ein paar historische Unfälle könnte man sicher beheben: Z.B. braucht man nicht 3 verschiedene Methoden, das Ende eines Requests anzuzeigen).
Damit würde die select-loop extrem einfach werden,
Glaube ich nicht, denn Du musst jetzt dieses Protokoll sprechen. Das wird aber ähnlich komplex sein wie HTTP, also nicht "extrem einfach". Es sei denn, man lässt Features weg: Aber dann kann es nicht mehr alles, was requests kann, und wäre nur mehr für spezielle Fälle brauchbar (die zwar wahrscheinlich eh 90% aller Anwendungen ausmachen, aber wenn man sowas als Funktion des Betriebssystems zur Verfügung stellt, dann will man natürlich 100% abdecken). Und da denke ich mir, Du kannst gleich HTTP sprechen (das macht man ja auch über einen Socket). Und weil oben schon das Stichwort Proxy gefallen ist: Was spricht dagegen einen solchen Procy mit den Features, die Du haben willst, du schreiben?
Die andere Seite (nämlich das NOTIFY von PostgreSQL) ist genau so einfach. 1 Socket, von dem man liest.
Hmm? Auf dem Socket musst Du aber das PostgreSQL-Protokoll sprechen. Ich nehme an, dafür verwendest Du psycopg2 und hast das nicht selbst implementiert? Das scheint mir jetzt nicht sonderlich event-loop-freundlich zu sein. Wenn Du nur NOTIFY brauchst, ok. Und einfache Querys gehen auch noch (dürften aber schon etwas komplexer sein). Aber sobald Du Transaktionen brauchst, hast Du (laut Manual) verloren. Da würde mich interessieren, wie das mit async/await aussieht: Laut Manual gibt es "Support for coroutine libraries", aber das ist recht vage und asyncio wird nicht mal erwähnt. Hat jemand damit praktische Erfahrungen? hp -- _ | Peter J. Holzer | Fluch der elektronischen Textverarbeitung: |_|_) | | Man feilt solange an seinen Text um, bis | | | hjp@hjp.at | die Satzbestandteile des Satzes nicht mehr __/ | http://www.hjp.at/ | zusammenpaßt. -- Ralph Babel
On 20.01.2018 09:53, Peter J. Holzer wrote:
Also einen HTTP-Client bzw. Proxy (nach außen soll er HTTP sprechen, zur Applikation (möglicherweise) etwas anderes).
Den Socket hatte ich nur deswegen im Kopf, weil ich mich mit select.select gut auskenne. Der Daemon würde das notify von Progress lesen, die URL in einen HTTP-Request einpacken und diesen dann auf einen HTTP-Socket schreiben. Dann kann der HTTP-Socket seine DNS und andere blockierende Operationen ausführen, aber der Socket, von dem der Daemon lesen würde, würde eben leer sein. Wo wir gerade darüber reden, fällt mir natürlich auf, dass die Verknüpfung von Request zu Response ein Problem sein könnte. Da bräuchte man dann wohl mehrere Socket-Paare, oder Header-Field-Matching.
Und weil oben schon das Stichwort Proxy gefallen ist: Was spricht dagegen einen solchen Procy mit den Features, die Du haben willst, du schreiben?
Ich hoffe doch, dass so etwas wie ein Proxy bereits existiert. ;-)
Die andere Seite (nämlich das NOTIFY von PostgreSQL) ist genau so einfach. 1 Socket, von dem man liest. Hmm? Auf dem Socket musst Du aber das PostgreSQL-Protokoll sprechen. Ich nehme an, dafür verwendest Du psycopg2 und hast das nicht selbst implementiert?
Natürlich. HTTP- oder PostgreSQL-Protokoll wäre natürlich durch eine Bibliothek gekapselt. So etwas macht man heutzutage eigentlich nicht mehr selbst. Das Protokoll ist ja auch gar nicht das Problem. Solche Sockets müsste man prinzipiell haben, damit man nach dem üblichen Verfahren mit select/epoll arbeiten kann.
Das scheint mir jetzt nicht sonderlich event-loop-freundlich zu sein. Wenn Du nur NOTIFY brauchst, ok. Und einfache Querys gehen auch noch (dürften aber schon etwas komplexer sein). Aber sobald Du Transaktionen brauchst, hast Du (laut Manual) verloren.
Freilich, das wäre ja auch bei einem Daemon dieser Natur nicht wirklich von Nöten.
Da würde mich interessieren, wie das mit async/await aussieht: Laut Manual gibt es "Support for coroutine libraries", aber das ist recht vage und asyncio wird nicht mal erwähnt. Hat jemand damit praktische Erfahrungen?
Meinst du async/await oder asyncio? Referenzierst du http://initd.org/psycopg/docs/advanced.html#asynchronous-support und http://initd.org/psycopg/docs/advanced.html#support-for-coroutine-libraries? Dort sieht man wie man async ohne asyncio machen kann, indem man die Loop selbst schreibt, was jetzt ehrlich gesagt nicht wirklich kompliziert ist while True: select .... Asynchronous != coroutine, ersteres geht nämlich auch ohne zweiteres. ;-) Sven
participants (2)
-
Peter J. Holzer
-
Sven R. Kunze