既要、又要!NJet支持不落盘的web服务访问记录分析报表了!

🙈 By 赵延刚, 单雷 2024-07-12

1. 背景需求

访问日志是目前web server,proxy最常用的问题跟踪、统计分析的源头。所以尽管由于IO,产生访问日志对系统的的影响很大(据客户的实际反馈,因打开访问日志,系统性能有50%以上的损耗),但在正式的上线环境中应该尽量打开访问日志。然后,产生的日志作为源头,会被输出到ES等统一的日志平台进行分析处理,或被各式各样的日志分析工具进行分析。比如一款开源的基于c编写的日志分析工具goaccess,就可以既在命令行下使用,也提供HTML格式的报表。

img

其产生的报表可以有命令行的:

img

或 html格式的:

img

以上图片来源于:https://goaccess.io/

当然,NJet针对落盘影响性能这个问题也做了很多优化,比如:

  1. 动态配置访问日志,仅仅在某个具体的访问url,仅仅在分析故障阶段打开,并在分析定位完成后尽快关闭;
  2. 动态输出日志到远端,避免磁盘IO的影响。但这个优化是减少了IO,也少输出了记录,影响了用户分析自己的网站的完整性。

在分析了goaccess的代码后,我们觉得,可以把NJet和goaccess结合起来,由NJet直接把访问记录提供给goaccess,复用goaccess经历社区需求验证的分析报表。这样即提供了丰富的分析报表,又避免了IO对性能的影响。

img

2. 实现简介

2.1 架构设计

img

goaccess原使用基于堆内存的hash存储报表数据,修改为共享内存存储。NJet 的工作进程在一个HTTP请求完成后,直接产生符合goaccess要求的统计信息计入共享内存中。

同时goaccess作为一个单独的CoPilot嵌入NJet中,并对外提供数据的实时更新。

运维人员通过NJet的统一的控制面端口访问,获得实时的报表。

2.2 相关指令

Syntax: access_log_zone name size.
Default:
Context: NJT_HTTP_MAIN_CONF
  • name: 共享内存的名字。
  • size: 共享内存大小。

例如: access_log_zone abc 1m;

Syntax: access_log_zone_valid days
Default:
Context: NJT_HTTP_MAIN_CONF
  • days: 统计日志保存的天数。

例如: access_log_zone_valid 3;

2.3 配置文件变更

2.3.1 数据面

njet.conf中需要 在main节新增加CoPilot配置,及加载so:

helper access_data modules/njt_helper_access_data_module.so conf/goaccess.conf;
load_module modules/njt_http_access_log_zone_module.so;

在html节增加zone相关的配置

access_log_zone  log_zone 100m;
access_log_zone_valid  3;

2.3.2 控制面

在njet_ctr中新增加goaccess报表的访问路径

  location /report/ {
            root html;
        }
         location /ws {
          proxy_pass http://127.0.0.1:7890;
        }

2.3.3 goaccess.conf

output html/report/report.html
real-time-html true

3. 测试

在如下的测试场景中,NJet部署在机器i192.168.40.139,其监听8080,控制面端口8081

load_module modules/njt_http_sendmsg_module.so;
load_module modules/njt_ctrl_config_api_module.so;
load_module modules/njt_helper_health_check_module.so;
load_module modules/njt_http_upstream_api_module.so;
load_module modules/njt_http_location_api_module.so;
load_module modules/njt_http_dyn_server_api_module.so;
load_module modules/njt_doc_module.so;
load_module modules/njt_http_vtsd_module.so;
load_module modules/njt_http_ssl_api_module.so;

#load_module modules/njt_stream_stsd_module.so;
#load_module modules/njt_http_lua_module.so;

error_log logs/error_ctrl.log debug;

events {
    worker_connections  1024;
}

http {
    include mime.types;
    access_log off;
    server {
        listen       8081;

        location / {
            return 200 "njet control panel\n";
        }

        location /api {
            dyn_module_api;
        }

        location /doc {
           doc_api;
        }

        location /report/ {
            root html;
        }
         location /ws {
          proxy_pass http://127.0.0.1:7890;
        }

        location /metrics {
           vhost_traffic_status_display;
            vhost_traffic_status_display_format html;
        }

    }
}

conf/goaccess.conf

output html/report/report.html
real-time-html true

测试结果:

在访问server(8080)一段时间后,可以通过控制面端口(http://192.168.40.139:8081/report/report.html)查看报表信息

img

其他说明

  • CoPilot,控制面、数据面等概念请参考用户指南中NJet架构说明
  • 感谢goaccess提供的丰富访问日志报表
  • 由于不再处理日志文件,报表页面展现的某些数据是无效的,如日志分析的字节数等。
  • 本功能在3.0.1起支持
  • 目前统计数据尚没有持久化,重启会丢失,会在下一个版本中解决