Nginx catches everything: dynamic and static separation, compression, caching, black and white lists, cross-domain, high availability, performance optimization

  • introduction

  • 1. The concept of performance monster-Nginx is explained in simple terms

  • Two, Nginx environment construction

  • Three, Nginx reverse proxy - load balancing

  • Four, Nginx dynamic and static separation

  • Five, Nginx resource compression

  • Six, Nginx buffer

  • Seven, Nginx cache mechanism

  • Eight, Nginx implements IP black and white list

  • Nine, Nginx cross-domain configuration

  • 10. Nginx anti-leech design

  • Eleven, Nginx large file transfer configuration

  • 12. Nginx configures SLL certificate

  • Thirteen, Nginx high availability

  • Fourteen, Nginx performance optimization

  • Fifteen, put it at the end

introduction

The early business was deployed based on a single node. Since the access traffic in the early stage was not large, the single structure can also meet the demand. However, as the business grows, the traffic is also increasing, so the access pressure on a single server is also increasing. will gradually increase. Over time, if the performance of a single server cannot keep up with business growth, it will cause frequent online downtime, and eventually cause the system to be paralyzed and unable to continue processing user requests.

From the above description, there are two main problems: ① The deployment method of the single structure cannot carry the growing business traffic. ②When the back-end node goes down, the whole system will be paralyzed, making the whole project unavailable.

Therefore, in this context, the benefits that can be brought by the introduction of load balancing technology:

  • "High availability of the system:"  When a node goes down, the traffic can be quickly transferred to other nodes.

  • "High performance of the system:"  Multiple servers jointly provide services to the outside world, providing a higher throughput for the entire system.

  • "System scalability:"  When the business grows or slumps again, nodes can be added/reduced for flexible scaling.

OK~, since the introduction of load balancing technology can bring us such huge benefits, what options are there for us? There are mainly two load solutions, "hardware level and software level"  . There are more commonly used hardware loaders A10、F5, but these machines often cost tens of thousands or even hundreds of thousands of dollars, so generally large enterprises will adopt this solution, such as Banks, state-owned enterprises, central enterprises, etc. And the cost is limited, but still want to do load balancing projects, so it can be realized at the software level, such as typical, Nginxetc. The load of the software layer is also the focus of this article. After all, Bossone of our guidelines is: ""What can be achieved by technology is Try not to spend money.""

Of course, if you think this article is helpful to you, remember to like, bookmark, and pay attention to Sanlian!

1. The concept of performance monster-Nginx is explained in simple terms

NginxIt is the mainstream solution in the current load balancing technology. It is used by almost most projects. It Nginxis a lightweight high-performance HTTPreverse proxy server. At the same time, it is also a general-purpose proxy server that supports most protocols, such TCP、UDP、SMTP、HTTPSas .

NginxLike Redis, it is a product built based on the multiplexing model, so it also Redishas  the characteristics of "low resource occupation and high concurrency support"  . In theory, a single node Nginxsupports 5Wconcurrent connections at the same time, but in actual production In the environment, this value can indeed be achieved after the hardware foundation is in place and combined with simple tuning.

Let’s take a look at Nginxthe comparison of the client request processing flow before and after the introduction:

Originally, the client directly requests the target server, and the target server directly completes the request processing work, but after joining, Nginxall requests will go through first Nginx, and then be distributed to specific servers for processing, and then return after processing Nginx, and finally Nginxthe final The response result is returned to the client.

After understanding Nginxthe basic concepts, let's quickly build the environment and understand some Nginxadvanced features, such as dynamic and static separation, resource compression, cache configuration, IPblacklist, high availability guarantee, etc.

Two, Nginx environment construction

❶First create Nginxthe directory and enter:

[root@localhost]# mkdir /soft && mkdir /soft/nginx/  
[root@localhost]# cd /soft/nginx/  

❷ The downloaded Nginxinstallation package can be FTPuploaded to the offline environment package through the tool, or wgetthe installation package can be obtained online through the command:

[root@localhost]# wget https://nginx.org/download/nginx-1.21.6.tar.gz  

If there is no wgetcommand, it can yumbe installed by command:

[root@localhost]# yum -y install wget  

❸ Decompressed Nginxcompressed package:

[root@localhost]# tar -xvzf nginx-1.21.6.tar.gz  

❹ Download and install Nginxthe required dependencies and packages:

[root@localhost]# yum install --downloadonly --downloaddir=/soft/nginx/ gcc-c++  
[root@localhost]# yum install --downloadonly --downloaddir=/soft/nginx/ pcre pcre-devel4  
[root@localhost]# yum install --downloadonly --downloaddir=/soft/nginx/ zlib zlib-devel  
[root@localhost]# yum install --downloadonly --downloaddir=/soft/nginx/ openssl openssl-devel 

It can also yumbe downloaded with one click through the command (which method above is recommended):

[root@localhost]# yum -y install gcc zlib zlib-devel pcre-devel openssl openssl-devel  

After the execution is complete, and then lslook at the directory file, you will see a lot of dependencies:

Then rpmbuild the dependent packages one by one through the command, or install all the dependent packages with one click through the following command:

[root@localhost]# rpm -ivh --nodeps *.rpm  

❺Enter the decompressed nginxdirectory, and then execute Nginxthe configuration script to configure the environment in advance for the subsequent installation, which is located /usr/local/nginx/in the directory by default (you can customize the directory):

[root@localhost]# cd nginx-1.21.6  
[root@localhost]# ./configure --prefix=/soft/nginx/  

❻Compile and install Nginx:

[root@localhost]# make && make install  

❼Finally, go back to the previous /soft/nginx/directory and enter lsto see nginxthe files generated after the installation is complete.

❽ Modify the configuration file confin the directory generated after installation nginx.conf:

[root@localhost]# vi conf/nginx.conf  
    修改端口号:listen    80;  
 修改IP地址:server_name  你当前机器的本地IP(线上配置域名);  

❾Make configuration file and start Nginx:

[root@localhost]# sbin/nginx -c conf/nginx.conf  
[root@localhost]# ps aux | grep nginx  

NginxOther operating commands:

sbin/nginx -t -c conf/nginx.conf # 检测配置文件是否正常  
sbin/nginx -s reload -c conf/nginx.conf # 修改配置后平滑重启  
sbin/nginx -s quit # 优雅关闭Nginx,会在执行完当前的任务后再退出  
sbin/nginx -s stop # 强制终止Nginx,不管当前是否有任务在执行  

❿Open 80the port and update the firewall:

[root@localhost]# firewall-cmd --zone=public --add-port=80/tcp --permanent  
[root@localhost]# firewall-cmd --reload  
[root@localhost]# firewall-cmd --zone=public --list-ports  

Windows/MacIn your browser, directly enter IPthe address you just configured to visit Nginx:

Finally see the above Nginxwelcome interface, which means Nginxthe installation is complete. Recommended: Java Interview Questions

Three, Nginx reverse proxy - load balancing

First, SpringBoot+Freemarkerquickly build a project: springboot-web-nginx, and then create a file WEBin this project , the logic is as follows:IndexNginxController.java

@Controller  
public class IndexNginxController {  
    @Value("${server.port}")  
    private String port;  
  
    @RequestMapping("/")  
    public ModelAndView index(){  
        ModelAndView model = new ModelAndView();  
        model.addObject("port", port);  
        model.setViewName("index");  
        return model;  
    }  
}  

In Controllerthis class , there is a member variable: port, whose value is application.propertiesobtained from the configuration file server.port. When there is a request to access /resources, jump to the front-end indexpage and return the value with it.

The front-end index.ftlfile code is as follows:

<html>  
    <head>  
        <title>Nginx演示页面</title>  
        <link href="nginx_style.css" rel="stylesheet" type="text/css"/>  
    </head>  
    <body>  
        <div style="border: 2px solid red;margin: auto;width: 800px;text-align: center">  
            <div  id="nginx_title">  
                <h1>欢迎来到熊猫高级会所,我是竹子${port}号!</h1>  
            </div>  
        </div>  
    </body>  
</html>  

It can be seen from the above that its logic is not complicated, only the output is obtained from the response port.

OK~, after the prerequisite work is ready, simply modify nginx.confthe configuration:

upstream nginx_boot{  
   # 30s内检查心跳发送两次包,未回复就代表该机器宕机,请求分发权重比为1:2  
   server 192.168.0.000:8080 weight=100 max_fails=2 fail_timeout=30s;   
   server 192.168.0.000:8090 weight=200 max_fails=2 fail_timeout=30s;  
   # 这里的IP请配置成你WEB服务所在的机器IP  
}  
  
server {  
    location / {  
        root   html;  
        # 配置一下index的地址,最后加上index.ftl。  
        index  index.html index.htm index.jsp index.ftl;  
        proxy_set_header Host $host;  
        proxy_set_header X-Real-IP $remote_addr;  
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;  
        # 请求交给名为nginx_boot的upstream上  
        proxy_pass http://nginx_boot;  
    }  
}  

At this point, all the prerequisite work is ready, then start again Nginx, and then start two services. When webthe first service starts, in the configuration file, change the port number to . When the second service starts, change its port number to Change to .WEBapplication.properties8080WEB8090

Finally, let's see the effect:

Load Balancing Effect-Gift Demonstration

Because the weight of request distribution is configured, 8080、8090the weight ratio is 2:1, so the request will be distributed to each machine according to the weight ratio, that is, 8080once, 8090twice, 8080once...

Nginx request distribution principle

The request sent by the client 192.168.12.129will eventually be transformed into: http://192.168.12.129:80/, and then IPinitiate a request to the target, the process is as follows:

Principle of Request Distribution

  • Due to the Nginxlistening 192.168.12.129port 80, the request will eventually find Nginxthe process;

  • NginxlocationFirst, it will match according to the configured rules, and /locate location /{}the rules according to the client's request path;

  • Then according to locationthe configuration in this proxy_passwill find the nginx_bootnamed upstream;

  • Finally, according to upstreamthe configuration information in , the request is forwarded to WEBthe machine running the service for processing. Since multiple services are configured WEBand the weight value is configured, Nginxthe request will be distributed according to the weight ratio in turn.

Four, Nginx dynamic and static separation

Dynamic and static separation should be a performance optimization solution that is listened to more often, so first think about a question: "Why do you need to do dynamic and static separation? What are the benefits it brings?"  Actually, this question is not difficult to answer, when you After understanding the essence of the website, it is natural to understand the importance of the separation of dynamic and static. Let’s take Taobao as an example to analyze:

Taobao Homepage

When the browser enters www.taobao.comto visit the Taobao homepage, open the developer debugging tool and you can clearly see 100+the number of requests that will occur when the homepage loads. However, during normal project development, static resources are generally placed in resources/static/the directory:

IDEA project structure

When the project is launched and deployed, these static resources will be packaged together, so think about a question at this time: "" Assuming that Taobao does the same, where will the request when the home page loads eventually go to be processed?" The answer is  beyond doubt , 100+all requests for the home page will come to WEBthe machine where the service is deployed for processing, which means that a client requesting the Taobao home page will cause 100+concurrent requests to the back-end server. There is no doubt that the pressure on the back-end server is particularly huge.

But at this time, you might as well analyze and see 100+if there are at least requests 60+for *.js、*.css、*.html、*.jpg.....this type of static resources among the requests on the home page? The answer is Yes.

Since there are so many requests that are static and there is a high probability that these resources will not change for a long time, why should these requests be processed at the backend? Can it be dealt with ahead of time? Of course OK, after the analysis, it can be made clear: "After the dynamic and static separation, at least the concurrency of the back-end service can be reduced by more than half."  At this point, everyone should understand the performance benefits that the dynamic and static separation can bring. how big.


OK~, after figuring out the necessity of dynamic and static separation, how to achieve dynamic and static separation? It's actually very simple, let's see it in practice.

① First create a directory under the directory of the deployed Nginxmachine :Nginxstatic_resources

mkdir static_resources  

②Copy all the static resources in the project to this directory, and then remove and repackage the static resources in the project.

 

③Slightly modify nginx.confthe configuration and add a locationmatching rule:

location ~ .*\.(html|htm|gif|jpg|jpeg|bmp|png|ico|txt|js|css){  
    root   /soft/nginx/static_resources;  
    expires 7d;  
}  

Then start nginxand remove the static resource WEBservice as usual, and you will find that the original styles, jseffects, pictures, etc. are still valid, as follows:

The files in staticthe directory nginx_style.csshave been removed, but the effect still exists (green font + blue big border):

Effect animation after removal

Finally, read the location rule:

location ~ .*\.(html|htm|gif|jpg|jpeg|bmp|png|ico|txt|js|css)
  • ~Represents case-sensitive matching

  • .*Represents that any character can appear zero or more times, that is, the resource name is not limited

  • \.Represents matching suffix delimiters.

  • (html|...|css)Represents matching all static resource types in brackets

To sum up, a simple sentence overview: This configuration represents all resource requests .html~.cssthat the suffix.

"Finally, you can also upload static resources to the file server, and then locationconfigure a new upstreampoint in it."

Five, Nginx resource compression

Based on the separation of dynamic and static resources, if a static resource is Sizesmaller, the natural transmission speed will be faster, and it will also save bandwidth. Therefore, when we deploy a project, we can also achieve Nginxcompressed transmission of static resources. On the one hand, it can save bandwidth resources, and on the other hand, it can also speed up the response speed and improve the overall throughput of the system.

It also Nginxprovides three modules that support resource compression ngx_http_gzip_module、ngx_http_gzip_static_module、ngx_http_gunzip_module, which ngx_http_gzip_moduleare built-in modules, which means that some compression instructions under this module can be used directly. Subsequent resource compression operations are based on this module. Let’s take a look at some parameters of the compression configuration/ instruction:

After understanding Nginxthe basic compression configuration in , you can simply Nginxconfigure it in :

http{
    # 开启压缩机制
    gzip on;
    # 指定会被压缩的文件类型(也可自己配置其他类型)
    gzip_types text/plain application/javascript text/css application/xml text/javascript image/jpeg image/gif image/png;
    # 设置压缩级别,越高资源消耗越大,但压缩效果越好
    gzip_comp_level 5;
    # 在头部中添加Vary: Accept-Encoding(建议开启)
    gzip_vary on;
    # 处理压缩请求的缓冲区数量和大小
    gzip_buffers 16 8k;
    # 对于不支持压缩功能的客户端请求不开启压缩机制
    gzip_disable "MSIE [1-6]\."; # 低版本的IE浏览器不支持压缩
    # 设置压缩响应所支持的HTTP最低版本
    gzip_http_version 1.1;
    # 设置触发压缩的最小阈值
    gzip_min_length 2k;
    # 关闭对后端服务器的响应结果进行压缩
    gzip_proxied off;
}

In the above compression configuration, the last gzip_proxiedoption can be determined according to the actual situation of the system, and there are a variety of options in total:

  • off: Close Nginxthe compression of the response result of the background server.

  • expired: Turn on compression if the response header contains Expiresinformation.

  • no-cache: Turn on compression if the response header contains Cache-Control:no-cacheinformation.

  • no-store: Turn on compression if the response header contains Cache-Control:no-storeinformation.

  • private: Turn on compression if the response header contains Cache-Control:privateinformation.

  • no_last_modified: Turn on compression if the response header does not contain Last-Modifiedinformation.

  • no_etag: Turn on compression if the response header does not contain ETaginformation.

  • auth: Turn on compression if the response header contains Authorizationinformation.

  • any: Unconditionally enable the compression mechanism for the response result of the backend.

OK~, after simply modifying the compression configuration, you can introduce a file into the Nginxoriginal page :indexjquery-3.6.0.js

<script type="text/javascript" src="jquery-3.6.0.js"></script>  

Compare the difference before and after compression:

It can be clearly seen from the figure that when accessing before the compression mechanism is enabled, the original jssize of the file is .230KNginx230KB→69KB

 

Points to note: ① For image and video data, the compression mechanism will be enabled by default, so generally there is no need to enable compression again. ②For .jsfiles, you need to specify the compression type as application/javascript, not text/javascript、application/x-javascript.

Six, Nginx buffer

Let’s think about a problem first. NginxThe general request process of an access project is: "client → Nginx→ server". In this process, there are two connections: "client → NginxNginx→ server", then two different connection speeds Inconsistency will affect the user experience (for example, the loading speed of the browser cannot keep up with the response speed of the server).

In fact, it is similar to the fact that the memory of a computer cannot keep up with CPUthe speed, so the user experience is extremely poor. Therefore, CPUa three-level high-speed buffer will be added in the design to alleviate CPUthe contradiction with the inconsistency of the memory speed.  There is also a buffer mechanism in NginxChina, the main purpose of which is: ""Used to solve the problem caused by the mismatch of speed between two connections""Nginx . data to the client. Let's take a look at some configuration items about the buffer:

  • proxy_buffering: Whether to enable the buffer mechanism, the default is onoff.

  • client_body_buffer_size: Set the memory size for buffering client request data.

  • proxy_buffers: Set the number and size of buffers for each request/connection, default 4 4k/8k.

  • proxy_buffer_size: Sets the size of the buffer used to store response headers.

  • proxy_busy_buffers_size: When the backend data is not fully received, the status buffer Nginxcan be busyreturned to the client. This parameter is used to set the specific size busyof the status , and the default is .bufferproxy_buffer_size*2

  • proxy_temp_path: When the memory buffer is full, the data can be temporarily stored to the disk. This parameter is to set the directory for storing the buffered data.

  • pathis the path to the temporary directory.

    • Syntax: proxy_temp_path path;  path is the path to the temporary directory

  • proxy_temp_file_write_size: Set the size limit for writing data to the temporary file each time.

  • proxy_max_temp_file_size: Set the maximum capacity allowed to be stored in the temporary buffer directory.

  • Non-buffered parameter items:

    • proxy_connect_timeout: Set the timeout period when establishing a connection with the backend server.

    • proxy_read_timeout: Set the timeout for reading response data from the backend server.

    • proxy_send_timeout: Set the timeout period for transmitting request data to the backend server.

The specific nginx.confconfiguration is as follows:

http{  
    proxy_connect_timeout 10;  
    proxy_read_timeout 120;  
    proxy_send_timeout 10;  
    proxy_buffering on;  
    client_body_buffer_size 512k;  
    proxy_buffers 4 64k;  
    proxy_buffer_size 16k;  
    proxy_busy_buffers_size 128k;  
    proxy_temp_file_write_size 128k;  
    proxy_temp_path /soft/nginx/temp_buffer;  
}  

The above buffer parameters are based on the space allocated for each request, not the shared space for all requests. Of course, the specific parameter values ​​need to be determined according to the business, and the memory of the machine and the average data size of each request should be considered comprehensively. Recommended: Java Interview Questions

One final note: using buffers can also reduce the bandwidth consumption of immediate transfers.

Seven, Nginx cache mechanism

For performance optimization, caching is a solution that can greatly improve performance, so caching can be seen almost everywhere, such as client caching, proxy caching, server caching, etc., and caching is a part of proxy caching Nginx. kind. For the whole system, the advantages brought by adding cache are extra obvious:

  • Reduced bandwidth consumption for re-requesting resources to the backend or file server.

  • It reduces the access pressure of downstream servers and improves the overall throughput of the system.

  • Response times are reduced, loading speeds are improved, and pages open faster.

So in Nginx, how to configure the proxy cache? Let's take a look at the cache-related configuration items first:

"proxy_cache_path" : The path of the proxy cache.

grammar:

proxy_cache_path path [levels=levels] [use_temp_path=on|off] keys_zone=name:size [inactive=time] [max_size=size] [manager_files=number] [manager_sleep=time] [manager_threshold=time] [loader_files=number] [loader_sleep=time] [loader_threshold=time] [purger=on|off] [purger_files=number] [purger_sleep=time] [purger_threshold=time];

Yes, you read that right, it is so long..., explain the meaning of each parameter item:

  • path: The path address of the cache.

  • levels: Hierarchical structure of cache storage, up to three levels of directories are allowed.

  • use_temp_path: Whether to use a temporary directory.

  • keys_zone: Designate a shared memory space to store hotspot keys (1M can store 8000 keys).

  • inactive: Set how long the cache will be deleted after it has not been accessed (default is ten minutes).

  • max_size: The maximum storage space allowed for the cache. After the cache is exceeded, the cache will be removed based on the LRU algorithm. Nginx will create a Cache manager process to remove the data, or it can be purge.

  • manager_files: The manager process removes the upper limit of the number of cache files each time.

  • manager_sleep: The upper limit of the time for the manager process to remove cache files each time.

  • manager_threshold: The interval between each time the manager process removes the cache.

  • loader_files: When restarting Nginx to load the cache, the number of loads each time, the default is 100.

  • loader_sleep: The maximum allowed time limit for each loading, the default is 200ms.

  • loader_threshold: After loading once, the pause time interval, the default is 50ms.

  • purger: Whether to enable the purge method to remove data.

  • purger_files: Amount each time cache files are removed.

  • purger_sleep: The maximum time allowed to be consumed each time it is removed.

  • purger_threshold: The interval of pause after each removal.

"proxy_cache" : Turn on or off the proxy cache, and you need to specify a shared memory area when turning it on.

grammar:

proxy_cache zone | off;

zone is the name of the memory area, which is the name set by keys_zone above.

"proxy_cache_key" : defines how to generate the cache key.

grammar:

proxy_cache_key string;

string is the rule for generating Key, eg $scheme$proxy_host$request_uri.

"proxy_cache_valid" : The status code and expiration time of the effective cache.

grammar:

proxy_cache_valid [code ...] time;

code is the status code, and time is the effective time. Different cache times can be set according to the status code.

For example:proxy_cache_valid 200 302 30m;

"proxy_cache_min_uses" : Set how many times a resource is requested before being cached.

grammar:

proxy_cache_min_uses number;

number is the number of times, the default is 1.

"proxy_cache_use_stale" : When an exception occurs in the backend, whether to allow Nginx to return the cache as a response.

grammar:

proxy_cache_use_stale error;

error is the error type and can be configured timeout|invalid_header|updating|http_500....

"proxy_cache_lock" : For the same request, whether to enable the lock mechanism, only one request is allowed to be sent to the backend.

grammar:

proxy_cache_lock on | off;

"proxy_cache_lock_timeout" : Configure the lock timeout mechanism, and the request will be released after the specified time is exceeded.

proxy_cache_lock_timeout time;

"proxy_cache_methods" : Set for which HTTP methods to enable caching.

grammar:

proxy_cache_methods method;

method is the request method type, such as GET, HEAD, etc.

"proxy_no_cache" : Defines the conditions for not storing the cache, and will not be saved when it is met.

grammar:

proxy_no_cache string...;

string is the condition, for example$cookie_nocache $arg_nocache $arg_comment;

"proxy_cache_bypass" : Defines the conditions for not reading the cache, and will not read from the cache when it is met.

grammar:

proxy_cache_bypass string...;

Similar to the above proxy_no_cacheconfiguration method.

"add_header" : Add field information to the response header.

grammar:

add_header fieldName fieldValue;

"$upstream_cache_status" : records whether the cache is hit, there are many situations:

  • MISS: The request misses the cache.

  • HIT: The request hits the cache.

  • EXPIRED: The request hit the cache but the cache has expired.

  • STALE: The request hit a stale cache.

  • REVALIDDATED: Nginx verifies that stale caches are still valid.

  • UPDATING: The hit's cache content is stale, but the cache is being updated.

  • BYPASS: The response result is fetched from the origin server.

PS: This is different from the previous ones. The previous ones are all parameter items. This one is an Nginx built-in variable.

OK~, Nginxafter getting a general understanding of the cache configuration items in , let’s configure Nginxthe proxy cache:

http{  
    # 设置缓存的目录,并且内存中缓存区名为hot_cache,大小为128m,  
    # 三天未被访问过的缓存自动清楚,磁盘中缓存的最大容量为2GB。  
    proxy_cache_path /soft/nginx/cache levels=1:2 keys_zone=hot_cache:128m inactive=3d max_size=2g;  
      
    server{  
        location / {  
            # 使用名为nginx_cache的缓存空间  
            proxy_cache hot_cache;  
            # 对于200、206、304、301、302状态码的数据缓存1天  
            proxy_cache_valid 200 206 304 301 302 1d;  
            # 对于其他状态的数据缓存30分钟  
            proxy_cache_valid any 30m;  
            # 定义生成缓存键的规则(请求的url+参数作为key)  
            proxy_cache_key $host$uri$is_args$args;  
            # 资源至少被重复访问三次后再加入缓存  
            proxy_cache_min_uses 3;  
            # 出现重复请求时,只让一个去后端读数据,其他的从缓存中读取  
            proxy_cache_lock on;  
            # 上面的锁超时时间为3s,超过3s未获取数据,其他请求直接去后端  
            proxy_cache_lock_timeout 3s;  
            # 对于请求参数或cookie中声明了不缓存的数据,不再加入缓存  
            proxy_no_cache $cookie_nocache $arg_nocache $arg_comment;  
            # 在响应头中添加一个缓存是否命中的状态(便于调试)  
            add_header Cache-status $upstream_cache_status;  
        }  
    }  
}  

Then look at the effect, as follows:

When accessing for the first time, because the resource has not been requested yet, there is no data in the cache, so the cache is not hit. For the second and third times, the cache is still not hit, and the hit is not displayed until the fourth time. Why is this? Because in the previous cache configuration, we configured the minimum condition for joining the cache as: "" Resources must be requested at least three times before they are added to the cache."  This can avoid a lot of space occupied by invalid caches.

cache cleaning

When there are too many caches, if they are not cleaned up in time, the disk space will be "eaten up". Therefore, we need a complete cache cleaning mechanism to delete the cache. There are related options in the previous parameters, which can help us automatically clean up after proxy_cache_pathopening purgerCache, but unfortunately: ** purgerseries parameters can only be used in the commercial version NginxPlus, so you need to pay to use them. **

But there is no way out, we can ngx_cache_purgereplace it with a powerful third-party module, let’s install the plugin first: ① First go to the Nginxinstallation directory and create a cache_purgedirectory:

[root@localhost]# mkdir cache_purge && cd cache_purge  

Pull the compressed file of the installation package wgetfrom above through the command and decompress it:github

[root@localhost]# wget https://github.com/FRiCKLE/ngx_cache_purge/archive/2.3.tar.gz  
[root@localhost]# tar -xvzf 2.3.tar.gz  

③ Go to the previous Nginxdecompression directory again:

[root@localhost]# cd /soft/nginx/nginx1.21.6  

④ Rebuild once Nginx, and --add-moduleadd the third-party module just passed the instruction:

[root@localhost]# ./configure --prefix=/soft/nginx/ --add-module=/soft/nginx/cache_purge/ngx_cache_purge-2.3/  

⑤ Compile again according to what you just built Nginx, "but remember not to make install"  :

[root@localhost]# make  

⑥Delete the previous Nginxstartup file, and move it to another location if you are worried:

[root@localhost]# rm -rf /soft/nginx/sbin/nginx  

⑦ From the generated objsdirectory, re-copy a Nginxstartup file to the original location:

[root@localhost]# cp objs/nginx /soft/nginx/sbin/nginx  

At this point, ngx_cache_purgethe installation of the third-party cache clearing module is complete. Next, modify nginx.confthe configuration slightly and add a locationrule:

location ~ /purge(/.*) {  
  # 配置可以执行清除操作的IP(线上可以配置成内网机器)  
  # allow 127.0.0.1; # 代表本机  
  allow all; # 代表允许任意IP清除缓存  
  proxy_cache_purge $host$1$is_args$args;  
}  

Then restart Nginx, and then you can http://xxx/purge/xxclear the cache by the following method.

Eight, Nginx implements IP black and white list

Sometimes there are often some requirements, and some interfaces may only be open to corresponding partners, or APIpartners who purchase/access, then it is necessary to implement IPa function similar to a whitelist at this time. And sometimes some malicious attackers or crawler programs need to be prohibited from accessing the website again after being identified, so a IPblacklist also needs to be implemented. Then these functions do not need to be implemented by the backend, but can Nginxbe processed directly in .

NginxThe black and white list mechanism is mainly allow、denyrealized through configuration items:

allow xxx.xxx.xxx.xxx; # 允许指定的IP访问,可以用于实现白名单。  
deny xxx.xxx.xxx.xxx; # 禁止指定的IP访问,可以用于实现黑名单。  

When you want to block/open multiple IPaccesses at the same time, if all of IPthem are written in nginx.confthe file, they will not be displayed. This method is redundant, so you can create two new files BlocksIP.conf、WhiteIP.conf:

# --------黑名单:BlocksIP.conf---------  
deny 192.177.12.222; # 屏蔽192.177.12.222访问  
deny 192.177.44.201; # 屏蔽192.177.44.201访问  
deny 127.0.0.0/8; # 屏蔽127.0.0.1到127.255.255.254网段中的所有IP访问  
  
# --------白名单:WhiteIP.conf---------  
allow 192.177.12.222; # 允许192.177.12.222访问  
allow 192.177.44.201; # 允许192.177.44.201访问  
allow 127.45.0.0/16; # 允许127.45.0.1到127.45.255.254网段中的所有IP访问  
deny all; # 除开上述IP外,其他IP全部禁止访问  

After adding the ones to be banned/opened IPto the corresponding files, you can nginx.confimport these two files in:

http{  
    # 屏蔽该文件中的所有IP  
    include /soft/nginx/IP/BlocksIP.conf;   
 server{  
    location xxx {  
        # 某一系列接口只开放给白名单中的IP  
        include /soft/nginx/IP/blockip.conf;   
    }  
 }  
}  

As for where to import the file, this is not arbitrary. If you want to block/open the entire site, httpimport it in . If you only need to block/open under a domain name sever, import it in . open IP, then locationimport it in.

Of course, the above is just the simplest IPblack/white list implementation method, and it can also be ngx_http_geo_module、ngx_http_geo_moduleimplemented through a third-party library (this method can be blocked by region and country, and IPa library is provided).

Nine, Nginx cross-domain configuration

The cross-domain problem is actually a relatively rare problem in the previous single-architecture development, unless it needs to be connected to a third party SDK, this problem needs to be dealt with. However, with the popularity of separation of front and back ends and distributed architecture, cross-domain issues have become a problem that every Java developer must know how to solve.

 

Causes of cross-domain problems

The main reason for cross-domain problems is  the "same-origin policy"  . In order to ensure the security of user information and prevent malicious websites from stealing data, the same-origin policy is necessary, otherwise cookieit can be shared. Since httpstateless protocols are usually used cookieto achieve stateful information records, such as user identity/password, etc., once cookieshared, the user's identity information will be stolen.

The same-origin policy mainly refers to the same three points.  Two requests with the same "protocol + domain name + port" can be regarded as the same source, but if any point is different, it means that they are from two different sources. The same-origin policy restricts resource interaction between different origins.

Nginx solves cross-domain problems

After figuring out the cause of the cross-domain problem, Nginxhow can we solve the cross-domain problem next? In fact, it is relatively simple, nginx.confjust add a little configuration in :

location / {  
    # 允许跨域的请求,可以自定义变量$http_origin,*表示所有  
    add_header 'Access-Control-Allow-Origin' *;  
    # 允许携带cookie请求  
    add_header 'Access-Control-Allow-Credentials' 'true';  
    # 允许跨域请求的方法:GET,POST,OPTIONS,PUT  
    add_header 'Access-Control-Allow-Methods' 'GET,POST,OPTIONS,PUT';  
    # 允许请求时携带的头部信息,*表示所有  
    add_header 'Access-Control-Allow-Headers' *;  
    # 允许发送按段获取资源的请求  
    add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';  
    # 一定要有!!!否则Post请求无法进行跨域!  
    # 在发送Post跨域请求前,会以Options方式发送预检请求,服务器接受时才会正式请求  
    if ($request_method = 'OPTIONS') {  
        add_header 'Access-Control-Max-Age' 1728000;  
        add_header 'Content-Type' 'text/plain; charset=utf-8';  
        add_header 'Content-Length' 0;  
        # 对于Options方式的请求返回204,表示接受跨域请求  
        return 204;  
    }  
}  

After nginx.confthe above configuration is added to the file, the cross-domain request will take effect.

HandlerInterceptorAdapterBut if the backend is developed using a distributed architecture, sometimes RPC calls also need to solve cross-domain problems, otherwise there will also be exceptions that cannot be cross-domain requests, so you can inherit classes in your backend projects. WebMvcConfigurerInterfaces and annotations @CrossOrginare used to implement cross-domain configuration between interfaces.

10. Nginx anti-leech design

First understand what hotlinking is: ""hotlinking refers to the external display of resources imported from the current website by external websites""  , let's give a simple example to understand:

Just like the wallpaper website XZhan, YZhan, XZhan is a way to buy copyrights and sign authors little by little, thus accumulating a large amount of wallpaper materials, but Ydue to various reasons such as funds, Zhan directly <img src="X站/xxx.jpg" />copied Xall the wallpapers of Zhan through this method Resources, and then provided to users for downloading.

So if we are from this Xsite Boss, we must be unhappy, so how can we shield such problems at this time? Then the ""anti-leech"" to be described next  is here!

NginxThe implementation of the anti-leech mechanism is Refererrelated to a header field: This field mainly describes where the current request is sent from, then Nginxyou can get this value in , and then judge whether it is a resource reference request of this site, if not then Access not allowed. NginxThere is a configuration item in valid_referers, which can meet the previous requirements. The syntax is as follows:

valid_referers none | blocked | server_names | string ...;
  • none: Indicates that request access without Refererfields is accepted.HTTP

  • blocked: Indicates that access is permitted http://or https//otherwise requested.

  • server_names: The white list of resources, here you can specify the domain names that are allowed to be accessed.

  • string: You can customize the string, control wildcards, and regular expressions.

After a brief understanding of the syntax, the next implementation is as follows:

# 在动静分离的location中开启防盗链机制  
location ~ .*\.(html|htm|gif|jpg|jpeg|bmp|png|ico|txt|js|css){  
    # 最后面的值在上线前可配置为允许的域名地址  
    valid_referers blocked 192.168.12.129;  
    if ($invalid_referer) {  
        # 可以配置成返回一张禁止盗取的图片  
        # rewrite   ^/ http://xx.xx.com/NO.jpg;  
        # 也可直接返回403  
        return   403;  
    }  
      
    root   /soft/nginx/static_resources;  
    expires 7d;  
}  

After configuring according to the above content, Nginxthe most basic anti-leeching mechanism has been realized, and finally only need to restart it again! Of course, for the implementation of the anti-leech mechanism, there are also special third-party modules ngx_http_accesskey_moduleto achieve a more complete design, and interested friends can go and see by themselves.

PS: The anti-leeching mechanism cannot solve the crawler's forged referersinformation grabbing data in this way.

Eleven, Nginx large file transfer configuration

In some business scenarios, some large files need to be transferred, but there will often be some problems when transferring large files Bug, such as file exceeding the limit, request timeout during file transfer, etc., then you can Nginxdo some configuration at this time, let’s understand first Some configuration items that may be used when transferring large files:

When transferring large files, the four parameter values ​​of client_max_body_size, client_header_timeout, proxy_read_timeout, proxy_send_timeoutcan be configured according to the actual situation of your project.

The above configuration is only required as a proxy layer, because the final client transfers files or directly interacts with the backend. Here, the Nginxconfiguration as a gateway layer is only adjusted to a level that can "accommodate large files" transfer. Of course, Nginxit can also be used as a file server, but it needs to use a special third-party module nginx-upload-module. If there are not many functions for file upload in the project, it is recommended to Nginxbuild it. After all, it can save a file server resource. However, if the file upload/download is more frequent, it is recommended to set up an additional file server and hand over the upload/download function to the backend for processing.

12. Nginx configures SLL certificate

As more and more websites are connected HTTPS, it is not enough Nginxto configure only in the middle HTTP, and it is often necessary to listen to 443the port request HTTPS. In order to ensure communication security, the server needs to configure the corresponding digital certificate. When the project is used Nginxas a gateway, then the certificate It also needs to be configured in Nginx, and then briefly talk about SSLthe certificate configuration process:

① First go to the CA organization or apply for the corresponding SSLcertificate from the cloud console, and download Nginxthe version certificate after passing the review.

② After downloading the digital certificate, there are a total of three complete files: .crt、.key、.pem:

  • .crt: Digital certificate file, .crtwhich is .peman extended file, so some people may not have it after downloading.

  • .key: The server's private key file and the asymmetrically encrypted private key are used to decrypt the data transmitted by the public key.

  • .pem: Base64-encodedThe text file of the source certificate in encoded format, and the extension name can be modified according to the needs.

③Create a Nginxnew certificatedirectory under the directory, and upload the downloaded certificate/private key and other files to the directory.

④ Finally, modify nginx.confthe file, as follows:

# ----------HTTPS配置-----------  
server {  
    # 监听HTTPS默认的443端口  
    listen 443;  
    # 配置自己项目的域名  
    server_name www.xxx.com;  
    # 打开SSL加密传输  
    ssl on;  
    # 输入域名后,首页文件所在的目录  
    root html;  
    # 配置首页的文件名  
    index index.html index.htm index.jsp index.ftl;  
    # 配置自己下载的数字证书  
    ssl_certificate  certificate/xxx.pem;  
    # 配置自己下载的服务器私钥  
    ssl_certificate_key certificate/xxx.key;  
    # 停止通信时,加密会话的有效期,在该时间段内不需要重新交换密钥  
    ssl_session_timeout 5m;  
    # TLS握手时,服务器采用的密码套件  
    ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;  
    # 服务器支持的TLS版本  
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;  
    # 开启由服务器决定采用的密码套件  
    ssl_prefer_server_ciphers on;  
  
    location / {  
        ....  
    }  
}  
  
# ---------HTTP请求转HTTPS-------------  
server {  
    # 监听HTTP默认的80端口  
    listen 80;  
    # 如果80端口出现访问该域名的请求  
    server_name www.xxx.com;  
    # 将请求改写为HTTPS(这里写你配置了HTTPS的域名)  
    rewrite ^(.*)$ https://www.xxx.com;  
}  

OK~, according to the above configuration Nginx, your website can https://be accessed through the method, and when the client uses http://the method to access, it will be automatically rewritten as HTTPSa request. Recommended: Java Interview Questions

 

Thirteen, Nginx high availability

If a single node is deployed online Nginx, natural disasters and man-made disasters will inevitably occur, such as system abnormalities, program downtime, server power outages, computer room explosions, and the destruction of the earth... Hahaha, exaggerated. However, there are indeed hidden dangers in the actual production environment. As Nginxthe gateway layer of the entire system accesses external traffic, once it Nginxgoes down, the entire system will eventually become unavailable. This is undoubtedly extremely bad for the user experience, so it is also NginxHigh availability must be guaranteed .

Next, the mechanism will be adopted to achieve keepalivedhigh availability. It doesn't mean only members, but means , that is, virtual .VIPNginxVIPVirtual IPIP

keepalivedIn the previous development of the single-node architecture, it was a relatively frequently used high-availability technology. For example, the mechanism provided MySQL、Redis、MQ、Proxy、Tomcatby etc. will be used to achieve high availability of single-node applications.keepalivedVIP

Keepalived + restart script + dual-machine hot standby construction

① First create a corresponding directory and download it keepalivedto Linuxand unzip it:

[root@localhost]# mkdir /soft/keepalived && cd /soft/keepalived  
[root@localhost]# wget https://www.keepalived.org/software/keepalived-2.2.4.tar.gz  
[root@localhost]# tar -zxvf keepalived-2.2.4.tar.gz  

②Enter the decompressed keepaliveddirectory and build the installation environment, then compile and install:

[root@localhost]# cd keepalived-2.2.4  
[root@localhost]# ./configure --prefix=/soft/keepalived/  
[root@localhost]# make && make install  

③Enter the installation directory /soft/keepalived/etc/keepalived/and edit the configuration file:

[root@localhost]# cd /soft/keepalived/etc/keepalived/  
[root@localhost]# vi keepalived.conf  

④ Edit keepalived.confthe core configuration file of the host, as follows:

global_defs {  
    # 自带的邮件提醒服务,建议用独立的监控或第三方SMTP,也可选择配置邮件发送。  
    notification_email {  
        root@localhost  
    }  
    notification_email_from root@localhost  
    smtp_server localhost  
    smtp_connect_timeout 30  
    # 高可用集群主机身份标识(集群中主机身份标识名称不能重复,建议配置成本机IP)  
 router_id 192.168.12.129   
}  
  
# 定时运行的脚本文件配置  
vrrp_script check_nginx_pid_restart {  
    # 之前编写的nginx重启脚本的所在位置  
 script "/soft/scripts/keepalived/check_nginx_pid_restart.sh"   
    # 每间隔3秒执行一次  
 interval 3  
    # 如果脚本中的条件成立,重启一次则权重-20  
 weight -20  
}  
  
# 定义虚拟路由,VI_1为虚拟路由的标示符(可自定义名称)  
vrrp_instance VI_1 {  
    # 当前节点的身份标识:用来决定主从(MASTER为主机,BACKUP为从机)  
 state MASTER  
    # 绑定虚拟IP的网络接口,根据自己的机器的网卡配置  
 interface ens33   
    # 虚拟路由的ID号,主从两个节点设置必须一样  
 virtual_router_id 121  
    # 填写本机IP  
 mcast_src_ip 192.168.12.129  
    # 节点权重优先级,主节点要比从节点优先级高  
 priority 100  
    # 优先级高的设置nopreempt,解决异常恢复后再次抢占造成的脑裂问题  
 nopreempt  
    # 组播信息发送间隔,两个节点设置必须一样,默认1s(类似于心跳检测)  
 advert_int 1  
    authentication {  
        auth_type PASS  
        auth_pass 1111  
    }  
    # 将track_script块加入instance配置块  
    track_script {  
        # 执行Nginx监控的脚本  
  check_nginx_pid_restart  
    }  
  
    virtual_ipaddress {  
        # 虚拟IP(VIP),也可扩展,可配置多个。  
  192.168.12.111  
    }  
}  

⑤ Clone a previous virtual machine as the slave (standby) machine, and edit keepalived.confthe files of the slave machine as follows:

global_defs {  
    # 自带的邮件提醒服务,建议用独立的监控或第三方SMTP,也可选择配置邮件发送。  
    notification_email {  
        root@localhost  
    }  
    notification_email_from root@localhost  
    smtp_server localhost  
    smtp_connect_timeout 30  
    # 高可用集群主机身份标识(集群中主机身份标识名称不能重复,建议配置成本机IP)  
 router_id 192.168.12.130   
}  
  
# 定时运行的脚本文件配置  
vrrp_script check_nginx_pid_restart {  
    # 之前编写的nginx重启脚本的所在位置  
 script "/soft/scripts/keepalived/check_nginx_pid_restart.sh"   
    # 每间隔3秒执行一次  
 interval 3  
    # 如果脚本中的条件成立,重启一次则权重-20  
 weight -20  
}  
  
# 定义虚拟路由,VI_1为虚拟路由的标示符(可自定义名称)  
vrrp_instance VI_1 {  
    # 当前节点的身份标识:用来决定主从(MASTER为主机,BACKUP为从机)  
 state BACKUP  
    # 绑定虚拟IP的网络接口,根据自己的机器的网卡配置  
 interface ens33   
    # 虚拟路由的ID号,主从两个节点设置必须一样  
 virtual_router_id 121  
    # 填写本机IP  
 mcast_src_ip 192.168.12.130  
    # 节点权重优先级,主节点要比从节点优先级高  
 priority 90  
    # 优先级高的设置nopreempt,解决异常恢复后再次抢占造成的脑裂问题  
 nopreempt  
    # 组播信息发送间隔,两个节点设置必须一样,默认1s(类似于心跳检测)  
 advert_int 1  
    authentication {  
        auth_type PASS  
        auth_pass 1111  
    }  
    # 将track_script块加入instance配置块  
    track_script {  
        # 执行Nginx监控的脚本  
  check_nginx_pid_restart  
    }  
  
    virtual_ipaddress {  
        # 虚拟IP(VIP),也可扩展,可配置多个。  
  192.168.12.111  
    }  
}  

⑥Create a new scriptsdirectory and write Nginxa restart script check_nginx_pid_restart.sh:

[root@localhost]# mkdir /soft/scripts /soft/scripts/keepalived  
[root@localhost]# touch /soft/scripts/keepalived/check_nginx_pid_restart.sh  
[root@localhost]# vi /soft/scripts/keepalived/check_nginx_pid_restart.sh  
  
#!/bin/sh  
# 通过ps指令查询后台的nginx进程数,并将其保存在变量nginx_number中  
nginx_number=`ps -C nginx --no-header | wc -l`  
# 判断后台是否还有Nginx进程在运行  
if [ $nginx_number -eq 0 ];then  
    # 如果后台查询不到`Nginx`进程存在,则执行重启指令  
    /soft/nginx/sbin/nginx -c /soft/nginx/conf/nginx.conf  
    # 重启后等待1s后,再次查询后台进程数  
    sleep 1  
    # 如果重启后依旧无法查询到nginx进程  
    if [ `ps -C nginx --no-header | wc -l` -eq 0 ];then  
        # 将keepalived主机下线,将虚拟IP漂移给从机,从机上线接管Nginx服务  
        systemctl stop keepalived.service  
    fi  
fi  

⑦The script file written needs to change the encoding format and grant execution permission, otherwise the execution may fail:

[root@localhost]# vi /soft/scripts/keepalived/check_nginx_pid_restart.sh  
  
:set fileformat=unix # 在vi命令里面执行,修改编码格式  
:set ff # 查看修改后的编码格式  
  
[root@localhost]# chmod +x /soft/scripts/keepalived/check_nginx_pid_restart.sh  

⑧Since the installation keepalivedis a custom installation location, some files need to be copied to the system directory:

[root@localhost]# mkdir /etc/keepalived/  
[root@localhost]# cp /soft/keepalived/etc/keepalived/keepalived.conf /etc/keepalived/  
[root@localhost]# cp /soft/keepalived/keepalived-2.2.4/keepalived/etc/init.d/keepalived /etc/init.d/  
[root@localhost]# cp /soft/keepalived/etc/sysconfig/keepalived /etc/sysconfig/  

⑨Add keepalivedthe system service and set to enable self-start, and then test whether the startup is normal:

[root@localhost]# chkconfig keepalived on  
[root@localhost]# systemctl daemon-reload  
[root@localhost]# systemctl enable keepalived.service  
[root@localhost]# systemctl start keepalived.service  

Other commands:

systemctl disable keepalived.service # 禁止开机自动启动  
systemctl restart keepalived.service # 重启keepalived  
systemctl stop keepalived.service # 停止keepalived  
tail -f /var/log/messages # 查看keepalived运行时日志  

⑩Finally, test VIPwhether it takes effect, by checking whether the virtual machine is successfully mounted IP:

[root@localhost]# ip addr  

Virtual IP-VIP

From the figure above, it can be clearly seen that the virtual machine has been successfully mounted, but the virtual machine will not be mounted on IPanother machine . Only when the main machine goes offline, the slave machine will go online and take over . Finally, test whether the external network can communicate normally, that is, directly in :192.168.12.130IP192.168.12.130VIPVIPWindowsping VIP

Ping-VIP

When the external VIPcommunication is passed, it can also Pingbe communicated normally, which means that the virtual IPconfiguration is successful. Recommended: Java Interview Questions

Nginx High Availability Test

After the above steps, keepalivedthe VIPmechanism has been successfully built. In the last stage, several things were mainly done:

  • 1. NginxMounted for the deployed machine VIP.

  • Second, through keepalivedthe establishment of a master-slave dual-machine hot backup.

  • Third, through keepalivedthe realization of Nginxdowntime restart.

Because there is no domain name in front, the initial server_nameconfiguration is the current machine IP, so nginx.confthe configuration needs to be changed slightly:

sever{  
    listen    80;  
    # 这里从机器的本地IP改为虚拟IP  
 server_name 192.168.12.111;  
 # 如果这里配置的是域名,那么则将域名的映射配置改为虚拟IP  
}  

Finally, let's experiment with the effect:

Nginx down

In the above process, first start keepalived、nginxthe services respectively, and then nginxsimulate Nginxthe downtime situation by manually stopping. After a while, check the background process again, and we will find that nginxit is still alive.

From this process, it is not difficult to find that the function of automatic restart after downtime keepalivedhas been realized for us Nginx, so let's simulate the situation when the server fails:

server failure

In the above process, we manually closed keepalivedthe service to simulate the power failure of the machine, hardware damage, etc. (because the power failure of the machine = the keepalivedprocess in the host disappears), and then checked IPthe information of the machine again, it is obvious that we can see VIPDisappeared!

Now switch to another machine: 192.168.12.130take a look at the situation:

IP status of 130

At this moment, we will find that 192.168.12.129after the host goes down, the VIP automatically drifts from the host to the slave 192.168.12.130, and at this time the client's request will eventually come to 130this machine Nginx.

"In the end, after Keepalivedusing Nginxthe master-slave hot backup, whether it encounters various failures such as online downtime or power failure in the computer room, it can ensure that the application system can provide users with 7x24hourly services."

Fourteen, Nginx performance optimization

The length of the article here is quite long. Finally, let’s talk about Nginxthe performance optimization. The main thing is to briefly talk about the optimization items with the highest income. I won’t expand the description here. After all, there are many reasons for affecting performance. For example, the network, server hardware, operating system, back-end services, the program itself, database services, etc.

Optimization 1: Open the long connection configuration

Usually Nginx acts as a proxy service and is responsible for distributing client requests, so it is recommended to enable HTTPlong connections so that users can reduce the number of handshakes and reduce server loss, as follows:

upstream xxx {  
    # 长连接数  
    keepalive 32;  
    # 每个长连接提供的最大请求数  
    keepalived_requests 100;  
    # 每个长连接没有新的请求时,保持的最长时间  
    keepalive_timeout 60s;  
}  

Optimization 2. Enable zero-copy technology

The concept of zero copy appears in most middleware with relatively good performance, such as Kafka、Nettyetc., and Nginxthe data zero copy technology can also be configured in the middleware, as follows:

sendfile on; # 开启零拷贝机制  

The difference between the zero-copy read mechanism and the traditional resource read mechanism:

  • "Traditional way:"  hardware --> kernel --> user space --> program space --> program kernel space --> network socket

  • "Zero copy method:"  hardware --> kernel --> program kernel space --> network socket

From the comparison of the above process, it is easy to see the performance difference between the two.

Optimization 3. Open the no-delay or multi-packet co-delivery mechanism

NginxThere are two key performance parameters in , that is , tcp_nodelay、tcp_nopushthe opening method is as follows:

tcp_nodelay on;  
tcp_nopush on;  

TCP/IPThe protocol uses the Nagle algorithm by default, that is, in the process of network data transmission, each data packet will not be sent out immediately, but will wait for a period of time, and combine the following data packets into a datagram However, although this algorithm improves the network throughput, the real-time performance is reduced.

Therefore, your project is a highly interactive application, so you can manually enable tcp_nodelaythe configuration, so that every data packet submitted by the application to the kernel will be sent out immediately. But this will generate a large number of TCPpacket headers and increase the network overhead.

On the contrary, the business of some projects does not require high real-time data, but pursues higher throughput. Then you can enable the tcp_nopushconfiguration item. This configuration is similar to the meaning of "plug". First, plug the connection so that The data will not be sent out yet, and will be sent out after the plug is removed. After setting this option, the kernel will try to splice small data packets into one large data packet (one MTU) and send it out.

Of course, if after a certain period of time (usually 200ms), the kernel still has not accumulated a MTUcertain amount, it must also send the existing data, otherwise it will always be blocked.

tcp_nodelay、tcp_nopushThe two parameters are "mutually exclusive". If the application pursues response speed, it is recommended to enable tcp_nodelaythe parameter, such as IM, financial and other types of projects. For applications that pursue throughput, it is recommended to enable tcp_nopushparameters, such as scheduling system, reporting system, etc.

Note: ① tcp_nodelayGenerally, it should be established and used when the long connection mode is turned on. tcp_nopushThe parameters must be enabled sendfilebefore they can be used.

Optimization 4. Adjust Worker Work Process

NginxAfter startup, only one Workerworker process will be opened by default to handle client requests, and we can start the corresponding number of worker processes according to the number of CPU cores of the machine, so as to improve the overall concurrency support, as follows:

# 自动根据CPU核心数调整Worker进程数量  
worker_processes auto;  

8It is OK if the maximum number of working processes is 1, and 8there will be no further performance improvement after 1.

At the same time, you can also slightly adjust the number of file handles that each worker process can open:

# 每个Worker能打开的文件描述符,最少调整至1W以上,负荷较高建议2-3W  
worker_rlimit_nofile 20000;  

The operating system kernel ( kernel) uses file descriptors to access files. Whether it is opening, creating, reading, or writing files, it is necessary to use file descriptors to specify the file to be operated. Therefore, the larger the value, it represents a The more files the process can operate (but it cannot exceed the kernel limit, the 3.8Wupper limit is recommended at most).

Optimization 5. Turn on the CPU affinity mechanism

Friends who are familiar with concurrent programming know that the number of processes/threads often far exceeds the number of CPU cores in the system, because the principle of operating system execution is essentially to use the time slice switching mechanism, that is, one CPU core will be in multiple processes. Frequent switching between them causes a large performance loss.

The CPU affinity mechanism refers to Nginxbinding each working process to a fixed CPU core, thereby reducing the time overhead and resource consumption caused by CPU switching. The opening method is as follows:

worker_cpu_affinity auto;  

Optimization 6. Open the epoll model and adjust the number of concurrent connections

It was mentioned at the very beginning: Nginx、Redisall programs are implemented based on the multiplexing model, but the original multiplexing model select/pollcan only monitor 1024a maximum of a connection, and epollit belongs to select/pollthe enhanced version of the interface, so using this model can Improve individual Workerperformance to a great extent , as follows:

events {  
    # 使用epoll网络模型  
    use epoll;  
    # 调整每个Worker能够处理的连接数上限  
    worker_connections  10240;  
}  

select/poll/epollThe model will not be elaborated here , and will be analyzed in detail in the following IO model articles.

Fifteen, put it at the end

So far, Nginxmost of the content has been explained. Regarding the performance optimization content of the last section, in fact, the dynamic and static separation, allocation buffer, resource cache, anti-leeching, resource compression, etc. mentioned earlier can also be summarized as A solution for performance optimization.

Guess you like

Origin blog.csdn.net/z_ssyy/article/details/131395099