Maison > Opération et maintenance > Nginx > le corps du texte

Comment implémenter la compression des requêtes Nginx

WBOY
Libérer: 2023-05-15 11:55:06
avant
1510 Les gens l'ont consulté

1. Introduction

La compression des demandes consiste à compresser les résultats du serveur via Nginx, puis à les envoyer au client pour réduire la pression de transmission du réseau et améliorer l'efficacité de la transmission.

Les deux méthodes de requête courantes sont : gzip, brotli (Google), qui est plus efficace que brotli, et sera expliquée en détail plus tard.

La demande de compression est divisée en : compression dynamique et compression statique. La compression dynamique entraînera l'échec du fichier d'envoi dans Nginx. Pour certains contenus inchangés, la compression statique peut être utilisée pour améliorer l'efficacité des requêtes.

Il est utilisé pour compresser les résultats de la requête. Le client et le serveur doivent prendre en charge le protocole de compression. Le serveur compresse les résultats et le client décompresse les données. La compression occupera une certaine efficacité du côté du serveur. Cela dépend du niveau de compression. En effet, plus le niveau est élevé, plus la perte est importante. Peut réduire la pression de transmission du réseau.

La compression ne prend effet que pour les demandes de proxy.

2. Processus de compression de la demande

Comment implémenter la compression des requêtes Nginx

Le processus d'exécution est le suivant : le client envoie une demande au serveur, et après que nginx ait reçu la demande, il enverra une demande au serveur en amont et un canal réseau sera créé entre Nginx et le serveur en amont. Les données seront transmises entre eux. Si l'opération de compression est activée ici, Nginx compressera les données de résultat et renverra les données au client. Lorsque le navigateur recevra la requête nginx, il traitera d'abord la requête nginx. en-tête de requête. Si un protocole de compression est trouvé, il sera jugé si le navigateur actuel prend en charge le protocole. S'il est pris en charge, les données seront décompressées et les données seront affichées à l'utilisateur.

Après avoir activé la compression, l'utilisateur est insensible et peut réduire la pression de transmission. Cependant, il n'est pas recommandé de compresser les images et les vidéos car la taille ne change pas beaucoup pour la transmission réseau et nécessite également l'assistance du client. côté serveur, nous avons besoin d'un support pour compresser les données transmises et réduire leur taille. Bien sûr, plus la compression est élevée, plus le temps de décompression et de compression est long et plus la pression sur le serveur est grande. .

3. Compression Gzip

3.1 Introduction à gzip

Gzip est l'abréviation de GNUzip, qui a été utilisée pour la première fois pour la compression de fichiers dans les systèmes UNIX. Le codage Gzip sur le protocole HTTP est une technologie utilisée pour améliorer les performances des applications Web. Le serveur Web et le client (navigateur) doivent tous deux prendre en charge Gzip. Actuellement, les navigateurs grand public : Chrome, Firefox, etc. prennent tous en charge ce protocole. Les serveurs courants : Apache, Nginx et IIS prennent également en charge Gzip.

Le taux de compression de Gzip est d'environ 3 à 10 fois (texte brut), ce qui peut considérablement économiser la bande passante réseau du serveur. Dans les applications réelles, tous les fichiers ne sont pas compressés, généralement seuls les fichiers statiques (jscsshtml) sont compressés. Les fichiers tels que JPEG ne sont pas suffisamment compressés avec Gzip et la compression consomme des ressources CPU.

Alors, comment Gzip compresse-t-il ? En termes simples, la compression Gzip trouve les chaînes similaires dans un fichier texte et les remplace temporairement pour réduire la taille du fichier entier. Cette forme de compression est idéale pour le Web, car les fichiers HTML et CSS contiennent souvent de grandes quantités de chaînes répétées telles que des espaces, des balises, etc.

Comment implémenter la compression des requêtes Nginx

3.2 Utilisation de gzip

Le module gzip est intégré à Nginx, il n'est donc pas nécessaire d'ajouter d'autres valeurs par défaut, il suffit de configurer et d'installer Nginx.

Portée d'utilisation : http, serveur, emplacement

Nginx est configuré comme suit

gzip sur ;

  • S'il faut activer la compression.

  • Valeur par défaut : gzip désactivé par défaut

gzip_buffers 32 4k | 16 8k

  • Taille du tampon de compression.

  • Valeur par défaut : gzip_buffers 32 4k | 16 8k

gzip_comp_level 1 ;

  • Niveau de compression 1 à 9, plus le nombre est grand, plus le taux de compression est élevé.

  • Plus la vitesse de compression est faible, plus la vitesse de décompression est rapide et plus le taux de compression est petit.

  • Valeur par défaut : gzip_comp_leve 1

gzip_http_version 1.1

  • Utilisez la plus petite version http de gzip. .

gzip_min_length

  • Définissez la longueur minimale de la réponse qui sera compressée par gzip. La longueur est déterminée uniquement par le champ d'en-tête de réponse "Content-Length".

gzip_proxied Choix multiples

  • Pour que le serveur en amont renvoie différentes têtes pour décider s'il doit compresser, il y en a deux communes : l'une est désactivée et l'autre est quelconque

  • Généralement, si le cache est activé , la compression a déjà été effectuée. Tous les détails peuvent être contournés

  • off car il n'y a aucune restriction.

  • Lorsqu'il est utilisé comme proxy inverse, compressez les informations d'en-tête renvoyées par le serveur en amont.

  • expired - Activer la compression si l'en-tête contient l'en-tête "Expires"

  • no-cache - Activer la compression si l'en-tête contient l'en-tête "Cache-Control:no-cache"

  • no-store - Activez la compression si l'en-tête contient l'en-tête "Cache-Control:no-store"

  • private - Activer la compression, si l'en-tête contient les informations d'en-tête "Cache-Control:private"

  • no_last_modified - Activer la compression, si l'en-tête ne contient pas les informations d'en-tête "Last-Modified"

  • no_etag - Activer la compression, si l'en-tête ne contient pas les informations d'en-tête "ETag"

  • auth - activer la compression, si l'en-tête contient les informations d'en-tête "Autorisation"

  • any - activer la compression sans condition.

gzip_vary on ;

  • Ajouter un en-tête pour s'adapter aux anciens navigateurs Vary: Accept-Encoding

gzip_types:

  • Quels types MIME de fichiers sont compressés.

gzip_disable :

  • Désactivez les navigateurs qui utilisent gzip.

  • Il est recommandé de ne pas configurer

  • Valeur par défaut : gzip_disable 'msie6MSIE [4-6].MSIE 6.0'

location / {
  
  gzip off ;  # 开启gzip压缩
  gzip_buffers 32 4k ; # 设置缓冲区大小
  gzip_comp_level 5; # 设置压缩等级 1-9 
  gzip_disable 'msie6MSIE [4-6]\.MSIE 6.0';  # 禁止哪些浏览器不使用压缩
  gzip_http_version 1.1; # 设置压缩所需要的最低的http版本。 
  gzip_min_length 20 ; # 设置响应的数据最小限制,在这个限制之后再回进行压缩
  gzip_vary on ; # 增加一个header ,适用于老的浏览器 Vary:Accept-Encoding 
  gzip_proxied any; # 无条件启动压缩
  # 哪些mime类型的文件进行压缩 
  #gzip_types text/plain application/x-javascript text/css application/xml; 
  gzip_types
    text/xml application/xml application/atom+xml application/rss+xml application/xhtml+xml image/svg+xml
    text/javascript application/javascript application/x-javascript
    text/x-json application/json application/x-web-app-manifest+json
    text/css text/plain text/x-component
    font/opentype application/x-font-ttf application/vnd.ms-fontobject
    image/x-icon;
}
Copier après la connexion

3.3 gzip request

Comment implémenter la compression des requêtes Nginx

Lorsque gzip est démarré , notre demande va à ng inx Sur le serveur, nginx a déjà produit une réponse entendue pour nous, mais les données n'ont pas encore été générées et il ne sait pas quelle est la taille des données spécifiques, car nginx est une demande de réponse asynchrone. Il le fait étape par étape. Étape. Il prépare d'abord l'en-tête, puis demande le contenu. Décompressez, et enfin fusionnez les deux éléments de contenu, décompressez-les et enfin envoyez-les parce qu'il ne connaît pas la taille spécifique en raison de la nature asynchrone.

Il renvoie d'abord l'en-tête de la requête, puis lit les données lentement.

----------------------------------响应体-------------------------------------------------
Connection: keep-alive
Content-Encoding: gzip # 结果启动了gzip压缩 
Content-Type: application/json # 响应结果 
Date: Mon, 13 Feb 2023 09:13:19 GMT
Keep-Alive: timeout=65
Server: nginx/1.20.2
Transfer-Encoding: chunked # 传输的格式这个对应的就是length,这个是他会发送一个一个的包,当最后一个包是0表示传输结束
Vary: Accept-Encoding
 
 
 
------------------------------------请求头-----------------------------------------------
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
Cache-Control: max-age=0
Connection: keep-alive
Host: 192.168.101.128
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36
Copier après la connexion

Remarque : ce qui précède est une compression dynamique, ce qui signifie que toutes les requêtes seront compressées une fois. Cela présente un inconvénient fatal : il ne prend pas en charge sendfile. Sendfile est une copie nulle des données. Il ne chargera pas les données dans nginx. mais transférez les données via l'interface réseau, mais une fois la compression dynamique gzip activée, sendfile deviendra invalide. La compression statique pourra être utilisée.

Lors de l'utilisation de Nginx multicouche, il est recommandé d'activer Gzip sur le Nginx connecté au serveur. Cela prendra en charge gzip et gzip sera activé sur n'importe quel serveur.

3.4 Compression statique

Comment implémenter la compression des requêtes Nginx

Pourquoi utiliser la compression statique ?

Tout d'abord, la compression dynamique ne peut pas utiliser sendfile, tandis que la compression statique résout parfaitement ce problème.

La compression statique est une fonction complémentaire ou étendue. Elle permet de compresser à l'avance les fichiers de ressources demandés dans un package compressé.

Tout d'abord, les ressources statiques doivent être plus efficaces que les ressources dynamiques. Après compression, la taille du disque peut être réduite et les ressources du canal réseau peuvent également être économisées.

Qu'est-ce que la compression statique

La compression statique ne convient pas au proxy inverse et ne convient qu'aux serveurs de ressources. Il peut transmettre les fichiers compressés au client. La compression statique signifie qu'il y aura un fichier de ressources sous le chemin de ressources. et un correspondant Nom du package compressé. Et Nginx donnera la priorité à la recherche de packages compressés et transmettra les données directement via sendfile.

Nginx envoie le fichier compressé sur le réseau, puis lorsque le navigateur reçoit le fichier du package compressé envoyé par Nginx, il le décompresse. Il enverra l'interface du package compressé au client avant de l'envoyer au client.

3. Configuration

Le module http_gzip_static_module permet d'envoyer des fichiers précompressés avec l'extension de fichier "", .gz au lieu de fichiers normaux. Ce module n'est pas construit par défaut, il doit être activé à l'aide du paramètre de configuration --with-http_gzip_static_module. Ce module n'est pas dans le package précompilé et doit être ajouté manuellement. La fonction de ce module est de décompresser le package compressé avec un module interne et d'ajouter un module externe.

Lors de l'installation de nginx pour la première fois, utilisez

./configure --prefix==/usr/local/nginx --with-hhtp_gzip_static_module

make && make install

Avez déjà installé nginx, utilisez la commande lors de la mise à niveau du client nginx

./configure --prefinx==/usr/local/nginx --with-http_gzip_static_module

make Ne faites pas d'installation sinon les fichiers précédents seront écrasés

Copiez le programme nginx d'objs dans /usr/local /nginx/sbin ·, veuillez noter que vous devez sauvegarder le programme nginx d'origine.

Syntaxe : gzip_static on | off | toujours ;

Fonction : s'il faut activer la fonction de compression statique.

Valeur du paramètre :

    on : activez la compression statique et vérifiez si le navigateur la prend en charge. S'il ne la prend pas en charge, la compression statique ne sera pas utilisée.
  • off : désactivez la compression statique
  • .
  • toujours : s'il faut l'utiliser Compression statique, que le navigateur prenne ou non en charge la fonctionnalité de compression statique.
    • Cela posera un problème. Si le client ne le prend pas en charge, il ne peut pas être décompressé. S'il n'y a pas de fichiers non compressés sur le disque, 404 sera signalé par défaut. Il peut être utilisé avec ngx_http_gunzip_module.
    Valeur par défaut : gzip_static on
  • Applicable à : http, serveur, emplacement

使用的需要将本地的资源文件进行压缩 ,压缩成 xxx.gz的文件

cd /usr/local/nginx/html 
gzip *
Copier après la connexion

注意:开启之后默认就会先访问 .gz 的文件了,如果不支持 静态压缩则会访问 正常文件,如果没有正常的文件只有 .gz 那么就会报错 。

4. nginx_http_gunzip_module 模块

Comment implémenter la compression des requêtes Nginx

这个模块是配合 gzip_static always时使用的 ,因为 当配置程 always 时,所有的请求会都进行找压缩文件,在文件存不存在或者说浏览器支不支持 静态压缩,nginx都会将静态压缩文件返回给浏览器,如果浏览器不支持的话会导致文件解不开,也就是 404 。

这个模块它没有在预编译的包里,需要手动添加,这个模块的作用就是把静态的压缩包解压开,他会在发送给客户端之前将压缩包接口在发送给客户端,它相当于是一层拦截器,它的作用就是可以把源文件进行压缩,我们可以把源文件进行删除了,节省磁盘空间,但是一般会用到。

注意 : with 是内部 、 add 是外部的

安装命令 :

./configure --prefix=/usr/local/nginx --add-module=/tools/nginx-sticky --with-http_gzip_static_module --with-http_gunzip_module

make

如果是替换的话,则将这个文件中的这个文件 cp 到 nginx的安装目录下的 sbin

Comment implémenter la compression des requêtes Nginx

移动命令:

 cp /usr/local/nginx/sbin/nginx /usr/local/nginx/sbin/nginx.old2
 
 cd /tools/nginx/objs 
 mv nginx /usr/local/nginx/sbin/
Copier après la connexion

这里没有gzip,但也没有 context-length 因为nginx需要把文件解压缩,他也不知道具体文件有多大,这个 gzip_static 适用场景 :在作为cdn服务器或者 cdn上游服务器文件存储服务器时,我们就可以把本地原始文件删了,只展示zip 包,把解压缩的压力丢弃给客户端 , 同时可以把本地压缩等级,提高不是 gzip的压缩等级 ,经常高配访问的一些页面 css js ,也可以通过 static压缩。

Comment implémenter la compression des requêtes Nginx

静态压缩 响应结果会有 Context-Encoding : gzip 、Conten-Length:392 有展示 context-length 表示他开启了静态压缩,预压缩直接返回zip包 没有源文件 ,1.速度快,2节省服务器资源。

四、Brotli

Brotli 是 Google 推出的开源压缩算法,通过变种的 LZ77 算法、Huffman 编码以及二阶文本建模等方式进行数据压缩,与其他压缩算法相比,它有着更高的压缩效率,性能也比我们目前常见的 Gzip 高17-25%,可以帮我们更高效的压缩网页中的各类文件大小及脚本,从而提高加载速度,提升网页浏览体验。需要说明的是 Brotli 压缩只在 https 下生效,因为 在 http 请求中 request header 里的 Accept-Encoding: gzip, deflate 是没有 br 的。

Brotli 如此高的压缩比率,得益于其使用一个预定义的字典,该字典包含超过 13000 个来自文本和 HTML 文档的大型语料库的常用字符串,预定义的算法可以提升较小文件的压缩密度,而压缩与解压缩速度则大致不变。

Brotli 凭借它优异的压缩性能迅速占领了市场,从下图可以看到,除了 IE 和 Opera Mini 之外,几乎所有的主流浏览器都已支持 Brotli 算法,因此处于资源占用的考虑,比如说流量,建议启用:

Brotil 规范由 Google 员工 Jyrki Alakuijala 和 Zoltan Szabadka 于 2013-2016开发,并伴随着规范的俩个作者Evgenii Kuliuchniko 和 Lode Vandevenne共同开发的参考实现,后者之前开发了谷歌的zopfli在2013年重新实现了收缩 /gzip 压缩格式。与zopfli不同,后者是对现有数据格式规范的重新实现,Brotli 是一种新的数据格式,并允许作者进一步提高压缩比。

4.1 Brotli 概述

Brotli 的编码器提供了 12 个质量级别 (从 0 到 11)。它们是压缩速度换取压缩效率的压缩模式:更高质量的几倍速度较慢,但会产生更好的压缩比。

一个 Brotli 压缩文件由 元块(meta-blocks)集合组成。每个元块最多可容纳 16 MiB,由俩部分组成:一个 数据部分(data part),它存储 LZ77 压缩的放入快,以及一个 标题(header),每个块的压缩遵循经典的 ①LZ77 压缩方案并由 ②计算具有良好的LZ77解析和计算 LZ 短语的简洁编码这俩个主要阶段组成。

它效率高是因为内置了 n多个字典,包含都是一些常见的文件文件 css 、js 等等一些标签,如果我们将这些标签归类生成一个字典之后,我们就可以按照序号去解压这个文件了。

并且它在 Nginx 中话是可以和 Gzip 共存,开启了Brotli 不会导致 Gzip失效,如果浏览器支持brotli 那么优先使用 Brotli ,不支持在使用 Gzip。

4.2 Brotli 的安装

--add-dynamic-module表示动态的引入模块在配置文件中还需要单独加入 load_module path/xxx

官网

  • https://github.com/google/ngx_brotli

  • https://codeload.github.com/google/brotli/tar.gz/refs/tags/v1.0.9

下载 俩个项目

解压缩

  • brotli-1.0.9 是 brotli 算法模块,需要先解压。

    • tar -zxvf brotli-1.0.9.tar.gz

  • ngx_brotli-1.0.0rc 是nginx的 brotli的模块。这模块里需要引入 brotli 算法模块

    • tar -zxvf ngx_brotli-1.0.0rc.tar.gz

接下来讲 brotli 的内容全部 复制到 ngx_brotli 的 deps/brotli/目录

  • cd /tools/brotli-1.0.9

  • cp -r * /tools/ngx_brotli-1.0.0rc/deps/brotli/

模块化编译 :

./configure --with-compat --add-dynamic-module=/tools/ngx_brotli-1.0.0rc --prefix=/usr/local/nginx/
Copier après la connexion

--add-dynamic-module=brotli目录

加载所有的压缩模块

./configure --with-compat --add-dynamic-module=/tools/ngx_brotli-1.0.0rc --prefix=/usr/local/nginx/ --add-module=/tools/nginx-sticky --with-http_gzip_static_module --with-http_gunzip_module
Copier après la connexion

make && make install

下载的两个模块 拷贝到 /usr/local/nginx/modules/

Comment implémenter la compression des requêtes Nginx

首先在 /usr/local/nginx创建一个modules文件夹 mkdir modules

mv ngx_http_brotli_filter_module.so ngx_http_brotli_static_module.so /usr/local/nginx/modules/

最后将新编译的 nginx 启动程序复制到 /usr/local/nginx/sbin下 做好之前程序复制。

  • cp /usr/local/nginx/sbin/nginx /usr/local/nginx/sbin/nginx.oid3

  • mv /tools/nginx-12.0/objs/nginx /usr/local/nginx/sbin/

在配置文件中动态加载模块

load_module "/usr/local/nginx/modules/ngx_http_brotli_filter_module.so";
load_module "/usr/local/nginx/modules/ngx_http_brotli_static_module.so";
Copier après la connexion

4.3 配置选项

具体的配置选项可以查看GitHub: https://github.com/google/ngx_brotli

brotli的配置可以参考Gzip的配置,几乎一致。

brotli

  • 语法:brotli on | off

  • 默认值 :brotli off

  • 适用于: http、server、location、if

  • 作用:开启或者禁用brotli 压缩功能。

brotli_static

  • 语法:brotli_static on | off | always

  • 默认值:brotli_static off

  • 适用于:http、server、location

  • 作用:brotli 也是支持预先压缩文件,启用或禁用检查是否存在带扩展名的预压缩文件.br 。使用该always值,在所有情况下都使用预压缩文件,而不检查客户端是否支持它。

brotli_types

  • 语法:brotli_types [...]

  • 默认值:brotli_types text/html

  • 适用于: http、server、location

  • 作用:指定哪些资源类型需要进行压缩操作,特殊值*匹配任何 MIME类型。

brotli_buffers

  • 语法:brotli_buffers

  • 默认值: 32 4k | 16 8 k

  • 适用于: http、server、location

  • 作用:设置压缩缓冲区大小,最新版本以及弃用了 。

brotli_comp_level

  • 语法:brotli_comp_level

  • 默认值 :6'

  • 适用于 : http、server、location

  • 作用 : 设置即时压缩 Brotli 质量(压缩)level。0可接受的值在从到 的范围内11。

brotli_window

  • 语法:brotli_window

  • 默认值 : 512k

  • 适用于 :http、server、 location

  • 作用:设置 Brotli 窗口size。可以比作是一个桌子,将要压缩的文件同时放在这个桌子上,这个桌子上可以放多少文件的大小,这个值也不越大越好,他比较占内存,值增加建议是2的倍数,可接受的值为1k, 2k, 4k, 8k, 16k, 32k, 64k, 128k, 256k, 512k, 1m, 2m,和4m。8m 16m

brotli_min_length

  • 语法:brotli_min_length

  • 默认值:20

  • 适用于: http、server、location

  • 作用:指定进行压缩的文件最小的长度,如果小于这个值则不压缩。

#加载动态模块 
load_module "/usr/local/nginx/modules/ngx_http_brotli_filter_module.so";
load_module "/usr/local/nginx/modules/ngx_http_brotli_static_module.so";
worker_processes  1;
events {
    worker_connections  1024;
}
 
http {
    server {
    listen       80;
    server_name  localhost;
        location  / {
          #brotli配置 
          brotli on;  # 开启 压缩
        brotli_static on; # 是否开启预先压缩,开启之后就会 .br的压缩包
          brotli_comp_level 6; # 压缩等级
          brotli_buffers 16 8k; # 缓冲区大小 ,已经启用 
          brotli_min_length 20; # 压缩时文件最小限制 
          # 对哪些mime.types类型进行压缩
          brotli_types text/plain text/css text/javascript application/javascript text/xml application/xml application/xml+rss application/json image/jpeg image/gif image/png;
    
          }
  }
}
Copier après la connexion

4.4 brotli 测试

因为默认 brotli 是必现 https 请求才能使用的,因为 http的请求 请求头的 Accept-Encoding 是没有 br的,所以服务器是无法知道客户端可以使用的。

测试方案:

使用 linux 的 curl 命令 :

curl -H 'Accept-Encding : br' -I 192.168.101.128/index.html
Copier après la connexion
[root@localhost sbin]# curl -H Accept-Encoding:br  -I http://192.168.101.128/static_page.html
HTTP/1.1 200 OK
Server: nginx/1.20.2
Date: Fri, 17 Feb 2023 08:11:05 GMT
Content-Type: text/html
Last-Modified: Fri, 17 Feb 2023 03:28:14 GMT
Connection: keep-alive
Keep-Alive: timeout=65
Vary: Accept-Encoding
ETag: W/"63eef44e-31"
Content-Encoding: br
[root@localhost sbin]# curl  -I http://192.168.101.128/static_page.html
HTTP/1.1 200 OK
Server: nginx/1.20.2
Date: Fri, 17 Feb 2023 08:11:54 GMT
Content-Type: text/html
Last-Modified: Fri, 17 Feb 2023 03:28:14 GMT
Connection: keep-alive
Keep-Alive: timeout=65
Vary: Accept-Encoding
ETag: W/"63eef44e-31"
Copier après la connexion

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Étiquettes associées:
source:yisu.com
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal
À propos de nous Clause de non-responsabilité Sitemap
Site Web PHP chinois:Formation PHP en ligne sur le bien-être public,Aidez les apprenants PHP à grandir rapidement!