hexo icarus、golang、google analytics自行实现访问量统计(一)
前言
此前摸索了一波Icarus的jsx模板,也了解了golang如何使用google analytics reporting api。现在打算结合起来自行实现访问量的统计,特此记录一下折腾的过程。
目前是打算用golang实现一个轻量的服务,服务启动时会拉取analytics的统计数据,并缓存在内存中,可以根据pathname获取访问量数据。数据更新的话,打算维护两个变量,定时扫描最新访问时间与最新数据更新时间,当新访问时间大于最新数据更新时间,且大于一个时间间隔更新,或着在这种情况下距离当前时间太远更新。
前端的话,只需要在页面加载完成后请求后端,并将获取到的值通过dom操作更新页面。
后端coding
缓存结构
首先定义了内存缓存结构体,PvMap是以页面path为key pv为value的map,到时候具体页面的访问量查询就是靠他了,TotalUv与TotalPv就是字面意思了。因为是运行在64位机上,所以int也够用了。
1 | type Data struct { |
获取数据并写入缓存
由于请求的内容是固定的,所以我把GetReportsRequest在服务启动时就生成了,此外更新操作是单线程的复用一个ReportsService也够了。
请求数据的时候如果发生错误,忽略即可,毕竟访问量并不是啥重要的数据。
我构造的GetReportsRequest的第一个度量是ga:newUsers、第二个是ga:pageViews,所以我就直接这样硬编码获取数据了。具体的返回内容在上上一篇博文中有提到,并且序列化地打印了出来,可以参考一下。
构造完缓存数据后,指针直接指向新缓存,并刷新更新时间。即使在并发的情况下取到旧的缓存,golang的gc也不会销毁还有引用的对象,因此这样也不用加锁,还是前面那句话,访问量并不是啥重要的数据。
1 | func (s *analyticsReportService) getReports() { |
定时更新缓存
这就是根据维护的两个时间变量调用上面的函数了,tick时间略小于更新时间。
1 | func (s *analyticsReportService) start() { |
构建http服务
由于golang自带了http服务,这里直接用原生的就够用了。
实现handler,当path为/时,返回的是total的数值。浏览器window.location.pathname获取到的值是urlencode过的,不确定不同的环境下浏览器decode会不会有什么神奇的bug,所以decode就放在后端做了。
每次访问过后,顺带更新一下访问时间。
1 | func Handler(w http.ResponseWriter, r *http.Request) { |
postman测试后端
测试根路径可以看到返回了总pv与uv。
具体的文章路径返回了pv,目前没做具体页面的uv信息。
内存占用
可以看到本服务在加载了内存缓存后,内存占用也只有个位数,非常轻量。
小结
目前实现了访问量统计的后端部分,数据全部缓存在内存中,实现上无锁,响应快速。
间歇更新也不会超出analytics reporting api一天5万次的请求上限与10qps/ip。
从wordpress迁移到hexo后,本人的主机上就不运行php cgi了,相比node.js或者php需要单独的运行环境,个位数的内存占用也对主机非常友好。
hexo icarus、golang、google analytics自行实现访问量统计(一)
https://www.huihongcloud.com/2021/10/04/go/hexo icarus、golang、google analytics自行实现访问量统计(一)/