The latest NGINX is an application server! ?? I measured the benchmark of NGINX Unit with PHP, Python, Go! !!

What is NGINX? ??

image.png

I will briefly explain the features of NGINX.

--Event-driven web server --Good at delivering static content --Often used as a reverse proxy --Second most used of all active sites (19.60%)

Reference: wikipedia nginx

In the past (although long ago) Apache was the strongest server industry. I'm not very familiar with it, but as the server became cheaper, the C10K problem became a hot topic in the industry and was adopted by Apache. The server with the pre-Fork architecture that used to be used can no longer handle a large number of requests. Among them, NGINX, which is an event-driven architecture, can handle a large number of requests and seems to have attracted attention. Therefore, NGINX receives the very beginning of the Web service request and reverse proxies it. It seems that the configuration is often taken. In addition, websites such as media need to respond at high speed, and there are many characteristics that are static as content, so it seems that NGINX may be adopted.

What is NGINX-Unit? ??

NGINX-Unit is a product newly announced on September 8, 2017. As its feature,

--NGINX Unit is an application server --Supports PHP, Python, Go --Server settings can be dynamically changed in real time using RESTful API and JSON

Quote: Application server "NGINX Unit" is open source from NGINX. Compatible with PHP, Go and Python. Support for Java and Node.js

It seems that there is a feature. In general, Web services often have a three-layer architecture. image.png

A server that only returns simple static HTML is called a Web server in a narrow sense, and a server that runs a program written in PHP or Python and can bind it to HTTP is called an application server. Until now, I was able to do something like "Run NGINX + gunicorn + Python." However, strictly speaking, WSGI server (application server) such as gunicorn and NGINX are only linked. In this example, it is an image that NGINX Unit replaces the gunicorn part. I have never heard of the feature of server setting by RESTful API on other servers. Generally, it is an image of putting a configuration file in / etc / conf and restarting.

Preparing the environment

We proceeded with the development environment while borrowing the wisdom of our predecessors.

I tried running PHP, Python, Golang with NGINX Unit

Mostly as per the official documentation. This time too, the environment will use pre-compiled binaries on Ubuntu.

$ wget http://nginx.org/keys/nginx_signing.key
$ sudo apt-key add nginx_signing.key

Add the following text to /etc/apt/sources.list

deb http://nginx.org/packages/mainline/ubuntu/ xenial nginx
deb-src http://nginx.org/packages/mainline/ubuntu/ xenial nginx

And install

$ sudo apt-get update
$ sudo apt-get install unit unit-dev

Start the server

$ sudo service unitd start

The survey took some time, but I think it's relatively easy to get into.

By the way, I also looked at the php and python versions of the NGINX Unit included above.

$ pwd
/usr/lib/unit/modules
$ ls
php.unit.so  python.unit.so

It seems that php and python so are included in / usr / lib / unit / modules. this

$ objdump -s php.unit.so  | less
$ objdump -s python.unit.so  | less

I read the binary dump visually. as a result,

It was a version like this. Probably because the official python of Ubuntu 16.04 is still 2.7 series. If you want to write a program in python3 series, is there no choice but to build from the source code?

Basic server settings

This time, the code and configuration file used in the benchmark are prepared in the repository.

https://github.com/kotauchisunsun/nginx_unit_bench

Setting up the server is very easy,

$ sudo curl -X PUT -d @php_config.json  \
       --unix-socket /run/control.unit.sock http://localhost/

Just throw json like this and you can set it without restarting the server. The points to note on Ubuntu are throwing with sudo and the socket working with /run/control.unit.sock. Also, json in the repository does not work as it is. The path of the source code to be moved and the path of the executable file are written as absolute paths, so please rewrite as appropriate.

benchmark

Benchmark languages are PHP, Python, Go. The application itself is very simple,

--PHP is "Hello PHP World !!" --Python is "Hello Python World !!" --Go is "Hello Go World !!"

It is an application that just outputs. ** What is the fastest bridge between the NGINX Unit and the programming language, making it as simple as possible? Check **.

The software used for benchmarking is Apache Bench

-Is the Serverless environment more than 600 times slower? ~ I tried benchmarking with Go, Node.js and Python! ~ -Introduction to serverless! Home serverless + serverless thumbnail server created in home S3 environment!

However, it is an easy-to-use load test tool that I used. The command looks like this

$ ab -n 100000 -c 100 http://localhost:8100/ 

Send 100,000 requests in 100 parallels. (Bench.sh in the repository is the execution script for benchmarking.)

Benchmark results

Language min Response Time[ms] mean Respones Time[ms] max Response Time[ms] Request Per Second
PHP 6 99 1,414 1005.30
Python 65 141 1,916 708.99
Go 48 106 2,567 946.90

image.png

image.png

Detailed data is placed in Repository as php.result, python.result, go.result.

Consideration

This may be a disappointing result, but ** the fastest language running on the NGINX Unit was PHP. ** For some reason, I understand. It looks at the code,

index.php


<?php
    echo "Hello PHP World!!";

wsgi.py


from flask import Flask

application = Flask(__name__)


@application.route("/")
def index():
    return "Hello Python World!!"

hello.go


package main

import (
	"fmt"
	"net/http"
	"unit"
)

func main() {
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprintf(w, "Hello Go World!!")
	})
	unit.ListenAndServe(":8300", nil)
}

It is. In the case of python, you need to create an application in the wsgi format. Therefore, it is essential to load Flask and wsgi modules. Also, Go is the same, and it is essential to bind with a module called "unit" for NGINX Unit. On the other hand, PHP does not load any libraries. Personally, I thought "Go running in binary would be the fastest". However, the Go is slow. And, considering that the min response time of PHP is unusually fast of 6 [ms], in summary, Python and Go were slow and PHP was the fastest because the ** module was used. You can see that **.

Summary

--I installed NGINX Unit on Ubuntu. --As a result of benchmarking by language, PHP> Go> Python. --It seems that PHP is the fastest because it loads less modules

The result was. After all, what was shocking was that "PHP was the fastest", but honestly PHP and Go are not so different in performance? I think. Ultimately, Go will be faster as you build the logic. I think. On the other hand, is Python a little slow? I have to feel that. Although not mentioned in the benchmark above, ** Go modules may fail to respond. ** I haven't tracked the cause so much, but during the load test

apr_socket_recv: Connection reset by peer (104)

Was output, and it failed with an error. Therefore, I re-benchmarked about 3 times in total. The NGINX Unit is still like the beta version, so I think this may happen. On the other hand, what I think is excellent is that you can set the server with REST Full API. This is fantastic. The bench was also easy to do. However, I wanted you to stick to the making of json a little more. As you can see by looking at the json for config in the repository, the notation of path is slightly different depending on the language. I'm addicted to it, but I hit the API with curl without noticing it, but the error message is unfriendly. The error message didn't tell me what part of json was wrong, so I had to stare at the official docs while looking like a plate myself, which was a pain. Anyway, once you get used to it, NGINX Unit may be easier. I don't like PHP. The reason is that you have to set open_base_dir etc. in php.ini (and you are often addicted to it), but that side can be completely ignored and you can run the source code of any path. The setting can also be specified in one shot with json, so it is very easy. This is also the case with Python, and it's a lot easier to set while holding the unfamiliar settings such as gunicorn and nginx. Moreover, since there is no need to restart the server, development is very easy and Try & Error can be done at high speed. It may be difficult to put it into production, but if it is a light product like a hackathon, it is easier to handle routing and settings than using a language built-in server, so I felt that it might be possible. Please feel it.

Recommended Posts

The latest NGINX is an application server! ?? I measured the benchmark of NGINX Unit with PHP, Python, Go! !!
I measured the speed of list comprehension, for and while with python2.7.
From the initial state of CentOS8 to running php python perl ruby with nginx
Since memory_profiler of python is heavy, I measured it
I measured the performance of 1 million documents with mongoDB
I thought about why Python self is necessary with the feeling of a Python interpreter
I built an application with Lambda that notifies LINE of "likes" using the Qiita API
I tried to find the entropy of the image with python
I tried "gamma correction" of the image with Python + OpenCV
I wrote the basic grammar of Python with Jupyter Lab
I evaluated the strategy of stock system trading with Python.
Let's run Fusion 360 with Python Part 11 Since there is no point along the path in the API, I thought of an alternative
I want to extract an arbitrary URL from the character string of the html source with python
Is the Serverless environment more than 600 times slower? ~ I tried benchmarking with Go, Node.js and Python! ~
I compared the speed of Hash with Topaz, Ruby and Python
I tried scraping the ranking of Qiita Advent Calendar with Python
March 14th is Pi Day. The story of calculating pi with python
I want to output the beginning of the next month with Python
I tried sending an email from the Sakura server with flask-mail
I tried to improve the efficiency of daily work with Python
I'm tired of Python, so I analyzed the data with nehan (corona related, is that word now?)
I tried to open the latest data of the Excel file managed by date in the folder with Python
I tried to output the rpm list of SSH login destination to an Excel sheet with Python + openpyxl.
I liked the tweet with python. ..
The story of remounting the application server
I replaced the numerical calculation of Python with Rust and compared the speed
Comparing the basic grammar of Python and Go in an easy-to-understand manner
I tried to get the authentication code of Qiita API with Python.
I tried to streamline the standard role of new employees with Python
I tried to get the movie information of TMDb API with Python
Get the return value of an external shell script (ls) with python3
[Introduction to Python] What is the method of repeating with the continue statement?
Explanation of creating an application for displaying images and drawing with Python
VS Code freezes & PC crashes when I start the server with go
The story of migrating from home server (MariaDB + Java) to AWS (DynamoDB + Python + PHP) with reduced monthly cost
Python> set> Convert with set ()> dictionary is only key> I was taught how to convert the values of dictionary to set / dir ({}) / help ({}) / help ({} .values)
I'm an amateur on the 14th day of python, but I want to try machine learning with scikit-learn
The story of making Python an exe
Check the existence of the file with python
I tried sending an email with python.
I didn't know the basics of Python
[python] [meta] Is the type of python a type?
The Python project template I think of.
Run python wsgi server on NGINX Unit
I compared the speed of go language web framework echo and python web framework flask
I tried to make a simple mail sending application with tkinter of Python
I want to send Gmail with Python, but I can't because of an error
With LINEBot, I made an app that informs me of the "bus time"
I tried to automatically send the literature of the new coronavirus to LINE with Python
I'm tired of Python, so I tried to analyze the data with nehan (I want to go live even with corona sickness-Part 2)
I'm tired of Python, so I tried to analyze the data with nehan (I want to go live even with corona sickness-Part 1)