如何统计S3对象访问次数?替代PHP访问统计的技术咨询
用S3 + CloudFront统计Widget访问量的可行方案
嘿,针对你遇到的PHP统计接口过载问题,咱可以用S3和CloudFront的原生能力搭配AWS无服务器工具来实现高效的访问统计,替代原来的1x1像素请求方案,下面给你几个具体的落地思路:
方案一:CloudFront访问日志 + 日志分析(低成本、非实时)
这是最省心的低成本方案,适合不需要实时数据的场景:
- 第一步:开启CloudFront访问日志
进入CloudFront控制台,找到你的分发,开启「标准日志」,指定一个S3桶来存储日志文件。日志里会包含每个请求的详细信息:请求的资源路径、时间戳、HTTP状态码等。 - 第二步:区分客户资源
确保每个客户的Widget资源(JS/CSS)有唯一的标识,比如给每个客户分配专属前缀:widgets/customer_xxx/main.js,这样在日志里就能通过路径过滤出对应客户的所有请求。 - 第三步:分析日志统计次数
用Amazon Athena直接查询S3里的日志文件,写简单的SQL就能统计每个客户的访问量,比如:
也可以用Amazon QuickSight把统计结果做成可视化报表,方便你随时查看。SELECT uri, COUNT(*) AS request_count FROM cloudfront_logs WHERE uri LIKE '/widgets/customer_xxx/%' AND date >= '2024-01-01' GROUP BY uri;
方案二:Lambda@Edge + DynamoDB(实时统计、高并发)
如果需要实时获取访问数据,这个方案更合适,完全无服务器,不用担心过载:
- 第一步:部署Lambda@Edge函数
创建一个Lambda函数(必须在us-east-1区域),绑定CloudFront的「Viewer Request」事件——每次用户请求你的Widget资源时,这个函数就会被触发。 - 第二步:在Lambda中统计计数
函数里提取请求路径中的客户标识(比如从/widgets/customer_xxx/main.js里拿到customer_xxx),然后调用DynamoDB的UpdateItem接口,给对应客户的计数加1。示例代码片段:const AWS = require('aws-sdk'); const dynamodb = new AWS.DynamoDB.DocumentClient(); exports.handler = async (event) => { const request = event.Records[0].cf.request; const uriParts = request.uri.split('/'); const customerId = uriParts[2]; // 假设路径格式是/widgets/{customerId}/xxx.js await dynamodb.update({ TableName: 'WidgetAccessCounts', Key: { customerId: customerId }, UpdateExpression: 'ADD requestCount :inc', ExpressionAttributeValues: { ':inc': 1 }, ReturnValues: 'UPDATED_NEW' }).promise(); return request; // 继续转发请求到S3 }; - 第三步:配置DynamoDB表
创建一个DynamoDB表,主键设为customerId,字段requestCount用来存储访问次数。可以用按需模式,自动适配并发请求量,不用手动配置容量。
方案三:Lambda@Edge + CloudWatch自定义指标(实时可视化)
如果只需要看实时的访问指标,不需要存储详细记录,这个方案更轻量:
- 第一步:Lambda@Edge中上报指标
在触发的Lambda函数里,调用CloudWatch的PutMetricData接口,发送自定义指标,比如维度设为CustomerId,指标值每次加1。示例代码片段:const AWS = require('aws-sdk'); const cloudwatch = new AWS.CloudWatch(); exports.handler = async (event) => { const request = event.Records[0].cf.request; const uriParts = request.uri.split('/'); const customerId = uriParts[2]; await cloudwatch.putMetricData({ Namespace: 'WidgetAccess', MetricData: [ { MetricName: 'RequestCount', Dimensions: [{ Name: 'CustomerId', Value: customerId }], Value: 1, Unit: 'Count' } ] }).promise(); return request; }; - 第二步:在CloudWatch查看指标
进入CloudWatch控制台,找到你创建的WidgetAccess命名空间,就能按客户ID查看实时的访问次数,还能设置告警(比如某个客户的访问量突增时提醒)。
迁移注意事项
原来的嵌入代码里的1x1像素请求可以直接去掉,改成让客户加载他们专属的JS/CSS文件——每次Widget加载时,浏览器会自动请求这些资源,CloudFront就会捕获到请求,进而被我们的统计方案记录下来,既简化了嵌入代码,又避免了额外的请求。
内容的提问来源于stack exchange,提问作者dang
相关产品推荐
相关产品推荐

