Updated "Introduction to Python Web Application Homebrew for Slow 3rd Year Web Engineers"

Updated the book

Chapter "Parallel Requests" has been updated.

If you want to read more, please like the book or follow the author ;-)


The following is an excerpt of the contents of the book.


current problem

Python reads the source code in order from the top, and when the processing of one line is completed, it executes the next line, and so on.

Therefore, with the current source code,

--Accept connections from clients (. accept ()) --Handle requests from clients (.handle_client ()) -End communication with the client (after handling exceptions if necessary) (.close ()) --Accept connections from clients (. accept ())

Be sure to follow this order.

In other words, ** "The next request will not be accepted until all the processing of one request is completed" ** It means that.

This becomes a big problem as the number of requests increases.


For example, suppose 10 requests come in at the same time.

At this point, the server starts processing the first request that comes first-come-first-served. And if this first request is a very time consuming process, the next nine requests will have to wait until the process is complete.

A common case is to throw a query with complex search criteria to a DB server and wait 30 seconds for a response. Overall performance will be much better if the machine handles the other 9 requests for 30 seconds waiting for a response from the DB.

In this way, while a certain program is performing a certain process, executing another program behind the scenes is called ** parallel processing ** or ** parallel processing **.

This parallel processing is implemented as a matter of course on a general Web server, so let's implement it as well.

Columns: "Parallel processing" and "Parallel processing"

Let me explain the difference between "parallel processing" and "parallel processing".

In general, processing multiple monogoto at the same time is called "parallel processing".

In the computer world, the CPU is responsible for all the actual processing, but one CPU can always do only one job at a time. Therefore, in a strict sense, "parallel processing" cannot be realized with one CPU.

However, from a human sense, CPU processing is so fast that " If you do this job and become "waiting", switch to another job, and if you become "waiting" again, do another job. " By switching the processes to be tackled one after another, it can be seen by the human eye as if they are doing tasks at the same time. (Depending on the OS, the CPU switches jobs one after another in about 0.2 seconds or less)

In the old days, it was natural for one computer to have one CPU, so in the computer world, there was no particular problem in reading this "pseudo-parallel processing" simply as "parallel processing". However, around 2000, with the release / spread of dual-core CPUs, two or four CPUs (more accurately, CPU cores) came to be installed in one computer, and by operating these CPUs at the same time, "pseudo" It has become possible to perform "real parallel processing" instead of "parallel processing".

Therefore, programmers call "pseudo-parallel processing" "** parallel ** processing" in order to distinguish between "pseudo-parallel processing" and "true parallel processing", which were previously read as "parallel processing". It came to be.

It is extremely difficult for humans to distinguish between "parallel processing" and "parallel processing" on the surface, and there is almost no need to distinguish between the two in programming until machine performance tuning is required. Therefore, in this document, these are unified and referred to as "parallel processing" without any particular distinction.

It's a very complicated story about when parallel processing and parallel processing are used properly, and how they affect performance. I will omit it in this book. There is a great deal of information available on the internet on this topic, so if you are interested, check it out.

Source code

Here is the source code that has been improved to perform parallel processing. Please note that there are two files.

study/WebServer.py https://github.com/bigen1925/introduction-to-web-application-with-python/blob/main/codes/chapter13/WebServer2.py

study/WorkerThread.py https://github.com/bigen1925/introduction-to-web-application-with-python/blob/main/codes/chapter13/WebServer2.py

Commentary

Common

Since the files are separated, the characters Server: and Worker: are output to the log showing the processing record, respectively. Example)

print("=== Server:Start the server===")
print("=== Worker:End communication with the client===")

WebServer.py

Lines 28-31

                #Create a thread to handle the client
                thread = WorkerThread(client_socket)
                #Run thread
                thread.start()

Create a ** thread ** that processes the client that established the connection, and start processing the thread. The processing that was done by the method .handle_client () until the last time and the exception handling before and after have all been moved to the processing in this thread.

A ** thread ** is a processing sequence that allows a computer to perform processing in parallel, and will be explained in detail later.

WorkerThread.py

9th line-57th line

class WorkerThread(Thread):
    #Directory with executable files
    BASE_DIR = os.path.dirname(os.path.abspath(__file__))
    #Directory to put files for static distribution
    DOCUMENT_ROOT = os.path.join(BASE_DIR, "static")

    def __init__(self, client_socket: socket):
        super().__init__()

        self.client_socket = client_socket

    def run(self) -> None:
        """
Receives a socket connected to the client as an argument
Process the request and send the response
        """
        
        #Processing corresponding to the client...

Thread is a class included in the threading module, which is a built-in library of python, and is a base class for easily creating threads.

When using Thread, create a class that inherits Thread and override the .run () method. An instance of this class creates a new thread by calling the .start () method and starts the processing of the .run () method.


The CPU cannot process programs executed in one thread in parallel, but programs executed in multiple threads can be processed in parallel.

Previously, the WebServer class handled all client responses sequentially within a single thread.

However, from this time, although the WebServer class can establish a connection with the client by using a thread, the response to the request content is processed in parallel by another thread.

This avoids the situation where one request is being processed for a long time and no other request is accepted.

Column: Things to keep in mind when working with threads

Basically, the processing of different threads runs as separate programs, so even if an exception occurs in one thread, it will not be propagated to another thread.

For example, in the past, requests were processed in the same thread, so if an exception occurred during request processing, the main processing (request reception processing) would have ended unless exception handling was performed. From this time, requests are processed in separate threads, so even if an exception occurs while processing a request in a certain thread, if there is no exception handling, that thread will just terminate and the main thread will be affected. there is not.

At first glance, it may seem grateful, but it shouldn't continue in the event of an anomaly that affects the entire server.

Be sensitive to exception handling when using threads.


Also, if you branch threads more and more, the process will not be infinitely fast.

There is a limit to the amount that the CPU can process at the same time. In a situation where most of the processes executed in parallel use a large amount of CPU, there are cases where the amount of CPU processing reaches the limit and parallel execution is delayed, and the performance does not improve or decreases. Processing that causes the CPU performance to become a bottleneck and reaches the limit of processing speed is called CPU bound processing.

For Web services that have a lot of CPU-bound processing, if you increase the number of threads unnecessarily, the amount of CPU processing may reach its limit and affect the execution speed of other programs. This is to prevent many web servers from setting limits on the number of threads and processes.

Be careful about how many thread branches your program does in the worst case.

In this book as well, you should originally set an upper limit on the number of threads that can be branched, and python provides a class called ThreadPoolExecutor for that purpose. If you are interested, please check it out.

Try to move

Let's actually move it.


Continue with Book!

Chapter "Parallel Requests"

Recommended Posts

Updated "Introduction to Python Web Application Homebrew for Slow 3rd Year Web Engineers"
Updated "Introduction to Python Web Application Homebrew for Slow 3rd Year Web Engineers"
Updated "Introduction to Python Web Application Homebrew for Slow 3rd Year Web Engineers"
Updated "Introduction to Python Web Application Homebrew for Slow 3rd Year Web Engineers"
Updated "Introduction to Python Web Application Homebrew for Slow 3rd Year Web Engineers"
Updated "Introduction to Python Web Application Homebrew for Slow 3rd Year Web Engineers"
Updated "Introduction to Python Web Application Homebrew for Slow 3rd Year Web Engineers"
[Introduction to Udemy Python3 + Application] 43. for else statement
Introduction to Python For, While
[Introduction to Udemy Python3 + Application] 42. for statement, break statement, and continue statement
[Introduction to Udemy Python 3 + Application] 58. Lambda
[Introduction to Udemy Python 3 + Application] 31. Comments
[Introduction to Udemy Python 3 + Application] 57. Decorator
[Introduction to Udemy Python 3 + Application] 56. Closure
[Introduction to Udemy Python3 + Application] 59. Generator
[Introduction to Udemy Python 3 + Application] Summary
An introduction to Python for non-engineers
Easy-to-understand explanation of Python Web application (Django) even for beginners (5) [Introduction to DB operation with Django shell]
[Introduction to Udemy Python3 + Application] 18. List methods
[Introduction to Udemy Python3 + Application] 63. Generator comprehension
[Introduction to Udemy Python3 + Application] 25. Dictionary-type method
[Introduction to Udemy Python3 + Application] 33. if statement
[Introduction to Udemy Python3 + Application] 13. Character method
[Introduction to Udemy Python3 + Application] 55. In-function functions
[Introduction to Udemy Python3 + Application] 48. Function definition
[Introduction to Udemy Python 3 + Application] 10. Numerical values
[Introduction to Udemy Python3 + Application] 41. Input function
[Introduction to Udemy Python3 + Application] 17. List operation
[Introduction to Udemy Python3 + Application] 65. Exception handling
[Introduction to Udemy Python3 + Application] 11. Character strings
[Introduction to Udemy Python3 + Application] 44. range function
[Introduction to Udemy Python3 + Application] 46. Zip function
[Introduction to Udemy Python3 + Application] 24. Dictionary type
[Python] Web application design for machine learning
An introduction to Python for machine learning
[Introduction to Udemy Python3 + Application] 8. Variable declaration
[Introduction to Udemy Python3 + Application] 29. Set method
[Introduction to Udemy Python3 + Application] 16. List type
[Introduction to Udemy Python3 + Application] 61. Dictionary comprehension
[Introduction to Udemy Python 3 + Application] 22. Tuple unpacking
An introduction to Python for C programmers
[Introduction to Udemy Python3 + Application] 47. Process the dictionary with a for statement
Take the free "Introduction to Python for Machine Learning" online until 4/27 application
An introduction to self-made Python web applications for a sluggish third-year web engineer
Easy-to-understand explanation of Python web application (Django) even for beginners (4) [Routing settings / Introduction to MTV design patterns]
Updated to Python 2.7.9
[Introduction to Udemy Python 3 + Application] 26. Copy of dictionary
[Introduction to Udemy Python3 + Application] 23. How to use tuples
[Introduction to Udemy Python3 + Application] 60. List comprehension notation
[Introduction to Udemy Python 3 + Application] 19. Copy of list
[Introduction to Udemy Python 3 + Application] 38. When judging None
[Introduction to Udemy Python3 + Application] 40.while else statement
[Introduction to Udemy Python3 + Application] 62. Set comprehension notation
Steps to develop a web application in Python
[Introduction to Udemy Python3 + Application] 64. Namespace and Scope
[Introduction to Python3 Day 20] Chapter 9 Unraveling the Web (9.1-9.4)
[Introduction to Udemy Python3 + Application] 67. Command line arguments
[Introduction to Udemy Python3 + Application] 9. First, print with print
Introduction to Programming (Python) TA Tendency for beginners
[Introduction to Udemy Python 3 + Application] 54. What is Docstrings?
[Introduction to Udemy Python3 + Application] 37. Techniques for determining that there is no value