Analysis of Python eventlet concurrency principle

Source: Internet
Author: User
Tags epoll
recently in learning eventlet This tough stuff, see some of my colleagues finishing. So stick it out and share it with us ~
Motivation

The time task (Periodic_task) and Heartbeat task (Report_state) implemented in the Nova service on the 114.113.199.11 server based on the Python eventlet are a eventlet instance of Greenthread.

At present on the server, some tasks in the Nova timed task have too long execution time, which causes the heartbeat task to not run on time.

If Eventlet is a completely similar thread/process parallel library, this problem should not occur, we need to study the concurrency implementation of Eventlet, understand its concurrency implementation principle, to avoid similar problems in the future. Analysis

After reading the Eventlet source code, you can know that Eventlet relies heavily on another 2 Python package:greenlet python-epoll (or other similar asynchronous IO libraries, such as poll/select, etc.)

There are 3 main jobs: Encapsulating Greenlet Encapsulation Epoll rewriting the associated module in the Python standard library to support Epoll Epoll

Epoll is an event-based asynchronous IO library implemented by Linux, and has been improved on the previous similar asynchronous IO Library poll.

The following two examples show how to use Epoll to overwrite blocked IO operations with Epoll as asynchronous non-blocking. (taken from official documents) Blocking IO

Import socket EOL1 = B ' \ n ' EOL2 = B ' \n\r\n ' response = B ' http/1.0 Ok\r\ndate:mon, 1 1996 01:01:01

    gmt\r\n ' response + = B ' content-type:text/plain\r\ncontent-length:13\r\n\r\n ' response + = B ' Hello, world! ' ServerSocket = Socket.socket (socket.af_inet, socket. SOCK_STREAM) serversocket.setsockopt (socket. Sol_socket, SOCKET.
            SO_REUSEADDR, 1) serversocket.bind ((' 0.0.0.0 ', 8080)) Serversocket.listen (1) try:while True: Connectiontoclient, address = serversocket.accept () request = B "While EOL1 not in Request a nd EOL2 not in Request:request + + + CONNECTIONTOCLIENT.RECV (1024) print ('-' *40 + ' \ n ' + request
        . Decode () [: -2]) connectiontoclient.send (response) Connectiontoclient.close () Finally: Serversocket.close ()

This example implements a simple Web server that listens on 8080 ports. Receives a connection from port 8080 through a dead loop and returns the result.

It should be noted that the program

Connectiontoclient, address = serversocket.accept ()

This line blocks until a new connection is obtained, and the program continues to run down.

Also, this program can only handle one connection at a time, if a lot of users access 8080 ports simultaneously, you must process these connections sequentially, after a successful return of the previous connection, the subsequent connection will not be processed.

The following example will overwrite this simple Web server with Epoll non-blocking IO by using Epoll

Import socket, select EOL1 = B ' \ n ' EOL2 = B ' \n\r\n ' response = B ' http/1.0 Ok\r\ndate:mon, 1 1996 GMT

\ r \ n ' response + B ' content-type:text/plain\r\ncontent-length:13\r\n\r\n ' response + = B ' Hello, world! ' ServerSocket = Socket.socket (socket.af_inet, socket. SOCK_STREAM) serversocket.setsockopt (socket. Sol_socket, SOCKET. SO_REUSEADDR, 1) serversocket.bind ((' 0.0.0.0 ', 8080)) Serversocket.listen (1) serversocket.setblocking (0) Epoll = Select.epoll () Epoll.register (Serversocket.fileno (), select. Epollin) try:connections = {}; requests = {}; responses = {} While true:events = Epoll.poll (1) for Fileno, event in events:if Fileno = = Serversocket.fileno (): connection, address = serversocket.accept () Connection.setblockin G (0) Epoll.register (Connection.fileno (), select. 
Epollin) Connections[connection.fileno ()] = Connection Requests[connection.fileno ()] = B '                Responses[connection.fileno ()] = Response Elif Event & Select.  Epollin:requests[fileno] + = CONNECTIONS[FILENO].RECV (1024) if EOL1 in Requests[fileno] or EOL2 in Requests[fileno]: epoll.modify (Fileno, select. epollout) Print ('-' *40 + ' \ n ' + requests[fileno].decode () [: -2]) elif event & Select. Epollout:byteswritten = Connections[fileno].send (Responses[fileno]) Responses[fileno] = R Esponses[fileno][byteswritten:] If Len (Responses[fileno]) = = 0:epoll.modify (Fileno, 0 ) Connections[fileno].shutdown (socket. SHUT_RDWR) elif Event & Select. EPOLLHUP:epoll.unregister (Fileno) connections[fileno].close () del Connect
 Ions[fileno] Finally:epoll.unregister (Serversocket.fileno ()) Epoll.close () Serversocket.close ()

As you can see, the example first uses serversocket.setblocking (0) to set the socket to asynchronous mode, and then creates a epoll with Select.epoll (), and then uses the Epoll.register ( Serversocket.fileno (), select. Epollin the IO input event (select) on the socket. Epollin) registered in the Epoll. When you do this, you can rewrite the main loop blocking the Socket.accept () in the example above into a Epoll loop based on an asynchronous IO event.

Events = Epoll.poll (1)

Simply put, if a lot of users are connected to port 8080 at the same time, the program will accept () all the socket connections, and then use this line of code to place the IO event socket into the events and process it later in the loop. Sockets that do not occur with IO events do not process in the loop. This allows a simple concurrent Web server to be implemented using Epoll.

Note that the concurrency mentioned here is not quite the same as what we normally understand about thread/process concurrency, or, more precisely, io multiplexing . Greenlet

Greentlet is one of the basic libraries in python that implements what we call "Coroutine (coprocessor)."

See the following example to understand.

 from Greenlet import Greenlet def test1 (): Print Gr2.switch () print def test2 (): Print Gr1.switch () print Gr1 = Greenlet (test1) GR2 = Greenlet (test2) GR1.SW Itch () 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.