CDN 日志实时分析综述
CDN将源站资源缓存至遍布全球的加速节点上,当终端用户请求获取该资源时,无需回源,系统自动调用离终端用户最近的CDN节点上已缓存的资源,那么如何进行实时日志分析呢?
架构
CDN日志的解析一般有一个通用的架构模式,就是首先要将各个边缘节点的日志数据进行采集,一般会采集到消息队列,然后将消息队列和实时计算集群进行集成进行实时的日志分析,最后将分析的结果写到存储系统里面。那么我今天的案例将架构实例化,消息队列采用Kafka,实时计算采用Flink,最终将数据存储到MySql中。如下图所示:
需求说明
阿里云实际的CDN日志数据结构如下(可能会不断丰富字段信息):
为了介绍方便,我们将实际的统计需求进行简化,示例将从CDN访问日志中,根据IP解析出其所属的地区,统计指标:
按地区统计资源访问量
按地区统计资源下载总量
按地区统计资源平均下载速度
DN实时日志分析UDF定义
这里我们需要定义一个 ip_to_province()的UDF,输入是ip地址,输出是地区名字字符串。UDF的输入类型是一个字符串,输出类型也是一个字符串。同时我们会用到地理区域查询服务
(http://whois.pconline.com.cn/ipJson.jsp?ip=27.184.139.25),大家在自己的生产环境要替换为可靠的地域查询服务。
import re
import json
from pyflink.table import DataTypes
from pyflink.table.udf import udf
from urllib.parse import quote_plus
from urllib.request import urlopen
@udf(input_types=[DataTypes.STRING()], result_type=DataTypes.STRING())
def ip_to_province(ip):
"""
format:
{
'ip': '27.184.139.25',
'pro': '河北省',
'proCode': '130000',
'city': '石家庄市',
'cityCode': '130100',
'region': '灵寿县',
'regionCode': '130126',
'addr': '河北省石家庄市灵寿县 电信',
'regionNames': '',
'err': ''
}
"""
try:
urlobj = urlopen( \
'http://whois.pconline.com.cn/ipJson.jsp?ip=%s' % quote_plus(ip))
data = str(urlobj.read(), "gbk")
pos = re.search("{[^{}]+\}", data).span()
geo_data = json.loads(data[pos[0]:pos[1]])
if geo_data['pro']:
return geo_data['pro']
else:
return geo_data['err']
except:
return "UnKnow"
数据读取和结果写入定义
按照通用的作业结构,需要定义Source connector来读取Kafka数据,定义Sink connector来将计算结果存储到MySQL。最后是编写统计逻辑。在这特别说明一下,在PyFlink中也支持SQL DDL的编写,我们用一个简单的DDL描述,就完成了Source Connector的开发。其中connector.type填写kafka。SinkConnector也一样,用一行DDL描述即可,其中connector.type填写jdbc。
1. Kafka 数据源读取DDL定义
数据统计需求我们只选取核心的字段,比如:uuid,表示唯一的日志标示,client_ip表示访问来源,request_time表示资源下载耗时,response_size表示资源数据大小。Kafka数据字段进行简化如下:
DDL定义如下:
kafka_source_ddl = """
CREATE TABLE cdn_a