IT评测·应用市场-qidao123.com技术社区

标题: 云原生系列 - Nginx(高级篇) [打印本页]

作者: 欢乐狗    时间: 2024-8-25 01:19
标题: 云原生系列 - Nginx(高级篇)
前言

一、扩容

通过扩容提升整体吞吐量


1、单机垂直扩容:硬件资源增长

  1. 云服务资源增加
  2. 整机:IBM、浪潮、DELL、HP等
  3. CPU/主板:更新到主流
  4. 网卡:10G/40G网卡
  5. 磁盘:SAS(SCSI) HDD(机械)、HHD(混合)、SATA SSD、PCI-e SSD、 MVMe SSD
  6. SSD
  7. 多副本机制
  8. 系统盘/热点数据/数据库存储
  9. HDD
  10. 冷数据存储
复制代码
2、水平扩展:集群化


2.1、会话管理

2.1.1、Nginx高级负载均衡


2.1.2、使用sticky模块完成对Nginx的负载均衡

使用参考
http://nginx.org/en/docs/http/ngx_http_upstream_module.html#sticky

tengine中有session_sticky模块我们通过第三方的方式安装在开源版本中
sticky是第三方模块,需要重新编译Nginx,他可以对Nginx这种静态文件服务器使用基于cookie的负载均衡
2.2、KeepAlive

在http协议header中可以看到当前毗连状态
2.2.1、测试工具charles

下载地址
https://www.charlesproxy.com/assets/release/4.6.2/charles-proxy-4.6.2-win64.msi?k=fc1457e312
官网
https://www.charlesproxy.com
1)、什么时间使用?

明显的预知用户会在当前毗连上有下一步操作
复用毗连,有效淘汰握手次数,尤其是https建立一次毗连开销会更大
2)、什么时间不用?

访问内联资源一般用缓存,不需要keepalive
长时间的tcp毗连容易导致体系资源无效占用
3)、对客户端使用keepalive



2.3、对上游服务器使用keepalive

起首需要配置使用http1.1协议。以便建立更高效的传输,默认使用http1.0,在http1.0中需要配置header才气
在Upstream中所配置的上游服务器默认都是用短毗连,即每次请求都会在完成之后断开
2.3.1、相干配置

1)、upstream中配置

配置

2)、server中配置


2.4、AB安装

  1. yum install httpd-tools
复制代码
参数分析:

2.4.1、直连nginx

  1. Server Software:        nginx/1.21.6
  2. Server Hostname:        192.168.44.102
  3. Server Port:            80
  4. Document Path:          /
  5. Document Length:        16 bytes
  6. Concurrency Level:      30
  7. Time taken for tests:   13.035 seconds
  8. Complete requests:      100000
  9. Failed requests:        0
  10. Write errors:           0
  11. Total transferred:      25700000 bytes
  12. HTML transferred:       1600000 bytes
  13. Requests per second:    7671.48 [#/sec] (mean)
  14. Time per request:       3.911 [ms] (mean)
  15. Time per request:       0.130 [ms] (mean, across all concurrent requests)
  16. Transfer rate:          1925.36 [Kbytes/sec] received
  17. Connection Times (ms)
  18.               min  mean[+/-sd] median   max
  19. Connect:        0    0   0.4      0      12
  20. Processing:     1    3   1.0      3      14
  21. Waiting:        0    3   0.9      3      14
  22. Total:          2    4   0.9      4      14
  23. Percentage of the requests served within a certain time (ms)
  24.   50%      4
  25.   66%      4
  26.   75%      4
  27.   80%      4
  28.   90%      5
  29.   95%      5
  30.   98%      6
  31.   99%      7
  32. 100%     14 (longest request)
复制代码
2.4.2、反向署理

  1. Server Software:        nginx/1.21.6
  2. Server Hostname:        192.168.44.101
  3. Server Port:            80
  4. Document Path:          /
  5. Document Length:        16 bytes
  6. Concurrency Level:      30
  7. Time taken for tests:   25.968 seconds
  8. Complete requests:      100000
  9. Failed requests:        0
  10. Write errors:           0
  11. Total transferred:      25700000 bytes
  12. HTML transferred:       1600000 bytes
  13. Requests per second:    3850.85 [#/sec] (mean)
  14. Time per request:       7.790 [ms] (mean)
  15. Time per request:       0.260 [ms] (mean, across all concurrent requests)
  16. Transfer rate:          966.47 [Kbytes/sec] received
  17. Connection Times (ms)
  18.               min  mean[+/-sd] median   max
  19. Connect:        0    0   0.2      0      13
  20. Processing:     3    8   1.4      7      22
  21. Waiting:        1    7   1.4      7      22
  22. Total:          3    8   1.4      7      22
  23. Percentage of the requests served within a certain time (ms)
  24.   50%      7
  25.   66%      8
  26.   75%      8
  27.   80%      8
  28.   90%      9
  29.   95%     10
  30.   98%     12
  31.   99%     13
  32. 100%     22 (longest request)
复制代码
2.4.3、直连Tomcat

  1. Server Software:        
  2. Server Hostname:        192.168.44.105
  3. Server Port:            8080
  4. Document Path:          /
  5. Document Length:        7834 bytes
  6. Concurrency Level:      30
  7. Time taken for tests:   31.033 seconds
  8. Complete requests:      100000
  9. Failed requests:        0
  10. Write errors:           0
  11. Total transferred:      804300000 bytes
  12. HTML transferred:       783400000 bytes
  13. Requests per second:    3222.38 [#/sec] (mean)
  14. Time per request:       9.310 [ms] (mean)
  15. Time per request:       0.310 [ms] (mean, across all concurrent requests)
  16. Transfer rate:          25310.16 [Kbytes/sec] received
  17. Connection Times (ms)
  18.               min  mean[+/-sd] median   max
  19. Connect:        0    0   0.3      0      15
  20. Processing:     0    9   7.8      7     209
  21. Waiting:        0    9   7.2      7     209
  22. Total:          0    9   7.8      7     209
  23. Percentage of the requests served within a certain time (ms)
  24.   50%      7
  25.   66%      9
  26.   75%     11
  27.   80%     13
  28.   90%     18
  29.   95%     22
  30.   98%     27
  31.   99%     36
  32. 100%    209 (longest request)
复制代码
1)、nginx反向署理Tomcat + keepalive

  1. Server Software:        nginx/1.21.6
  2. Server Hostname:        192.168.44.101
  3. Server Port:            80
  4. Document Path:          /
  5. Document Length:        7834 bytes
  6. Concurrency Level:      30
  7. Time taken for tests:   23.379 seconds
  8. Complete requests:      100000
  9. Failed requests:        0
  10. Write errors:           0
  11. Total transferred:      806500000 bytes
  12. HTML transferred:       783400000 bytes
  13. Requests per second:    4277.41 [#/sec] (mean)
  14. Time per request:       7.014 [ms] (mean)
  15. Time per request:       0.234 [ms] (mean, across all concurrent requests)
  16. Transfer rate:          33688.77 [Kbytes/sec] received
  17. Connection Times (ms)
  18.               min  mean[+/-sd] median   max
  19. Connect:        0    0   0.2      0       9
  20. Processing:     1    7   4.2      6     143
  21. Waiting:        1    7   4.2      6     143
  22. Total:          1    7   4.2      6     143
  23. Percentage of the requests served within a certain time (ms)
  24.   50%      6
  25.   66%      7
  26.   75%      7
  27.   80%      7
  28.   90%      8
  29.   95%     10
  30.   98%     13
  31.   99%     16
  32. 100%    143 (longest request)
复制代码
2)、nginx反向署理Tomcat

  1. Server Software:        nginx/1.21.6
  2. Server Hostname:        192.168.44.101
  3. Server Port:            80
  4. Document Path:          /
  5. Document Length:        7834 bytes
  6. Concurrency Level:      30
  7. Time taken for tests:   33.814 seconds
  8. Complete requests:      100000
  9. Failed requests:        0
  10. Write errors:           0
  11. Total transferred:      806500000 bytes
  12. HTML transferred:       783400000 bytes
  13. Requests per second:    2957.32 [#/sec] (mean)
  14. Time per request:       10.144 [ms] (mean)
  15. Time per request:       0.338 [ms] (mean, across all concurrent requests)
  16. Transfer rate:          23291.74 [Kbytes/sec] received
  17. Connection Times (ms)
  18.               min  mean[+/-sd] median   max
  19. Connect:        0    0   0.2      0       9
  20. Processing:     1   10   5.5      9     229
  21. Waiting:        1   10   5.5      9     229
  22. Total:          1   10   5.5      9     229
  23. Percentage of the requests served within a certain time (ms)
  24.   50%      9
  25.   66%     10
  26.   75%     11
  27.   80%     11
  28.   90%     13
  29.   95%     14
  30.   98%     17
  31.   99%     19
  32. 100%    229 (longest request)
复制代码
2.5、UpStream工作流程

proxy_pass 向上游服务器请求数据共有6个阶段

set_header
设置header
proxy_connect_timeout
与上游服务器毗连超时时间、快速失败
proxy_send_timeout
界说nginx向后端服务发送请求的隔断时间(不是耗时)。默认60秒,超过这个时间会关闭毗连
proxy_read_timeout
后端服务给nginx响应的时间,规定时间内后端服务没有给nginx响应,毗连会被关闭,nginx返回504 Gateway Time-out。默认60秒
2.5.1、缓冲区

proxy_requset_buffering
是否完全读到请求体之后再向上游服务器发送请求
proxy_buffering
是否缓冲上游服务器数据
proxy_buffers 32 64k;
缓冲区大小 32个 64k大小内存缓冲块
proxy_buffer_size
header缓冲区大小
  1. proxy_requset_buffering on;
  2. proxy_buffering on;
  3. proxy_buffer_size 64k;
  4. proxy_buffers 32 128k;
  5. proxy_busy_buffers_size 8k;
  6. proxy_max_temp_file_size 1024m;
复制代码
proxy_temp_file_write_size 8k
当启用从署理服务器到临时文件的响应的缓冲时,一次限定写入临时文件的数据的大小。 默认情况下,大小由proxy_buffer_size和proxy_buffers指令设置的两个缓冲区限定。 临时文件的最大大小由proxy_max_temp_file_size指令设置。
proxy_max_temp_file_size 1024m;
临时文件最大值
proxy_temp_path
  
  1. proxy_temp_path /spool/nginx/proxy_temp 1 2;
复制代码
a temporary file might look like this:
  
  1. /spool/nginx/proxy_temp/7/45/00000123457
复制代码
2.5.2、对客户端的限定

可配置位置

client_body_buffer_size
对客户端请求中的body缓冲区大小
默认32位8k 64位16k
如果请求体大于配置,则写入临时文件
client_header_buffer_size
设置读取客户端请求体的缓冲区大小。 如果请求体大于缓冲区,则将整个请求体或仅将其部分写入临时文件。 默认32位8K。 64位平台16K。
client_max_body_size 1000M;
默认1m,如果一个请求的大小超过配置的值,会返回413 (request Entity Too Large)错误给客户端
将size设置为0将禁用对客户端请求正文大小的查抄。
client_body_timeout
指定客户端与服务端建立毗连后发送 request body 的超时时间。如果客户端在指定时间内没有发送任何内容,Nginx 返回 HTTP 408(Request Timed Out)
client_header_timeout
客户端向服务端发送一个完整的 request header 的超时时间。如果客户端在指定时间内没有发送一个完整的 request header,Nginx 返回 HTTP 408(Request Timed Out)。
client_body_temp_path path [level1 [level2 [level3`]]]
在磁盘上客户端的body临时缓冲区位置
client_body_in_file_only on;
把body写入磁盘文件,请求竣事也不会删除
client_body_in_single_buffer
尽量缓冲body的时间在内存中使用一连单一缓冲区,在二次开发时使用$request_body读取数据时性能会有所进步
client_header_buffer_size
设置读取客户端请求头的缓冲区大小
如果一个请求行大概一个请求头字段不能放入这个缓冲区,那么就会使用large_client_header_buffers
large_client_header_buffers
默认8k
2.6、反向署理中的容错机制

2.6.1、参考文档

https://docs.nginx.com/nginx/admin-guide/load-balancer/http-load-balancer/
http://nginx.org/en/docs/stream/ngx_stream_proxy_module.html#proxy_bind
proxy_timeout
2.6.2、重试机制

proxy_next_upstream
作用:
当后端服务器返回指定的错误时,将请求传递到其他服务器。
error与服务器建立毗连,向其传递请求或读取响应头时发生错误;
timeout在与服务器建立毗连,向其传递请求或读取响应头时发生超时;
invalid_header服务器返回空的或无效的响应;
http_500服务器返回代码为500的响应;
http_502服务器返回代码为502的响应;
http_503服务器返回代码为503的响应;
http_504服务器返回代码504的响应;
http_403服务器返回代码为403的响应;
http_404服务器返回代码为404的响应;
http_429服务器返回代码为429的响应;
不相识这个机制,在一样平常开发web服务的时间,就大概会踩坑。
比如有这么一个场景:一个用于导入数据的web页面,上传一个excel,通过读取、处理excel,向数据库中插入数据,处理时间较长(如1分钟),且为同步操作(即处理完成后才返回效果)。暂且岂论这种方式的好坏,若nginx配置的响应等待时间(proxy_read_timeout)为30秒,就会触发超时重试,将请求又打到另一台。如果处理中没有考虑到重复数据的场景,就会发生数据多次重复插入!(当然,这种场景,内网可以通过呆板名访问该服务器进行操作,就可以绕过nginx了,不外外网就没办法了。)
2.7、获取客户端真实IP

2.7.1、X-Real-IP

额外模块,不保举使用
2.7.2、setHeader

  1. proxy_set_header X-Forwarded-For $remote_addr;
复制代码
2.8、Gzip

作用域 http, server, location

完整实例
  1.   gzip on;
  2.   gzip_buffers 16 8k;
  3.   gzip_comp_level 6;
  4.   gzip_http_version 1.1;
  5.   gzip_min_length 256;
  6.   gzip_proxied any;
  7.   gzip_vary on;
  8.   gzip_types text/plain application/x-javascript text/css application/xml;
  9.   gzip_types
  10.     text/xml application/xml application/atom+xml application/rss+xml application/xhtml+xml image/svg+xml
  11.     text/javascript application/javascript application/x-javascript
  12.     text/x-json application/json application/x-web-app-manifest+json
  13.     text/css text/plain text/x-component
  14.     font/opentype application/x-font-ttf application/vnd.ms-fontobject
  15.     image/x-icon;
  16.   gzip_disable "MSIE [1-6]\.(?!.*SV1)";
复制代码
  1. HTTP/1.1 200
  2. Server: nginx/1.21.6
  3. Date: Wed, 18 May 2022 17:42:35 GMT
  4. Content-Type: text/html;charset=utf-8
  5. Content-Length: 7832
  6. Connection: keep-alive
  7. Keep-Alive: timeout=65
复制代码
2.9、ngx_http_gunzip_module

帮助不支持gzip的客户端解压本地文件
2.9.1、http_gzip_static_module

需要重新编译nginx
  1. ./configure --with-http_gzip_static_module
复制代码
2.10、Brotli

安装


2.11、合并客户端请求

Concat模块
Tengine
Nginx官方先容
https://www.nginx.com/resources/wiki/modules/concat/
git地址
https://github.com/alibaba/nginx-http-concat

下载源码解压缩编译安装

2.12、资源静态化


2.13、SSI合并服务器端文件

官方文档
http://nginx.org/en/docs/http/ngx_http_ssi_module.html
2.13.1、配置


两端安装
  1. yum install -y rsync
复制代码
rsync --list-only 192.168.119.128::www/
修改配置
  1. rsync -avz --password-file=/etc/rsyncd.passwd.client /usr/local/nginx/html/ rsync://sgg@192.168.44.105:/www
复制代码
--delete 删除目的目录比源目录多余文件
3、多级缓存

3.1、静态资源缓存

3.2、欣赏器缓存

3.2.1、什么时间可以用缓存?

观察京东缓存及加载速度

3.2.2、Age

是CDN添加的属性表如今CDN中缓存了多少秒
3.2.3、via

用来标识CDN缓存履历了哪些服务器,缓存是否掷中,使用的协议
3.3、Nginx默认缓存

Nginx版本不同会默认配置
3.4、强制缓存与协商缓存

强制缓存:直接从本机读取,不请求服务器
协商缓存:发送请求header中携带Last-Modified,服务器大概会返回304 Not Modified
3.5、欣赏器强制缓存

3.5.1、cache-control

http1.1的规范,使用max-age表现文件可以在欣赏器中缓存的时间以秒为单位
标记范例功能public响应头响应的数据可以被缓存,客户端和署理层都可以缓存private响应头可私有缓存,客户端可以缓存,署理层不能缓存(CDN,proxy_pass)no-cache请求头可以使用本地缓存,但是必须发送请求到服务器回源验证no-store请求和响应应禁用缓存max-age请求和响应文件可以在欣赏器中缓存的时间以秒为单位s-maxage请求和响应用户署理层缓存,CDN下发,当客户端数据过期时会重新校验max-stale请求和响应缓存最大使用时间,如果缓存过期,但还在这个时间范围内则可以使用缓存数据min-fresh请求和响应缓存最小使用时间,must-revalidate请求和响应当缓存过期后,必须回源重新请求资源。比no-cache更严酷。因为HTTP 规范是答应客户端在某些特殊情况下直接使用过期缓存的,比如校验请求发送失败的时间。那么带有must-revalidate的缓存必须校验,其他条件全部失效。proxy-revalidate请求和响应和must-revalidate雷同,只对CDN这种署理服务器有效,客户端碰到此头,需要回源验证stale-while-revalidate响应表如今指定时间内可以先使用本地缓存,后台进行异步校验stale-if-error响应在指定时间内,重新验证时返回状态码为5XX的时间,可以用本地缓存only-if-cached响应那么只使用缓存内容,如果没有缓存 则504 getway timeout 在欣赏器和服务器端验证文件是否过期的时间,欣赏器在二次请求的时间会携带IF-Modified-Since属性
3.5.2、Expires

过期时间
  1. expires 30s;   #缓存30秒
  2. expires 30m;  #缓存30分钟   
  3. expires 2h;     #缓存2小时
  4. expires 30d;    #缓存30天
复制代码
3.6、协商缓存

3.6.1、last-modified

3.6.2、etag

http1.1支持
在HTTP协议中If-Modified-Since和If-None-Match分别对应Last-Modified和ETag
Entity Tag 的缩写,中文译过来就是实体标签的意思.
HTTP中并没有指定怎样生成ETag,哈希是比力抱负的选择。
在盘算Etag的时间,会产生CPU的淹灭,所以也可以用时间戳,但这样直接使用Last-Modified即可。
ETag 用来校验用户请求的资源是否有变化,作用和lastmodified很像,区别是lastmodified准确到秒,ETag可以用hash算法来生成更准确的比对内容。
当用户初次请求资源的时间返回给用户数据和200状态码并生成ETag,再次请求的时间服务器比对ETag,没有发生变化的话返回304
Cache-Control直接是通过不请求来实现,而ETag是会发请求的,只不外服务器根据请求的东西的内容有无变化来判断是否返回请求的资源
3.7、总结:

3.7.1、cache-control expires 强制缓存

页面初次打开,直接读取缓存数据,刷新,会向服务器发起请求
3.7.2、etag lastmodify 协商缓存

没发生变化 返回304 不发送数据
3.7.3、ast-modified 与ssi的冲突

3.7.4、欣赏器缓存原则


3.8、GEOip

3.8.1、下载数据库

官网需注册登录
下载数据库
maxmind.com
3.8.2、安装依赖

官方git
https://github.com/maxmind/libmaxminddb
下载后执行编译安装之后
  1. echo /usr/local/lib  >> /etc/ld.so.conf.d/local.conf
  2. ldconfig
复制代码
3.8.3、Nginx模块

https://github.com/leev/ngx_http_geoip2_module
更完整的配置可参考官方文档
http://nginx.org/en/docs/http/ngx_http_geoip_module.html#geoip_proxy
3.8.4、Nginx配置

  1. geoip2 /root/GeoLite2-ASN_20220524/GeoLite2-ASN.mmdb {
  2.         $geoip2_country_code country iso_code;
  3. }
  4. add_header country $geoip2_country_code;
复制代码
3.9、正向署理与反向署理缓存

3.9.1、正向署理配置

  1. proxy_pass $scheme://$host$request_uri;
  2. resolver 8.8.8.8;
复制代码
3.9.2、署理https请求

需要第三方模块
https://github.com/chobits/ngx_http_proxy_connect_module
配置
  1. server {
  2.      listen                         3128;
  3.      # dns resolver used by forward proxying
  4.      resolver                       8.8.8.8;
  5.      # forward proxy for CONNECT request
  6.      proxy_connect;
  7.      proxy_connect_allow            443 563;
  8.      proxy_connect_connect_timeout  10s;
  9.      proxy_connect_read_timeout     10s;
  10.      proxy_connect_send_timeout     10s;
  11.      # forward proxy for non-CONNECT request
  12.      location / {
  13.          proxy_pass http://$host;
  14.          proxy_set_header Host $host;
  15.      }
  16. }
复制代码
3.10、proxy缓存

官网解释
http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_cache
3.10.1、配置

  1. http模块:
  2. proxy_cache_path /ngx_tmp levels=1:2 keys_zone=test_cache:100m inactive=1d max_size=10g ;
  3. location模块:
  4. add_header  Nginx-Cache "$upstream_cache_status";
  5. proxy_cache test_cache;
  6. proxy_cache_valid 168h;
复制代码
proxy_cache_use_stale
默认off
在什么时间可以使用过期缓存
可选error | timeout | invalid_header | updating | http_500 | http_502 | http_503 | http_504 | http_403 | http_404 | http_429 | off
proxy_cache_background_update
默认off
运行开启子请求更新过期的内容。同时会把过期的内容返回给客户端
proxy_no_cache proxy_cache_bypass
指定什么时间不使用缓存而直接请求上游服务器
  1. proxy_no_cache $cookie_nocache $arg_nocache$arg_comment;
  2. proxy_no_cache $http_pragma    $http_authorization;
复制代码
如果这些变量如果存在的话不为空大概不等于0,则不使用缓存
proxy_cache_convert_head
默认 on
是否把head请求转换成get请求后再发送给上游服务器 以便缓存body里的内容
如果关闭 需要在 cache key 中添加 $request_method 以便区分缓存内容
proxy_cache_lock
默认off
缓存更新锁
proxy_cache_lock_age
默认5s
缓存锁超时时间
3.10.2、断点续传缓存 range

当有完整的content-length之后即可断点续传
在反向署理服务器中需向后传递header
  1. proxy_set_header Range $http_range;
复制代码
proxy_cache_key中增长range
proxy_cache_max_range_offset
range最大值,超过之后不做缓存,默认情况下 不需要对单文件较大的资源做缓存
proxy_cache_methods
默认 head get
proxy_cache_min_uses
默认1
被请求多少次之后才做缓存
proxy_cache_path
path 指定存储目录
以cache_key取md5值

目录层级数及目录名称位数
取mdb5后几位
TMPFS

默认创建缓存文件时,先向缓冲区创建临时文件,再移动到缓存目录
是否使用缓冲区

指定时间内未被访问过的缓存将被删除
3.10.3、缓存清理

purger
需要第三方模块支持
https://github.com/FRiCKLE/ngx_cache_purge
配置
  1.         location ~ /purge(/.*) {
  2.             proxy_cache_purge  test_cache  $1;
  3.         }
  4.         自定义cachekey
  5.          proxy_cache_key $uri;
复制代码
proxy_cache_key
默认$scheme$proxy_host$request_uri
缓存的key
proxy_cache_revalidate
如果缓存过期了,向上游服务器发送“If-Modified-Since” and “If-None-Match来验证是否改变,如果没有就不需要重新下载资源了
proxy_cache_valid
可以针对不容http状态码设置缓存过期时间
不设置状态码会默认200, 301, 302
  1. proxy_cache_valid 200 302 10m;
  2. proxy_cache_valid 301      1h;
  3. proxy_cache_valid any      1m;
复制代码
any指其他恣意状态码
二、高效

1、Nginx内存缓存

strace
一般应用为静态文件元数据信息缓存
sendfile执行过程
  1. epoll_wait(8, [{EPOLLIN, {u32=1904243152, u64=140709327827408}}, {EPOLLIN, {u32=1904242704, u64=140709327826960}}], 512, 25215) = 2
  2. recvfrom(10, "GET / HTTP/1.1\r\nHost: 192.168.44"..., 1024, 0, NULL, NULL) = 475
  3. stat("/usr/local/nginx//html/index.html", {st_mode=S_IFREG|0644, st_size=1429, ...}) = 0
  4. open("/usr/local/nginx//html/index.html", O_RDONLY|O_NONBLOCK) = 11
  5. fstat(11, {st_mode=S_IFREG|0644, st_size=1429, ...}) = 0
  6. writev(10, [{iov_base="HTTP/1.1 200 OK\r\nServer: nginx/1"..., iov_len=263}], 1) = 263
  7. sendfile(10, 11, [0] => [1429], 1429)   = 1429
  8. write(4, "192.168.44.1 - - [27/May/2022:14"..., 193) = 193
  9. close(11)
复制代码
open_file_cache
  1. open_file_cache max=500 inactive=60s
  2. open_file_cache_min_uses 1;
  3. open_file_cache_valid 60s;
  4. open_file_cache_errors on
复制代码
max缓存最大数目,超过数目后会使用LRU镌汰
inactive 指定时间内未被访问过的缓存将被删除
pen_file_cache_min_uses
被访问到多少次后会开始缓存
open_file_cache_valid
隔断多长时间去查抄文件是否有变化
open_file_cache_errors
对错误信息是否缓存
2、Nginx外置缓存缓存

http://nginx.org/en/docs/http/ngx_http_memcached_module.html
2.1、error_page

指定状态码
  1.         error_page 404 =302 http://www.atguigu.com;
复制代码
默认指向location
2.2、匿名location

2.3、nginx + memcached

2.3.1、memcached安装

yum -y install memcached
默认配置文件在
/etc/sysconfig/memcached
查看状态
  1. memcached-tool 127.0.0.1:11211  stats
复制代码
2.3.2、nginx配置

  1.    upstream backend {
  2.    
  3. #   server 192.168.44.102 weight=8 down;
  4.    server 192.168.44.104:8080;
  5.    }
  6. location / {
  7.         set            $memcached_key "$uri?$args";
  8.         memcached_pass 127.0.0.1:11211;
  9.         add_header X-Cache-Satus HIT;
  10.         add_header Content-Type 'text/html; charset=utf-8'; # 强制响应数据格式为html
  11.         # root   html;
  12.         }
复制代码
2.4、nginx + redis

2.4.1、Redis安装

7.0下载地址
https://codeload.github.com/redis/redis/tar.gz/refs/tags/7.0.0
安装
  1. 依赖
  2. yum install -y tcl-devel
  3. 解压
  4. make
  5. make install
复制代码
2.4.2、redis2-nginx-module

redis2-nginx-module是一个支持 Redis 2.0 协议的 Nginx upstream 模块,它可以让 Nginx 以非阻塞方式直接防问远方的 Redis 服务,同时支持 TCP 协议和 Unix Domain Socket 模式,并且可以启用强盛的 Redis 毗连池功能。
https://www.nginx.com/resources/wiki/modules/redis2/
https://github.com/openresty/redis2-nginx-module
redis快速安装
  1. yum install epel-release
  2. yum install -y redis
复制代码
redis2-nginx-module 安装

3、Stream模块

http://nginx.org/en/docs/stream/ngx_stream_core_module.html
3.1、限流

3.1.1、QPS限定

官方文档
http://nginx.org/en/docs/http/ngx_http_limit_req_module.html
测试工具
https://jmeter.apache.org/
配置
  1. limit_req_zone $binary_remote_addr zone=test:10m rate=15r/s;
  2. limit_req zone=req_zone_wl burst=20 nodelay;
复制代码
3.1.2、日志

3.1.3、ngx_http_log_module

http://nginx.org/en/docs/http/ngx_http_log_module.html
1)、ngx_http_empty_gif_module

http://nginx.org/en/docs/http/ngx_http_empty_gif_module.html
2)、json

  1. log_format  ngxlog json '{"timestamp":"$time_iso8601",'
  2.                     '"source":"$server_addr",'
  3.                     '"hostname":"$hostname",'
  4.                     '"remote_user":"$remote_user",'
  5.                     '"ip":"$http_x_forwarded_for",'
  6.                     '"client":"$remote_addr",'
  7.                     '"request_method":"$request_method",'
  8.                     '"scheme":"$scheme",'
  9.                     '"domain":"$server_name",'
  10.                     '"referer":"$http_referer",'
  11.                     '"request":"$request_uri",'
  12.                     '"requesturl":"$request",'
  13.                     '"args":"$args",'
  14.                     '"size":$body_bytes_sent,'
  15.                     '"status": $status,'
  16.                     '"responsetime":$request_time,'
  17.                     '"upstreamtime":"$upstream_response_time",'
  18.                     '"upstreamaddr":"$upstream_addr",'
  19.                     '"http_user_agent":"$http_user_agent",'
  20.                     '"http_cookie":"$http_cookie",'
  21.                     '"https":"$https"'
  22.                     '}';
复制代码
3)、errorlog

http://nginx.org/en/docs/ngx_core_module.html#error_log
4)、日志分割

3.1.4、重试机制

http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_next_upstream
max_fails
最大失败次数
0为标记一直可用,不查抄健康状态
fail_timeout
失败时间
当fail_timeout时间内失败了max_fails次,标记服务不可用
fail_timeout时间后会再次激活次服务
proxy_next_upstream
proxy_next_upstream_timeout
重试最大超时时间
proxy_next_upstream_tries
重试次数,包罗第一次
proxy_next_upstream_timeout时间内答应proxy_next_upstream_tries次重试
3.1.5、主动健康查抄

tengine版
https://github.com/yaoweibin/nginx_upstream_check_module
nginx贸易版
http://nginx.org/en/docs/http/ngx_http_upstream_hc_module.html
3.1.6、配置

  1.    upstream backend {
  2.            server 192.168.119.128:8080;
  3.            server 192.168.119.129:8080;
  4.         check interval=3000 rise=2 fall=5 timeout=1000 type=http;
  5.     check_http_send "HEAD / HTTP/1.0\r\n\r\n";
  6.     check_http_expect_alive http_2xx http_3xx;
  7.    }
  8.    location /status {
  9.         check_status;
  10.         access_log off;
  11.    }
  12.    location / {
  13.                 proxy_pass http://backend;
  14.                  root   html;
  15.    }
复制代码
4、Openresty

4.1、Lua

Lua 是由巴西里约热内卢天主教大学(Pontifical Catholic University of Rio de Janeiro)里的一个研究小组于1993年开发的一种轻量、小巧的脚本语言,用标准 C 语言编写,其设计目的是为了嵌入应用程序中,从而为应用程序提供灵活的扩展和定制功能。
官网:http://www.lua.org/
4.2、IDE

4.2.1、EmmyLua插件

https://github.com/EmmyLua/IntelliJ-EmmyLua
https://emmylua.github.io/zh_CN/
4.2.2、LDT 基于eclipse

https://www.eclipse.org/ldt/
4.3、Lua底子语法

4.3.1、hello world

  1. print("hello world!")
复制代码
4.3.2、保存关键字

and break do  else elseif end false  for function if in local nil not or repeat return then  true until  while
注释

  1. -- 两个减号是行注释
  2. --[[
  3. 这是块注释
  4. 这是块注释.
  5. --]]
复制代码
4.3.3、变量

1)、数字范例

Lua的数字只有double型,64bits
你可以以如下的方式表现数字
  1. num = 1024
  2. num = 3.0
  3. num = 3.1416
  4. num = 314.16e-2
  5. num = 0.31416E1
  6. num = 0xff
  7. num = 0x56
复制代码
2)、字符串

可以用单引号,也可以用双引号
也可以使用转义字符‘\n’ (换行), ‘\r’ (回车), ‘\t’ (横向制表), ‘\v’ (纵向制表), ‘\’ (反斜杠), ‘\”‘ (双引号), 以及 ‘\” (单引号)等等
下面的四种方式界说了完全相同的字符串(此中的两个中括号可以用于界说有换行的字符串)
  1. a = 'alo\n123"'
  2. a = "alo\n123""
  3. a = '\97lo\10\04923"'
  4. a = [[alo
  5. 123"]]
复制代码
3)、空值

C语言中的NULL在Lua中是nil,比如你访问一个没有声明过的变量,就是nil
4)、布尔范例

只有nil和false是 false
数字0,‘’空字符串(’\0’)都是true
5)、作用域

lua中的变量如果没有特殊分析,满是全局变量,那怕是语句块或是函数里。
变量前加local关键字的是局部变量。
4.3.4、控制语句

1)、while循环

  1. local i = 0
  2. local max = 10
  3. while i <= max do
  4. print(i)
  5. i = i +1
  6. end
复制代码
2)、if-else

  1. local function main()
  2. local age = 140
  3. local sex = 'Male'
  4.   if age == 40 and sex =="Male" then
  5.     print(" 男人四十一枝花 ")
  6.   elseif age > 60 and sex ~="Female" then
  7.    
  8.     print("old man!!")
  9.   elseif age < 20 then
  10.     io.write("too young, too simple!\n")
  11.   
  12.   else
  13.   print("Your age is "..age)
  14.   end
  15. end
  16. -- 调用
  17. main()
复制代码
3)、for循环

  1. sum = 0
  2. for i = 100, 1, -2 do
  3.         sum = sum + i
  4. end
复制代码
4.3.5、函数

  1. function myPower(x,y)
  2.   return      y+x
  3. end
  4. power2 = myPower(2,3)
  5. print(power2)
复制代码
  1. function newCounter()
  2.    local i = 0
  3.    return function()     -- anonymous function
  4.         i = i + 1
  5.         return i
  6.     end
  7. end
  8. c1 = newCounter()
  9. print(c1())  --> 1
  10. print(c1())  --> 2
  11. print(c1())
复制代码
4.3.6、返回值

  1. name, age,bGay = "yiming", 37, false, "yimingl@hotmail.com"
  2. print(name,age,bGay)
复制代码
  1. function isMyGirl(name)
  2. return name == 'xiao6' , name
  3. end
  4. local bol,name = isMyGirl('xiao6')
  5. print(name,bol)
复制代码
4.3.6、Table

key,value的键值对 雷同 map
  1. local function main()
  2. dog = {name='111',age=18,height=165.5}
  3. dog.age=35
  4. print(dog.name,dog.age,dog.height)
  5. print(dog)
  6. end
  7. main()
复制代码
4.3.6、数组

  1. local function main()
  2. arr = {"string", 100, "dog",function() print("wangwang!") return 1 end}
  3. print(arr[4]())
  4. end
  5. main()
复制代码
4.3.7、遍历

  1. arr = {"string", 100, "dog",function() print("wangwang!") return 1 end}
  2. for k, v in pairs(arr) do
  3.    print(k, v)
  4. end
复制代码
4.3.8、成员函数

  1. local function main()
  2. person = {name='旺财',age = 18}
  3.   function  person.eat(food)
  4.     print(person.name .." eating "..food)
  5.   end
  6. person.eat("骨头")
  7. end
  8. main()
复制代码
5、Openresty Nginx + Lua

Nginx是一个主历程配合多个工作历程的工作模式,每个历程由单个线程来处理多个毗连。
在生产环境中,我们往往会把cpu内核直接绑定到工作历程上,从而提升性能。
5.1、安装

5.1.1、预编译安装

以CentOS举例 其他体系参照:http://openresty.org/cn/linux-packages.html
你可以在你的 CentOS 体系中添加 openresty 堆栈,这样就可以便于将来安装或更新我们的软件包(通过 yum update 命令)。运行下面的命令就可以添加我们的堆栈:

5.1.2、源码编译安装

5.1.3、下载

http://openresty.org/cn/download.html
最小版本基于nginx1.21
./configure
然后在进入 openresty-VERSION/ 目录, 然后输入以下命令配置:
./configure
默认, --prefix=/usr/local/openresty 程序会被安装到/usr/local/openresty目录。
依赖 gcc openssl-devel pcre-devel zlib-devel
安装:yum install gcc openssl-devel pcre-devel zlib-devel postgresql-devel
您可以指定各种选项,比如
  1. ./configure --prefix=/opt/openresty \
  2.            --with-luajit \
  3.            --without-http_redis2_module \
  4.            --with-http_iconv_module \
  5.            --with-http_postgres_module
复制代码
试着使用 ./configure --help 查看更多的选项。
make && make install
5.1.4、服务命令

启动
Service openresty start
制止
Service openresty stop
查抄配置文件是否精确
Nginx -t
重新加载配置文件
Service openresty reload
查看已安装模块和版本号
Nginx -V
5.2、测试lua脚本

在Nginx.conf 中写入
  1.    location /lua {
  2.         default_type text/html;
  3.         content_by_lua '
  4.            ngx.say("<p>Hello, World!</p>")
  5.          ';
  6.       }
复制代码
5.3、lua-nginx-module

5.4、Nginx缓存

5.4.1、Nginx全局内存缓存

  1. lua_shared_dict shared_data 1m;
  2. local shared_data = ngx.shared.shared_data  
  3. local i = shared_data:get("i")  
  4. if not i then  
  5.     i = 1  
  6.     shared_data:set("i", i)  
  7.     ngx.say("lazy set i ", i, "<br/>")  
  8. end  
  9. i = shared_data:incr("i", 1)  
  10. ngx.say("i=", i, "<br/>")
复制代码
5.4.2、lua-resty-lrucache

Lua 实现的一个简朴的 LRU 缓存,得当在 Lua 空间里直接缓存较为复杂的 Lua 数据结构:它相比 ngx_lua 共享内存字典可以省去较昂贵的序列化操作,相比 memcached 这样的外部服务又能省去较昂贵的 socket 操作
https://github.com/openresty/lua-resty-lrucache
引用lua文件
  1.                 content_by_lua_block {
  2.                 require("my/cache").go()
  3.             }
复制代码
自界说函数
  1. local _M = {}
  2. lrucache = require "resty.lrucache"
  3. c, err = lrucache.new(200)  -- allow up to 200 items in the cache
  4. ngx.say("count=init")
  5. if not c then
  6.     error("failed to create the cache: " .. (err or "unknown"))
  7. end
  8. function _M.go()
  9. count = c:get("count")
  10. c:set("count",100)
  11. ngx.say("count=", count, " --<br/>")
  12. if not count then  
  13.     c:set("count",1)
  14.     ngx.say("lazy set count ", c:get("count"), "<br/>")  
  15. else
  16. c:set("count",count+1)
  17. ngx.say("count=", count, "<br/>")
  18. end
  19. end
  20. return _M
复制代码
打开lua_code_cache
5.5、lua-resty-redis访问redis

https://github.com/openresty/lua-resty-redis
5.5.1、常用方法

  1. local res, err = red:get("key")
  2. local res, err = red:lrange("nokey", 0, 1)
  3. ngx.say("res:",cjson.encode(res))
复制代码
5.5.2、创建毗连

  1. red, err = redis:new()
  2. ok, err = red:connect(host, port, options_table?)
复制代码

https://github.com/steve0511/resty-redis-cluster
5.6、redis2-nginx-module

redis2-nginx-module是一个支持 Redis 2.0 协议的 Nginx upstream 模块,它可以让 Nginx 以非阻塞方式直接防问远方的 Redis 服务,同时支持 TCP 协议和 Unix Domain Socket 模式,并且可以启用强盛的 Redis 毗连池功能。

5.7、lua-resty-mysql

  https://github.com/openresty/lua-resty-mysql
  1. local mysql = require "resty.mysql"
  2.                 local db, err = mysql:new()
  3.                 if not db then
  4.                     ngx.say("failed to instantiate mysql: ", err)
  5.                     return
  6.                 end
  7.                 db:set_timeout(1000) -- 1 sec
  8.                 local ok, err, errcode, sqlstate = db:connect{
  9.                     host = "192.168.44.211",
  10.                     port = 3306,
  11.                     database = "zhangmen",
  12.                     user = "root",
  13.                     password = "111111",
  14.                     charset = "utf8",
  15.                     max_packet_size = 1024 * 1024,
  16.                 }
  17.                 ngx.say("connected to mysql.<br>")
  18.                 local res, err, errcode, sqlstate = db:query("drop table if exists cats")
  19.                 if not res then
  20.                     ngx.say("bad result: ", err, ": ", errcode, ": ", sqlstate, ".")
  21.                     return
  22.                 end
  23.                 res, err, errcode, sqlstate =
  24.                     db:query("create table cats "
  25.                              .. "(id serial primary key, "
  26.                              .. "name varchar(5))")
  27.                 if not res then
  28.                     ngx.say("bad result: ", err, ": ", errcode, ": ", sqlstate, ".")
  29.                     return
  30.                 end
  31.                 ngx.say("table cats created.")
  32.                 res, err, errcode, sqlstate =
  33.                     db:query("select * from t_emp")
  34.                 if not res then
  35.                     ngx.say("bad result: ", err, ": ", errcode, ": ", sqlstate, ".")
  36.                     return
  37.                 end
  38.                 local cjson = require "cjson"
  39.                 ngx.say("result: ", cjson.encode(res))
  40.                 local ok, err = db:set_keepalive(10000, 100)
  41.                 if not ok then
  42.                     ngx.say("failed to set keepalive: ", err)
  43.                     return
  44.                 end
复制代码
6、模板实时渲染 lua-resty-template

https://github.com/bungle/lua-resty-template
如果学习过JavaEE中的servlet和JSP的话,应该知道JSP模板最终会被翻译成Servlet来执行;
而lua-resty-template模板引擎可以以为是JSP,其最终会被翻译成Lua代码,然后通过ngx.print输出。
lua-resty-template大体内容有:
l 模板位置:从那边查找模板;
l 变量输出/转义:变量值输出;
l 代码片段:执行代码片段,完成如if/else、for等复杂逻辑,调用对象函数/方法;
l 注释:解释代码片段含义;
l include:包含另一个模板片段;
l 其他:lua-resty-template还提供了不需要剖析片段、简朴布局、可复用的代码块、宏指令等支持。
底子语法
l {(include_file)}:包含另一个模板文件;
l {* var *}:变量输出;
l {{ var }}:变量转义输出;
l {% code %}:代码片段;
l {# comment #}:注释;
l {-raw-}:中心的内容不会剖析,作为纯文本输出;
6.1、lua代码热加载

在http模块中加入
  1. lua_code_cache off
  2. ;
复制代码
reload后Nginx会提示影响性能,记得在生产环境中关掉。
6.2、测试

6.2.1、初始化

  1. -- Using template.new
  2. local template = require "resty.template"
  3. local view = template.new "view.html"
  4. view.message = "Hello, World!"
  5. view:render()
  6. -- Using template.render
  7. -- template.render("view.html", { message = "Hel11lo, Worl1d!" })
复制代码
6.2.2、执行函数,得到渲染之后的内容

  1. local func = template.compile("view.html")  
  2. local content = func(context)  
  3. ngx.say("xx:",content)
复制代码
模板文件存放位置
nginx.conf中配置
  1. set $template_root /usr/local/openresty/nginx/tmp;
复制代码
6.2.3、resty.template.html

  1. local template = require("resty.template")
  2. local html = require "resty.template.html"
  3. template.render([[
  4. <ul>
  5. {% for _, person in ipairs(context) do %}
  6.     {*html.li(person.name)*} --
  7. {% end %}
  8. </ul>
  9. <table>
  10. {% for _, person in ipairs(context) do %}
  11.     <tr data-sort="{{(person.name or ""):lower()}}">
  12.         {*html.td{ id = person.id }(person.name)*}
  13.     </tr>
  14. {% end %}
  15. </table>]], {
  16.     { id = 1, name = "Emma"},
  17.     { id = 2, name = "James" },
  18.     { id = 3, name = "Nicholas" },
  19.     { id = 4 }
  20. })
复制代码
6.2.4、模板内容

  1. <!DOCTYPE html>
  2. <html>
  3. <body>
  4.   <h1>{{message}}</h1>
  5. </body>
  6. </html>
复制代码
6.2.5、多值传入

  1. template.caching(false)
  2. local template = require("resty.template")
  3. local context = {
  4.     name = "lucy",
  5.     age = 50,
  6. }
  7. template.render("view.html", context)
复制代码
6.2.6、模板内容

  1. <!DOCTYPE html>
  2. <html>
  3. <body>
  4.   <h1>name:{{name}}</h1>
  5.   <h1>age:{{age}}</h1>
  6. </body>
  7. </html>
复制代码
6.2.7、模板管理与缓存

模板缓存:默认开启,开发环境可以手动关闭
template.caching(true)
模板文件需要业务体系更新与维护,当模板文件更新后,可以通过模板版本号或消息通知Openresty清空缓存重载模板到内存中
template.cache = {}
6.2.8、完整页面

  1. local template = require("resty.template")
  2. template.caching(false)
  3. local context = {
  4.     title = "测试",
  5.     name = "lucy",
  6.     description = "<script>alert(1);</script>",
  7.     age = 40,
  8.     hobby = {"电影", "音乐", "阅读"},
  9.     score = {语文 = 90, 数学 = 80, 英语 = 70},
  10.     score2 = {
  11.         {name = "语文", score = 90},
  12.         {name = "数学", score = 80},
  13.         {name = "英语", score = 70},
  14.     }
  15. }
  16. template.render("view.html", context)
复制代码
6.2.9、模板

  1. {(header.html)}  
  2.    <body>  
  3.       {# 不转义变量输出 #}  
  4.       姓名:{* string.upper(name) *}<br/>  
  5.       {# 转义变量输出 #}  
  6.       简介:{{description}}
  7.            简介:{* description *}<br/>  
  8.       {# 可以做一些运算 #}  
  9.       年龄: {* age + 10 *}<br/>  
  10.       {# 循环输出 #}  
  11.       爱好:  
  12.       {% for i, v in ipairs(hobby) do %}  
  13.          {% if v == '电影' then  %} - xxoo
  14.             
  15.               {%else%}  - {* v *}
  16. {% end %}  
  17.          
  18.       {% end %}<br/>  
  19.   
  20.       成绩:  
  21.       {% local i = 1; %}  
  22.       {% for k, v in pairs(score) do %}  
  23.          {% if i > 1 then %},{% end %}  
  24.          {* k *} = {* v *}  
  25.          {% i = i + 1 %}  
  26.       {% end %}<br/>  
  27.       成绩2:  
  28.       {% for i = 1, #score2 do local t = score2[i] %}  
  29.          {% if i > 1 then %},{% end %}  
  30.           {* t.name *} = {* t.score *}  
  31.       {% end %}<br/>  
  32.       {# 中间内容不解析 #}  
  33.       {-raw-}{(file)}{-raw-}  
  34. {(footer.html)}  
复制代码
6.2.10、layout 布局统一风格

使用模板内容嵌套可以实现全站风格同一布局
1)、lua

local template = require "resty.template"
一、
  1. local layout   = template.new "layout.html"
  2. layout.title   = "Testing lua-resty-template"
  3. layout.view    = template.compile "view.html" { message = "Hello, World!" }
  4. layout:render()
复制代码
二、
  1. template.render("layout.html", {
  2.   title = "Testing lua-resty-template",
  3.   msg = "type=2",
  4.   view  = template.compile "view.html" { message = "Hello, World!" }
  5. })
复制代码
三、
此方式重名变量值会被覆盖
  1. local view     = template.new("view.html", "layout.html")
  2. view.title     = "Testing lua-resty-template"
  3. view.msg = "type=3"
  4. view.message   = "Hello, World!"
  5. view:render()
复制代码
四、
可以区分一下
  1. local layout   = template.new "layout.html"
  2. layout.title   = "Testing lua-resty-template"
  3. layout.msg = "type=4"
  4. local view     = template.new("view.html", layout)
  5. view.message   = "Hello, World!"
  6. view:render()
复制代码
2)、layout.html

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. ​    <title>{{title}}</title>
  5. </head>
  6. <h1>layout</h1>
  7. <body>
  8. ​    {*view*}
  9. </body>
  10. </html>
复制代码
3)、view.html·

msg:{{message}}
4)、多级嵌套

lua
  1. local view     = template.new("view.html", "layout.html")
  2. view.title     = "Testing lua-resty-template"
  3. view.message   = "Hello, World!"
  4. view:render()
  5. view.html
  6. {% layout="section.html" %}
复制代码
section.html
  1. <div id="section">
  2.         <h1>msg:{{message}}</h1>
  3. ​    {*view*} - sss
  4. </div>
复制代码
layout.html
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. ​    <title>{{title}}</title>
  5. </head>
  6. <h1>layout {{msg}}</h1>
  7. <body>
  8. ​    {*view*}
  9. </body>
  10. </html>
复制代码
6.2.11、Redis缓存+mysql+模板输出

lua
  1. cjson = require "cjson"
  2. sql="select * from t_emp"
  3. local redis = require "resty.redis"
  4.                 local red = redis:new()
  5.                 red:set_timeouts(1000, 1000, 1000) -- 1 sec
  6.   local ok, err = red:connect("127.0.0.1", 6379)
  7. if not ok then
  8.                     ngx.say("failed to connect: ", err)
  9.                     return
  10.                 end
  11.         
  12.                 local res, err = red:get(sql)
  13.                 if not res then
  14.                     ngx.say("failed to get sql: ", err)
  15.                     return
  16.                 end
  17.                 if res == ngx.null then
  18.                     ngx.say("sql"..sql.." not found.")
  19. --mysql查询
  20. local mysql = require "resty.mysql"
  21.                 local db, err = mysql:new()
  22.                 if not db then
  23.                     ngx.say("failed to instantiate mysql: ", err)
  24.                     return
  25.                 end
  26.                 db:set_timeout(1000) -- 1 sec
  27.                 local ok, err, errcode, sqlstate = db:connect{
  28.                     host = "192.168.44.211",
  29.                     port = 3306,
  30.                     database = "zhangmen",
  31.                     user = "root",
  32.                     password = "111111",
  33.                     charset = "utf8",
  34.                     max_packet_size = 1024 * 1024,
  35.                 }
  36.                 ngx.say("connected to mysql.<br>")
  37. res, err, errcode, sqlstate =
  38.                     db:query(sql)
  39.                 if not res then
  40.                     ngx.say("bad result: ", err, ": ", errcode, ": ", sqlstate, ".")
  41.                     return
  42.                 end
  43.           --ngx.say("result: ", cjson.encode(res))
  44.       ok, err = red:set(sql, cjson.encode(res))
  45.                 if not ok then
  46.                     ngx.say("failed to set sql: ", err)
  47.                     return
  48.                 end
  49.                 ngx.say("set result: ", ok)
  50.                     return
  51.                 end
  52. local template = require("resty.template")
  53. template.caching(false)
  54. local context = {
  55.     title = "测试",
  56.     name = "lucy",
  57.     description = "<script>alert(1);</script>",
  58.     age = 40,
  59.     hobby = {"电影", "音乐", "阅读"},
  60.     score = {语文 = 90, 数学 = 80, 英语 = 70},
  61.     score2 = {
  62.         {name = "语文", score = 90},
  63.         {name = "数学", score = 80},
  64.         {name = "英语", score = 70},
  65.     },
  66. zhangmen=cjson.decode(res)
  67. }
  68. template.render("view.html", context)
复制代码
模板
  1. {(header.html)}  
  2.    <body>  
  3.       {# 不转义变量输出 #}  
  4.       姓名:{* string.upper(name) *}<br/>  
  5.       {# 转义变量输出 #}  
  6.       年龄: {* age + 10 *}<br/>  
  7.       {# 循环输出 #}  
  8.       爱好:  
  9.       {% for i, v in ipairs(hobby) do %}  
  10.          {% if v == '电影' then  %} - xxoo
  11.             
  12.               {%else%}  - {* v *}
  13. {% end %}  
  14.          
  15.       {% end %}<br/>  
  16.   
  17.       成绩:  
  18.       {% local i = 1; %}  
  19.       {% for k, v in pairs(score) do %}  
  20.          {% if i > 1 then %},{% end %}  
  21.          {* k *} = {* v *}  
  22.          {% i = i + 1 %}  
  23.       {% end %}<br/>  
  24.       成绩2:  
  25.       {% for i = 1, #score2 do local t = score2[i] %}  
  26.          {% if i > 1 then %},{% end %}  
  27.           {* t.name *} = {* t.score *}  
  28.       {% end %}<br/>  
  29.       {# 中间内容不解析 #}  
  30.       {-raw-}{(file)}{-raw-}  
  31. 掌门:
  32. {* zhangmen *}
  33.    {% for i = 1, #zhangmen do local z = zhangmen[i] %}  
  34.          {* z.deptId *},{* z.age *},{* z.name *},{* z.empno *},<br>
  35.       {% end %}<br/>  
  36. {(footer.html)}  
复制代码
7、Lua 开源项目

7.1、WAF

https://github.com/unixhot/waf
https://github.com/loveshell/ngx_lua_waf
l 防止 SQL 注入,本地包含,部分溢出,fuzzing 测试,XSS/SSRF 等 Web 攻击
l 防止 Apache Bench 之类压力测试工具的攻击
l 屏蔽常见的扫描黑客工具,扫描器
l 屏蔽图片附件类目录执行权限、防止 webshell 上传
l 支持 IP 白名单和黑名单功能,直接将黑名单的 IP 访问拒绝
l 支持 URL 白名单,将不需要过滤的 URL 进行界说
l 支持 User-Agent 的过滤、支持 CC 攻击防护、限定单个 URL 指定时间的访问次数
l 支持支持 Cookie 过滤,URL 与 URL 参数过滤
l 支持日志记录,将所有拒绝的操作,记录到日志中去
7.2、Kong 基于Openresty的流量网关

https://konghq.com/
https://github.com/kong/kong
Kong 基于 OpenResty,是一个云原生、快速、可扩展、分布式的微服务抽象层(Microservice Abstraction Layer),也叫 API 网关(API Gateway),在 Service Mesh 里也叫 API 中心件(API Middleware)。
Kong 开源于 2015 年,核心代价在于高性能和扩展性。从环球 5000 强的构造统计数据来看,Kong 是如今依然在维护的,在生产环境使用最广泛的 API 网关。
Kong 宣称本身是世界上最盛行的开源微服务 API 网关(The World’s Most Popular Open Source Microservice API Gateway)。
核心优势:
l 可扩展:可以方便的通过添加节点水平扩展,这意味着可以在很低的延迟下支持很大的体系负载。
l 模块化:可以通过添加新的插件来扩展 Kong 的能力,这些插件可以通过 RESTful Admin API 来安装和配置。
l 在任何底子架构上运行:Kong 可以在任何地方都能运行,比如在云或肴杂环境中部署 Kong,单个或环球的数据中心。
7.3、APISIX

7.4、ABTestingGateway

https://github.com/CNSRE/ABTestingGateway
ABTestingGateway 是一个可以动态设置分流策略的网关,关注与灰度发布相干范畴,基于 Nginx 和 ngx-lua 开发,使用 Redis 作为分流策略数据库,可以实现动态调理功能。
ABTestingGateway 是新浪微博内部的动态路由体系 dygateway 的一部分,如今已经开源。在以往的基于 Nginx 实现的灰度体系中,分流逻辑往往通过 rewrite 阶段的 if 和 rewrite 指令等实现,长处是性能较高,缺点是功能受限、容易堕落,以及转发规则固定,只能静态分流。ABTestingGateway 则接纳 ngx-lua,通过启用 lua-shared-dict 和 lua-resty-lock 作为体系缓存和缓存锁,体系得到了较为接近原生 Nginx 转发的性能。
l 支持多种分流方式,如今包罗 iprange、uidrange、uid 尾数和指定uid分流
l 支持多级分流,动态设置分流策略,即时见效,无需重启
l 可扩展性,提供了开发框架,开发者可以灵活添加新的分流方式,实现二次开发
l 高性能,压测数据接近原生 Nginx 转发
l 灰度体系配置写在 Nginx 配置文件中,方便管理员配置
l 实用于多种场景:灰度发布、AB 测试和负载均衡等

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 IT评测·应用市场-qidao123.com技术社区 (https://dis.qidao123.com/) Powered by Discuz! X3.4