百万QPS下热点数据的收集方案
在高并发场景下,如京东、淘宝的秒杀活动开始时候,会有很多的用户同时抢购秒杀商品,由于同一个场次成百上千种商品参与秒杀活动,但是热点的商品往往就只有那么几十个左右,此时系统的90%的流量都是来自于这几十个热点商品,极端情况下因为这几十个热度商品导致服务器宕机,因此针对热点商品需要做一些应对的措施。常见的应对措施有缓存热点商品数据、热点数据和非热点数据做隔离等等。
如何在高并发下识别热点商品数据呢?下面我们将通过OpenResty+Lua+Kafka+ES方案实现热点数据收集的方案。
1、方案的实现流程
(1)当用户访问(如http://www.longxia.com/web/item/index.html)的时候,请求进入到OpenResty中。
(2)OpenResty中的Nginx上location拦截到请求,它会做去掉请求地址上的特定部分(如/web/item/index.html —-> /item/index.html),然后访问真实的服务获取数据。
(3)Lua组装用户访问的数据(如商品信息)发送消息到Kafka中,Kafka随后将数据推送到Logstash中,Logstash会把数据推送到ES中存储起来。
2、核心的实现过程
(1)配置lua-resty-kafka
地址:https://github.com/doujiang24/lua-resty-kafka
插件配置到Nginx模块上
(2)编写lua脚本
--依赖导入
local cjson = require "cjson"
local client = require "resty.kafka.client"
local producer = require "resty.kafka.producer"
--配置kafka的服务地址
local broker_list = {
{ host = "192.168.203.237",port = 9092}
}
--创建kafka的生产者
local bp = producer:new(broker_list, { producer_type = "async" })
--先获取用户的请求头 然后获取IP的信息
local headers=ngx.req.get_headers()
local ip=headers["X-REAL_IP"] or headers["X_FORWARDED_FCR"] or ngx.var.remote_addr or "0.0.0.0"
--创建消息
local message={}
message["uri"]=ngx.var.uri
message["ip"]=ip
message["token"]="987654"
message["actime"]=os.date("%y-%M-%d %H:%m:%S")
--发送消息
local ok, err = bp:send("collection_hot_item",nil, cjson.encode(message))
--把请求中的/web去掉
local uri = ngx.var.uri
uri = string.gsub(uri,"/web","")
--将去掉的路径再次执行转发查找静态页
ngx.exec(uri)
(3)页面的请求被Nginx拦截的配置
#拦截/web/item的请求 然后交给lua文件处理
location /web/item/ {
content_by_lua_file /usr/local/openresty/nginx/lua/item-access.lua;
}
location /item/ {
root /usr/local/web;
}
(4)kafka消息推送到Logstash
input {
kafka {
bootstrap_servers => "192.168.203.237:9092" # Kafka 服务器地址和端口
topics => ["collection_hot_item"] # 需要消费的 Kafka 话题
group_id => "logstash_group" # Kafka 消费者组ID
consumer_threads => 3 # 消费者线程数
codec =>json
}
}
filter {
}
output {
#数据推送到es
elasticsearch {
hosts => ["http://192.168.203.238:9200"]
index => "hot_item"
}
}
总结:运营人员通过Kibana可以查询到热点商品数据,定位到热点的商品数据后可以有针对性地做一些应对措施。本文是通过ES存储热点数据,也可以使用Druid来实现,Druid有更好的数据处理分析能力。