亚马逊AWS官方博客

Amazon CloudFront 部署小指南(十五)- CloudFront Standard logging (v2) 优化场景应用

背景

AWS CloudFront 原生可以提供 Distribution 维度的监控,例如请求数、下载数据量、命中率等,但在生产环境中经常会出现一个 Distribution 下绑定多个域名的场景,这时 Distribution ID 无法与一个域名一一对应,所以无法提供用户希望的域名维度监控数据。此前的解决方案是通过解析 CloudFront Real-time logging 或  Standard logging(legacy) 统计出域名维度的监控指标,但利用 Real-time logging 的方案费用较高,而利用 Standard logging(legacy) 的方案延迟相对较大(在日志量大的情况下,准确的指标统计工作完成需要等待达到小时级别的时长)。AWS CloudFront 推出了 Standard logging (v2) 功能,它相较 Real-time logging 成本更低,又比 Standard logging(legacy) 延迟低且灵活,而且为用户提供了多种日志输出格式和目标。

本文通过两个典型案例来展示 Standard logging (v2) 是如何优化之前的方案的:1)Standard logging (v2)格式化输出到S3,替换 Standard logging (legacy);2)Standard logging (v2) 输出到 Cloudwatch Log Groups 实现自定义监控。

Standard logging (v2)特性

丰富、可定制化的日志内容

Standard logging (v2) 提供了 39 个日志字段,用户可以根据实际需求选择性使用,避免没有必要的资源浪费,相比于 logging(legacy) 增加了 4 个日志字段:

  • timestamp(ms):这个字段提供了更精准的日志时间。
  • origin-fbl,origin-lbl:这两个字段有助于分析边缘节点到后端源站之间的网络延期情况。
  • asn:该字段可以帮助用户分析运营商的网络性能和故障。

灵活的日志输出方式

  • 输出到 CloudWatch Log Group:CloudWatch 内嵌的 Logs Insights 功能支持直接对 Log Group 中的日志进行查询分析,简化了用户分析日志和定位问题的难度,此前都需要将 CloudFront 日志输出到 S3,并建立 Athena 日志表结构,然后才能利用 Athena 对日志进行扫描分析。
  • 输出到 Firehouse:Standard logging (v2) 与 Firehouse 相结合使用可以满足对 CloudFront 日志信息进行二次加工的需求,例如:需要通过分析客户端 IP 来判断访问客户端所在国家或地理位置,可以利用 Firehouse 配合 Lambda 来实现。
  • 输出到 S3:相比于 CloudFront standard logging(legacy),用户可以对日志字段裁剪,将没有必要的字段去掉节省存储和处理成本。而且 Standard logging (v2) 可以直接按照分区格式输出的 S3,而此前 logging(legacy) 没有自动分区功能,用户需要配置定时任务触发 Lambda 对 CloudFront 日志文件进行剪切并分区存储。

横向对比

Real-time log Standard v1 S3 Legacy Standard v2
延迟 <30 秒 <1 小时 <5 分钟
成本对比
支持字段数量  67 个 35 个 39 个
字段定制化 支持 不支持 支持
输出目标 Kinesis Data Stream S3 S3, Kinesis Firehouse, CloudWatch
输出格式 Plain Text Plain Text W3C / JSON/Parquet/Plain text
分区查询 不支持 不支持 支持

案例一:自定义日志以格式化形式输出到 S3

此前,在没有 Standard logging (v2) 功能时,如果对 CloudFront 的标准日志进行分析,需要将 CloudFront 标准日志输出到 S3,然后使用 Athena 对 S3 中的日志进行扫描。但此方案 CloudFront 标准日志会输出到一个指定 S3 目录中,并未进行任何分区,所以 Athena 必须对全量日志进行扫描,这样会造成大量资源浪费,通常的优化方法是使用 Lambda 对输出到 S3 的 CloudFront 标准日志进行分区处理,增加了部署复杂度和成本。目前,CloudFront Standard logging (v2) 支持以分区形式发送日志到 S3,并且日志字段和输出的文件格式都是可选的,这样既省去了引入额外 Lambda 的成本,又通过对日志字段进行剪切也减少了 Athena 扫面的数据量。

配置步骤(Console 模式)

1. 创建 Logv2 日志组

在 CloudFront – Distribution – <Distribution ID> 界面下,点击“Logging”Tab,点击“Add”,选择“Amazon S3”

在弹出的窗口中配置 S3 相关参数 — 目标存储桶信息

通过展开“Additional settings”,可以:1)对输出字段做精简或者定制;2)定义 Partition 分区命名;3)使用兼容 Hive 的文件格式(<key>=<value>);4)定义文件输出格式(Plain-Text / W3C / Parquet / JSON 可供选择)和分隔符定义。点击“Submit”,完成 Logv2 标准日志的配置。

2. 通过 Athena 进行查询(可选)

在 Athena 中使用建表 SQL 创建外表 cloudfront_logv2,由于 Standard logging (v2) 已经按照分区目录形式进行存储了,在 SQL 语句中也需要指定分区路径格式:PARTITIONED BY (year string, month string, day string, hour string),SQL 如下:

CREATE EXTERNAL TABLE cloudfront_logv2 (
timestamp STRING,
x_edge_location STRING,
sc_bytes BIGINT,
c_ip STRING,
cs_method STRING,
cs_host STRING,
cs_uri_stem STRING,
sc_status STRING,
referer STRING,
user_agent STRING,
cs_uri_query STRING,
x_edge_result_type STRING,
x_edge_request_id STRING,
x_host_header STRING,
cs_protocol STRING,
cs_bytes BIGINT,
time_to_first_byte BIGINT
)
PARTITIONED BY (year string, month string, day string, hour string)
ROW FORMAT DELIMITED FIELDS TERMINATED BY ' '
LOCATION 's3://XXXXXX/XXXXX/'
TBLPROPERTIES ( 'skip.header.line.count'='2' )
SQL

SQL 执行成功后,可以在 Athena 中看到表 cloudfront_logv2 已经出现。

注意:虽然日志已经按照分区路径存储在 S3 中,但还需执行 SQL 命令将当前目录增加到分区中,而且每次新增的目录都需要手动添加到分区中,如果想要实现自动化将新增目录添加到分区中请参考 Athena 分区投影功能,本文就不在此赘述。添加现有目录到分区中的 SQL 命令如下:

MSCK REPAIR TABLE cloudfront_logv2
SQL

至此,我们可以在 Athena 中使用 SQL 来分析已经分区存储的 Cloudfront Standard logging (v2)。

案例二:巧用 CloudFront Logv2 进行自定义 CloudWatch 指标

本方案会将 CloudFront Standard logging (v2) 输出到 CloudWatch Log Groups 中,然后利用 Log Groups Metric Filters 功能生成域名维度的准实时监控,例如:域名维度的请求命中率、域名维度的请求量、域名维度的数据下载量、域名维度的响应状态码统计。架构图,如下:

配置步骤

1. 创建 CloudWatch Log Group

提前在 AWS Virginia Region 创建 CloudWatch Log Group 作为 CloudFront 发送日志的目标

2. 开启 CloudFront logging v2

创建 CloudFront logging v2,并选择将 CloudWatch Logs 作为日志的发送目的地

目前 CloudFront logging v2 支持 39 个字段,用户可以只选择业务关心的字段,本案例只需要选择 4 个字段就可以满足需求,输出格式为 Plain-text,使用空格进行字段分隔。

使用 Cloudwatch Log Filters 生成 Metrics

等待几分钟后,就可以看到 CloudFront 已经将日志发送到 Cloudwatch log 中。

3. 创建 CloudWatch Log Group Metric Filter

现在我们需要创建一个 CloudWatch Log Group Metric Filter 用于统计日志里的指标,然后将聚合后的数据以 Metric 的形式发送到 CloudWatch Metric 中。在 Metric Filter 中可以加载少量日志用于查看日志格式和字段顺序,然后创建一个 Filter Parttern [bytes, host, status, result](注意字段顺序),你也可以根据自己需求增加过滤条件。

Metric Namespace 第一次可以创建一个新的,后续可以复用。由于我们要统计的是请求量所以 Metrics Name 定义为 Requests,Value 定义为 1,意味着每接受一个请求日志该指标会自动增加 1,单位为 Count。Dimension 最多支持 3 项,本案例中要对请求域名、边缘节点、请求状态这三个维度进行统计。

创建一个统计不同命中结果的数据下载量 Metric,再创建一个统计不同状态码的请求量 Metric。至此,我们在这个 Log Groups 下创建了三个 Filters,如下图:

4. 聚合分析 Metrics 生成监控 Dashboard

我们可以在 Cloudwatch 中看到刚刚创建的 Custom namespaces,并在 namespaces 里分析我们聚合的 Metrics

统计一个域名下不同命中状态的流量数据

统计一个域名下不同命中状态的请求数量

统计一个域名下不同响应状态码的请求数量

CloudFront Logv2 成本概述

CloudFront Logv2 成本分为 2 个部分:1)日志费用。2)日志投送的目标服务产生的相关费用。

使用 S3 作为目的,不收取日志费用(Parquet 文件格式除外,如果 S3 输出格式是 Parquet,将额外收取 $0.035 per GB 的费用)。使用 CloudWatch Log Groups 作为目的,如果每行日志的字节数小于 750 字节,日志费用会被自动免除;如果超过了 750 字节,超出的部分将按照日志输出的字节数进行费用收取(价格参考下表)。使用 Kinesis Data Firehose 作为目的,直接按照日志输出的字节数进行费用收取(价格参考下表)。

目标服务产生的相关费用主要包括:1)S3 – 存储费用。2)CloudWatch Log Group 存储费用 / Metric 使用费用。3)Kinesis Data FireHose 的数据处理费用。CloudFront Logv2 的 S3 存储费用和使用 CloudFront Log Legacy 的费用是一致的;CloudWatch 部分建议设置相对短的存储时间(比如 1 周),以有效控制存储费用。

总结

根据上面两个典型的案例可以看到 Standard logging (v2) 是对之前的 CloudFront 标准日志的功能增强,在日志分析场景和定制化监控场景都提供了更简单和高效的解决方案。利用 CloudFront Standard logging (v2) 集成 CloudWatch 构建了域名维度准实时监控,包含了指定域名下不同缓存命中情况的请求数量、指定域名下不同缓存命中情况的数据下载量、指定域名下不同状态码的请求数量,弥补了原生 CloudFront 原生监控不支持域名维度监控的缺失。由于我们选择了最小范围的 CloudFront 日志字段(远低于 750 bytes),符合 CloudFront 日志输出免费条件,而且 CloudWatch 的存储成本以及指标成本都不高,所以总体成本可控

本篇作者

刘欣然

亚马逊云科技解决方案架构师,目前负责互联网媒体行业云端应用的架构设计与技术咨询。在加入亚马逊云科技之前从事多年互联网开发工作,目前专注于 Devops 与边缘计算领域。

Sam Ye

亚马逊云科技边缘产品架构师,负责 CloudFront 和 Global Accelerator 服务在中国和全球的市场拓展,专注于互联网用户访问云上服务的感受的优化以及数据洞察。在互联网基础设施领域有丰富的实践经验。