Use a simple web chat to talk about Python, Golang, Nodejs async

Source: Internet
Author: User
Tags joins one table
This is a creation in Article, where the information may have evolved or changed.

In web programming, there are often business needs to do asynchronous operations when processing requests, such as long-time IO operations, such as the completion of asynchronous execution before the end of the request to return response to the client, in this process, the client and the server has maintained a connection is not released, that is, the current request in the The client's point of view is blocked until the request is over.

The most important feature of being called Async is that the server can continue to process other request without being blocked .

Different languages handle this asynchronous scenario in a very different way, with common processing strategies: Message Sharing (asynchronous task queue), multithreaded multi-process, event (Linux Signals,nodejs event loop), Coroutine (Return to future, Promise represents the future state of program execution), where Coroutine is the most widely used, and this is the subject of today's article.

What is Coroutine? It is simply a program that can be freely suspend, execute, and kill at certain times. The program controls the Coroutine as if the operating system controls the process, but at a much lower cost. This is also an important reason why many languages support asynchronous operations in a coroutine way, including Golang, Python, JavaScript (ES6), Erlang, and so on.

Talk is cheap, show me your code. Here we use a very simple Web chat demo app to table one table Golang, Python, Nodejs async.

A simple description of the Chat demo app

Demo is just to illustrate how coroutine is applied in different languages, so the scene is very simple: a content input box, any client sent messages can be displayed in other client.

Project Address

Https://github.com/zhyq0826/chat-app-tutorial

How the Chat demo app works

Two main APIs:

    1. /a/message/newFor message sending, this is called message-new
    2. /a/message/updatesFor message acceptance, this is called message-update

The Client obtains the latest message from the server side via Message-update, and if there is no new message, when the request is suspended, waiting for the new message to be sent, when a new message arrives, the latest message is obtained, the connection is disconnected, and the request is re-requested after a certain interval. The server continues to fetch new messages and repeats the previous procedure.

Because Message-update may take a long time to wait while retrieving a message from the server, the server will always hold the client's connection not released, so requests from the Message-update client cannot block the server from processing other Request, and the message-update needs to hang until no message arrives.

the process of handling message-update by the Server is an asynchronous process .

Implementation of Python

Python uses yield to implement coroutine, but to implement Coroutine in the Web requires special handling, where we use Tornado, a web framework that supports asynchronous network, to implement Message-update of the process.

A future in Tornado represents a result of the next, in the process of an asynchronous request, the yield will resolve the futures, and if future is not completed, the request will continue to wait.

 12345678910 
  @gen. coroutine #1  def  post   (self) :  cursor = self.get_argument (, none ) # Save the future returned By wait_for_messages so we can cancel the  # it in wait_for_messages  self.future = GL Obal_message_buffer.wait_for_messages (cursor=cursor) messages = yield  self.future span class= "comment" > #2  if  self.request.connection.stream.closed (): return  self.write (Dict (messages=messages)) 

#1The tornado-specific gen.coroutine allows the current request to support Coroutine, which #2 is the future execution result of the current request waiting, each message-update client through Global_message_buffer The call of the. Wait_for_messages generates a future, and then joins the list of message waits, as long as the next unresolved completion, the request will be suspended, Tornado is to complete an asynchronous request through yield and future mates.

The process of understanding how yield is waiting for the future to be completed is actually the process of understanding how Python generator is parsed, and details we have the opportunity to watch.

The realization of Golang

Golang is born on the language level support Coroutine go func() can open coroutine execution, is not very simple, is not very exciting, compared to the tornado must be specially handled to be pleasing more, and go comes with the net/http package implementation of the HTTP request Also born to support Coroutine, there is no need for a third-party library like Tornado to support it (this is Python 2). Golang more than Python is that it is more exciting to support the use of channel communication between Coroutine.

 1234567 
 func  messageupdateshandler   (w http. Responsewriter, R *http. Request)   {client: = Client{id:uuid. NewV4 (). String (), C: make  (chan  []byte )} #1  messagebuffer.newwaiter (&client) #2  msg: = <-client.c //pending request waiting for the message to come #3  W.header (). Set ( "Content-type" , ) W.write (msg)} 

#1A unique identity and channel is generated for each client, and then the client joins the message #2 waiting list waiting for the message to arrive, which #3 is the key point of the pending request: The message waiting for the channel. Channel communication is blocked by default, that is, the current message-update this coroutine will be #3 waiting for the suspension will not be executed, also reached the client connection can not be broken requirements.

The realization of Nodejs

Nodejs is inherently asynchronous, and through callback to complete the reception and execution of asynchronous notifications. For demonstration convenience we use express, in Express if a request is not actively invoked res.end or res.send , the res.json request will not end. How do I request to know when the message arrives and need response in Nodejs? Python we use the future, Golang with the channel, NODEJS implementation is not only one, where we use the event and Promise.

The Promise is similar to the future, which represents the execution of the next, and the execution results are notified by resolve and reject after the execution is complete, then or catch. Promise can effectively solve the problem that callback nesting in Nodejs and asynchronous execution error cannot be thrown out.

Promise as a specification, Nodejs in a variety of third-party libraries have been implemented, where we used the Bluebird this library.

The event is a common programming model in Nodejs, and the classmate who is familiar with JavaScript should know it very well, not fine table.

12345678910111213
App.post ('/a/message/updates ', function (req, res) {    var p = new Promise (function (resolve, reject) {        MessageBuffer.messageEmitter.on ("Newmessage", function (data) {  #1            resolve (data); #2        });    });    var client = Makeclient (uuidv4 (), p);    Messagebuffer.newwaiter (client);    P.then (function (data) {  #3        res.set (' Content-type ', ' Application/json ');        Res.json ({' Messages ': Data});})    ;

Each message-update client generates a Promise, and Promise executes Promise resolve after the message arrival event Newmessage #1 triggered #2 to inform the current client The news is coming.

Summary

The strategy for implementing async in three languages is not the same, with Golang's easiest to understand and easiest to implement, which is entirely proud of the support that go has for coroutine and the powerful channel communication. Python's implementation is based on Python 2, the use of coroutine in Python 3 has been greatly improved, but compared to Golang is still a drawback. Nodejs as a natural asynchronous back-end JavaScript, it would take a lot of skill to fully use the Promise to make the entire call stack work, but await/async in ES6 yield,es7 a great improvement in asynchronous operations, They are handled in a spirit of Python (it is said that the implementation of the ES6 is a bunch of Python programmers).

Examples of Python change from Tornado https://github.com/tornadoweb/tornado/tree/master/demos/chat

Chat-app Address Https://github.com/zhyq0826/chat-app-tutorial

Promise Bluebird Http://bluebirdjs.com/docs/getting-started.html

Tornado https://tornado.readthedocs.io/en/stable/guide/intro.html

Golang Channel HTTPS://TOUR.GOLANG.ORG/CONCURRENCY/2

Related Article

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.