需通过nginx日志记录真实客户端ip、结合geoip解析(如lua-resty-maxminddb或nginx-prometheus-exporter正则提取)打标地域信息,再由prometheus按country/city分组计算p95延迟,最后在grafana用worldmap或heatmap面板以国家代码为地理字段、延迟值为指标渲染热力图。

要实现 Nginx 在 Grafana 中展示不同地域用户的访问延迟热力图,关键不是直接让 Nginx “知道”用户在哪,而是通过日志中可推断地理位置的信息(如客户端 IP),结合 GeoIP 解析与指标打标,最终在 Grafana 中用 Heatmap 或 Worldmap 面板呈现。
一、确保 Nginx 日志记录真实客户端 IP
默认情况下,Nginx 的 $remote_addr 是上游代理(如 CDN、LB)的地址。需先还原真实用户 IP:
- 若前端有 CDN 或反向代理,确保它在请求头中透传真实 IP,例如:
X-Forwarded-For: 203.123.45.67, 192.168.1.1 - 在 Nginx 配置中使用
set_real_ip_from和real_ip_header还原:set_real_ip_from 10.0.0.0/8; # 你的 CDN 或 LB 网段 real_ip_header X-Forwarded-For; real_ip_recursive on;
- 然后在日志格式中使用
$realip_remote_addr(或$http_x_forwarded_for的首 IP)替代$remote_addr。
二、在日志中加入地理标签(GeoIP)
Nginx 本身不内置 GeoIP v2,但可通过以下任一方式注入地域维度:
-
方式 A:使用 nginx-plus 或 OpenResty + lua-resty-maxminddb(推荐)
编译时启用 Lua 模块,加载 MaxMind GeoLite2 City 数据库,在 log_format 中动态写入:log_format geo_log '$realip_remote_addr $geoip2_data_country_code $geoip2_data_city_name ' '$request_time $upstream_response_time $status'; access_log /var/log/nginx/access_geo.log geo_log;此时每条日志含
CN、US、Frankfurt等字段,后续可被 exporter 解析为标签。 -
方式 B:用 nginx-prometheus-exporter 的 log parsing 模式
启动 exporter 时指定 access log 路径,并配置正则提取地理字段:./nginx-prometheus-exporter \ --web.listen-address=:9113 \ --nginx.scrape-uri=http://localhost/nginx_status \ --nginx.exporter.log-format='^(?P<ip>\S+) (?P<country>\S+) (?P<city>[^ ]+) .* request_time=(?P<rt>\S+)'</rt></city></country></ip>
它会将
country、city自动转为 Prometheus 标签,如:nginx_http_request_seconds_sum{country="CN", city="Shenzhen"}
三、Prometheus 抓取并保留地理标签
- 确保抓取 job 不做提前聚合(避免丢标):
- job_name: 'nginx-geo' static_configs: - targets: ['nginx-exporter:9113'] # 不加 relabel_configs 删除 country/city 标签! - 计算地域延迟时,用
histogram_quantile按 country 分组:histogram_quantile(0.95, sum(rate(nginx_http_request_seconds_bucket[5m])) by (le, country))
四、Grafana 中配置热力图面板
- 使用 Worldmap Panel(需插件)或 Heatmap Panel(内置):
- 数据源选 Prometheus;
- 查询用
sum by(country) (rate(nginx_http_request_seconds_sum[5m])) / sum by(country) (rate(nginx_http_request_seconds_count[5m]))得平均延迟; - 或更推荐用 P95:
histogram_quantile(0.95, sum(rate(...bucket[5m])) by (le, country)); - 在 Worldmap 设置中:
- Location Data → Geohash / Country Code;
- Mode → Countries;
- Country Code Field →
country(Prometheus 标签名); - Metric Field → 延迟值(单位秒或毫秒);
- 颜色映射建议用红→黄→绿表示高→中→低延迟。
示例效果:中国区域显示深红色(P95 = 420ms),德国法兰克福浅黄色(110ms),美国西海岸绿色(75ms),直观暴露跨域链路瓶颈。
不复杂但容易忽略











