Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

python Gevent – 高性能的Python并发框架 #65

Open
myyyy opened this issue Mar 16, 2018 · 0 comments
Open

python Gevent – 高性能的Python并发框架 #65

myyyy opened this issue Mar 16, 2018 · 0 comments
Labels

Comments

@myyyy
Copy link
Owner

@myyyy myyyy commented Mar 16, 2018

话说gevent也没个logo啥的,于是就摆了这张图= =|||,首先这是一种叫做greenlet的鸟,而在python里,按照官方解释greenlet是轻量级的并行编程,而gevent呢,就是利用greenlet实现的基于协程的python的网络library,好了,关系理清了。。。

话说pycon没有白去阿,了解了很多以前不知道的东西,比如说协程,gevent,greenlet,eventlet。说说协程,进程和线程大家平时了解的都比较多,而协程算是一种轻量级进程,但又不能叫进程,因为操作系统并不知道它的存在。什么意思呢,就是说,协程像是一种在程序级别来模拟系统级别的进程,由于是单进程,并且少了上下文切换,于是相对来说系统消耗很少,而且网上的各种测试也表明,协程确实拥有惊人的速度。并且在实现过程中,协程可以用以前同步思路的写法,而运行起来确是异步的,也确实很有意思。话说有一种说法就是说进化历程是多进程->多线程->异步->协程,暂且不论说的对不对,单从诸多赞誉来看,协程还是有必要理解一下的。

比较惭愧,greenlet没怎么看就直接看gevent,官方文档还是可以看看的,尤其是源码里的examples都相当不错,有助于理解gevent的使用。

gevent封装了很多很方便的接口,其中一个就是monkey

from gevent import monkey
monkey.patch_all()

这样两行,就可以使用python以前的socket之类的,因为gevent已经给你自动转化了,真是超级方便阿。

而且安装gevent也是很方便,首先安装依赖libevent和greenlet,再利用pypi安装即可

sudo apt-get install libevent-dev
sudo apt-get install python-dev
sudo easy-install gevent

然后,gevent中的event,有wait,set等api,方便你可以让某些协程在某些地方等待条件,然后用另一个去唤醒他们。

再就是gevent实现了wsgi可以很方便的当作python的web server服务器使。

最后放送一个我利用gevent实现的一个带有缓存的dns server

 # -*- coding: UTF-8 -*-
 
import gevent
import dnslib
from gevent import socket
from gevent import event
 
rev=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
rev.bind(('',53))
ip=[]
cur=0
 
def preload():
    for i in open('ip'):
        ip.append(i)
    print "load "+str(len(ip))+" ip"
 
def send_request(data):
    global cur
    ret=rev.sendto(data,(ip[cur],53))
    cur=(cur+1)%len(ip)
 
class Cache:
    def __init__(self):
        self.c={}
    def get(self,key):
        return self.c.get(key,None)
    def set(self,key,value):
        self.c[key]=value
    def remove(self,key):
        self.c.pop(key,None)
 
cache=Cache()
 
def handle_request(s,data,addr):
    req=dnslib.DNSRecord.parse(data)
    qname=str(req.q.qname)
    qid=req.header.id
    ret=cache.get(qname)
    if ret:
        ret=dnslib.DNSRecord.parse(ret)
        ret.header.id=qid;
        s.sendto(ret.pack(),addr)
    else:
        e=event.Event()
        cache.set(qname+"e",e)
        send_request(data)
        e.wait(60)
        tmp=cache.get(qname)
        if tmp:
            tmp=dnslib.DNSRecord.parse(tmp)
            tmp.header.id=qid;
            s.sendto(tmp.pack(),addr)
 
def handle_response(data):
    req=dnslib.DNSRecord.parse(data)
    qname=str(req.q.qname)
    print qname
    cache.set(qname,data)
    e=cache.get(qname+"e")
    cache.remove(qname+"e")
    if e:
        e.set()
        e.clear()
 
def handler(s,data,addr):
    req=dnslib.DNSRecord.parse(data)
    if req.header.qr:
        handle_response(data)
    else:handle_request(s,data,addr)
 
def main():
    preload()
    while True:
        data,addr=rev.recvfrom(8192)
        gevent.spawn(handler,rev,data,addr)
 
if __name__ == '__main__':
    main()

这个是直接利用了dict来作为缓存查询了,在这里还有我将dict换成redis持久化实现的另一个版本(话说redis的python api也可以利用pypi安装,pypi这真是个好东西阿),话说可以将这段代码放到国外的服务器上去运行,然后修改dns的地址去指向它,然后你懂的。。。

转载自

@myyyy myyyy changed the title 1 python Gevent – 高性能的Python并发框架 Mar 16, 2018
@myyyy myyyy added the python label Mar 16, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
1 participant
You can’t perform that action at this time.