在nginx这一层,接收到访问请求的时候,就把请求的流量上报发送给kafka

storm才能去消费kafka中的实时的访问日志,然后去进行缓存热数据的统计

从lua脚本直接创建一个kafka producer,发送数据到kafka

wget https://github.com/doujiang24/lua-resty-kafka/archive/master.zip

yum install -y unzip

unzip lua-resty-kafka-master.zip

cp -rf /usr/local/lua-resty-kafka-master/lib/resty /usr/hello/lualib
nginx -s reload

  lua脚本:

local cjson = require("cjson")
local producer = require("resty.kafka.producer") local broker_list = {
{ host = "192.168.31.187", port = 9092 },
{ host = "192.168.31.19", port = 9092 },
{ host = "192.168.31.227", port = 9092 }
} local log_json = {}
log_json["headers"] = ngx.req.get_headers()
log_json["uri_args"] = ngx.req.get_uri_args()
log_json["body"] = ngx.req.read_body()
log_json["http_version"] = ngx.req.http_version()
log_json["method"] =ngx.req.get_method()
log_json["raw_reader"] = ngx.req.raw_header()
log_json["body_data"] = ngx.req.get_body_data() local message = cjson.encode(log_json); local productId = ngx.req.get_uri_args()["productId"] local async_producer = producer:new(broker_list, { producer_type = "async" })
local ok, err = async_producer:send("access-log", productId, message) if not ok then
ngx.log(ngx.ERR, "kafka send err:", err)
return
end

  

两台机器上都这样做,才能统一上报流量到kafka

bin/kafka-topics.sh --zookeeper 192.168.31.187:2181,192.168.31.19:2181,192.168.31.227:2181 --topic access-log --replication-factor 1 --partitions 1 --create

bin/kafka-console-consumer.sh --zookeeper 192.168.31.187:2181,192.168.31.19:2181,192.168.31.227:2181 --topic access-log --from-beginning

(1)kafka在187上的节点死掉了,可能是虚拟机的问题,杀掉进程,重新启动一下

nohup bin/kafka-server-start.sh config/server.properties &

(2)需要在nginx.conf中,http部分,加入resolver 8.8.8.8;

(3)需要在kafka中加入advertised.host.name = 192.168.31.187,重启三个kafka进程

(4)需要启动eshop-cache缓存服务,因为nginx中的本地缓存可能不在了

基于storm+kafka完成商品访问次数实时统计拓扑的开发:
总结思路:

1、kafka consumer spout

单独的线程消费,写入队列

nextTuple,每次都是判断队列有没有数据,有的话再去获取并发射出去,不能阻塞

2、日志解析bolt

3、商品访问次数统计bolt

4、基于LRUMap完成统计

import org.apache.storm.Config;
import org.apache.storm.LocalCluster;
import org.apache.storm.StormSubmitter;
import org.apache.storm.topology.TopologyBuilder;
import org.apache.storm.tuple.Fields;
import org.apache.storm.utils.Utils; import com.roncoo.eshop.storm.bolt.LogParseBolt;
import com.roncoo.eshop.storm.bolt.ProductCountBolt;
import com.roncoo.eshop.storm.spout.AccessLogKafkaSpout; /**
* 热数据统计拓扑
* @author Administrator
*
*/
public class HotProductTopology { public static void main(String[] args) {
TopologyBuilder builder = new TopologyBuilder(); builder.setSpout("AccessLogKafkaSpout", new AccessLogKafkaSpout(), 1);
builder.setBolt("LogParseBolt", new LogParseBolt(), 5)
.setNumTasks(5)
.shuffleGrouping("AccessLogKafkaSpout");
builder.setBolt("ProductCountBolt", new ProductCountBolt(), 5)
.setNumTasks(10)
.fieldsGrouping("LogParseBolt", new Fields("productId")); Config config = new Config(); if(args != null && args.length > 1) {
config.setNumWorkers(3);
try {
StormSubmitter.submitTopology(args[0], config, builder.createTopology());
} catch (Exception e) {
e.printStackTrace();
}
} else {
LocalCluster cluster = new LocalCluster();
cluster.submitTopology("HotProductTopology", config, builder.createTopology());
Utils.sleep(30000);
cluster.shutdown();
}
} }

  

import java.util.Map;

import org.apache.storm.task.OutputCollector;
import org.apache.storm.task.TopologyContext;
import org.apache.storm.topology.OutputFieldsDeclarer;
import org.apache.storm.topology.base.BaseRichBolt;
import org.apache.storm.tuple.Fields;
import org.apache.storm.tuple.Tuple;
import org.apache.storm.tuple.Values; import com.alibaba.fastjson.JSONObject; /**
* 日志解析的bolt
* @author Administrator
*
*/
public class LogParseBolt extends BaseRichBolt { private static final long serialVersionUID = -8017609899644290359L; private OutputCollector collector; @SuppressWarnings("rawtypes")
public void prepare(Map conf, TopologyContext context, OutputCollector collector) {
this.collector = collector;
} public void execute(Tuple tuple) {
String message = tuple.getStringByField("message");
JSONObject messageJSON = JSONObject.parseObject(message);
JSONObject uriArgsJSON = messageJSON.getJSONObject("uri_args");
Long productId = uriArgsJSON.getLong("productId"); if(productId != null) {
collector.emit(new Values(productId));
}
} public void declareOutputFields(OutputFieldsDeclarer declarer) {
declarer.declare(new Fields("productId"));
} }

  

import java.util.ArrayList;
import java.util.List;
import java.util.Map; import org.apache.storm.shade.org.json.simple.JSONArray;
import org.apache.storm.task.OutputCollector;
import org.apache.storm.task.TopologyContext;
import org.apache.storm.topology.OutputFieldsDeclarer;
import org.apache.storm.topology.base.BaseRichBolt;
import org.apache.storm.trident.util.LRUMap;
import org.apache.storm.tuple.Tuple;
import org.apache.storm.utils.Utils; import com.roncoo.eshop.storm.zk.ZooKeeperSession; /**
* 商品访问次数统计bolt
* @author Administrator
*
*/
public class ProductCountBolt extends BaseRichBolt { private static final long serialVersionUID = -8761807561458126413L; private LRUMap<Long, Long> productCountMap = new LRUMap<Long, Long>(1000);
private ZooKeeperSession zkSession;
private int taskid; @SuppressWarnings("rawtypes")
public void prepare(Map conf, TopologyContext context, OutputCollector collector) {
this.zkSession = ZooKeeperSession.getInstance();
this.taskid = context.getThisTaskId(); new Thread(new ProductCountThread()).start(); // 1、将自己的taskid写入一个zookeeper node中,形成taskid的列表
// 2、然后每次都将自己的热门商品列表,写入自己的taskid对应的zookeeper节点
// 3、然后这样的话,并行的预热程序才能从第一步中知道,有哪些taskid
// 4、然后并行预热程序根据每个taskid去获取一个锁,然后再从对应的znode中拿到热门商品列表
initTaskId(context.getThisTaskId());
} private void initTaskId(int taskid) {
// ProductCountBolt所有的task启动的时候, 都会将自己的taskid写到同一个node的值中
// 格式就是逗号分隔,拼接成一个列表
// 111,211,355 zkSession.acquireDistributedLock(); String taskidList = zkSession.getNodeData();
if(!"".equals(taskidList)) {
taskidList += "," + taskid;
} else {
taskidList += taskid;
} zkSession.setNodeData("/taskid-list", taskidList); zkSession.releaseDistributedLock();
} private class ProductCountThread implements Runnable { public void run() {
List<Map.Entry<Long, Long>> topnProductList = new ArrayList<Map.Entry<Long, Long>>(); while(true) {
topnProductList.clear(); int topn = 3; if(productCountMap.size() == 0) {
Utils.sleep(100);
continue;
} for(Map.Entry<Long, Long> productCountEntry : productCountMap.entrySet()) {
if(topnProductList.size() == 0) {
topnProductList.add(productCountEntry);
} else {
// 比较大小,生成最热topn的算法有很多种
// 但是我这里为了简化起见,不想引入过多的数据结构和算法的的东西
// 很有可能还是会有漏洞,但是我已经反复推演了一下了,而且也画图分析过这个算法的运行流程了
boolean bigger = false; for(int i = 0; i < topnProductList.size(); i++){
Map.Entry<Long, Long> topnProductCountEntry = topnProductList.get(i); if(productCountEntry.getValue() > topnProductCountEntry.getValue()) {
int lastIndex = topnProductList.size() < topn ? topnProductList.size() - 1 : topn - 2;
for(int j = lastIndex; j >= i; j--) {
topnProductList.set(j + 1, topnProductList.get(j));
}
topnProductList.set(i, productCountEntry);
bigger = true;
break;
}
} if(!bigger) {
if(topnProductList.size() < topn) {
topnProductList.add(productCountEntry);
}
}
}
} // 获取到一个topn list
String topnProductListJSON = JSONArray.toJSONString(topnProductList);
zkSession.setNodeData("/task-hot-product-list-" + taskid, topnProductListJSON); Utils.sleep(5000);
}
} } public void execute(Tuple tuple) {
Long productId = tuple.getLongByField("productId"); Long count = productCountMap.get(productId);
if(count == null) {
count = 0L;
}
count++; productCountMap.put(productId, count);
} public void declareOutputFields(OutputFieldsDeclarer declarer) { } }

  

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ArrayBlockingQueue; import kafka.consumer.Consumer;
import kafka.consumer.ConsumerConfig;
import kafka.consumer.ConsumerIterator;
import kafka.consumer.KafkaStream;
import kafka.javaapi.consumer.ConsumerConnector; import org.apache.storm.spout.SpoutOutputCollector;
import org.apache.storm.task.TopologyContext;
import org.apache.storm.topology.OutputFieldsDeclarer;
import org.apache.storm.topology.base.BaseRichSpout;
import org.apache.storm.tuple.Fields;
import org.apache.storm.tuple.Values;
import org.apache.storm.utils.Utils; /**
* kafka消费数据的spout
*/
public class AccessLogKafkaSpout extends BaseRichSpout { private static final long serialVersionUID = 8698470299234327074L; private ArrayBlockingQueue<String> queue = new ArrayBlockingQueue<String>(1000); private SpoutOutputCollector collector; @SuppressWarnings("rawtypes")
public void open(Map conf, TopologyContext context,
SpoutOutputCollector collector) {
this.collector = collector;
startKafkaConsumer();
} @SuppressWarnings("rawtypes")
private void startKafkaConsumer() {
Properties props = new Properties();
props.put("zookeeper.connect", "192.168.31.187:2181,192.168.31.19:2181,192.168.31.227:2181");
props.put("group.id", "eshop-cache-group");
props.put("zookeeper.session.timeout.ms", "40000");
props.put("zookeeper.sync.time.ms", "200");
props.put("auto.commit.interval.ms", "1000");
ConsumerConfig consumerConfig = new ConsumerConfig(props); ConsumerConnector consumerConnector = Consumer.
createJavaConsumerConnector(consumerConfig);
String topic = "access-log"; Map<String, Integer> topicCountMap = new HashMap<String, Integer>();
topicCountMap.put(topic, 1); Map<String, List<KafkaStream<byte[], byte[]>>> consumerMap =
consumerConnector.createMessageStreams(topicCountMap);
List<KafkaStream<byte[], byte[]>> streams = consumerMap.get(topic); for (KafkaStream stream : streams) {
new Thread(new KafkaMessageProcessor(stream)).start();
}
} private class KafkaMessageProcessor implements Runnable { @SuppressWarnings("rawtypes")
private KafkaStream kafkaStream; @SuppressWarnings("rawtypes")
public KafkaMessageProcessor(KafkaStream kafkaStream) {
this.kafkaStream = kafkaStream;
} @SuppressWarnings("unchecked")
public void run() {
ConsumerIterator<byte[], byte[]> it = kafkaStream.iterator();
while (it.hasNext()) {
String message = new String(it.next().message());
try {
queue.put(message);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} } public void nextTuple() {
if(queue.size() > 0) {
try {
String message = queue.take();
collector.emit(new Values(message));
} catch (Exception e) {
e.printStackTrace();
}
} else {
Utils.sleep(100);
}
} public void declareOutputFields(OutputFieldsDeclarer declarer) {
declarer.declare(new Fields("message"));
} }

  

import java.util.concurrent.CountDownLatch;

import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.Watcher.Event.KeeperState;
import org.apache.zookeeper.ZooDefs.Ids;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.data.Stat; /**
* ZooKeeperSession
* @author Administrator
*
*/
public class ZooKeeperSession { private static CountDownLatch connectedSemaphore = new CountDownLatch(1); private ZooKeeper zookeeper; public ZooKeeperSession() {
// 去连接zookeeper server,创建会话的时候,是异步去进行的
// 所以要给一个监听器,说告诉我们什么时候才是真正完成了跟zk server的连接
try {
this.zookeeper = new ZooKeeper(
"192.168.31.187:2181,192.168.31.19:2181,192.168.31.227:2181",
50000,
new ZooKeeperWatcher());
// 给一个状态CONNECTING,连接中
System.out.println(zookeeper.getState()); try {
// CountDownLatch
// java多线程并发同步的一个工具类
// 会传递进去一些数字,比如说1,2 ,3 都可以
// 然后await(),如果数字不是0,那么久卡住,等待 // 其他的线程可以调用coutnDown(),减1
// 如果数字减到0,那么之前所有在await的线程,都会逃出阻塞的状态
// 继续向下运行 connectedSemaphore.await();
} catch(InterruptedException e) {
e.printStackTrace();
} System.out.println("ZooKeeper session established......");
} catch (Exception e) {
e.printStackTrace();
}
} /**
* 获取分布式锁
* @param productId
*/
public void acquireDistributedLock() {
String path = "/taskid-list-lock"; try {
zookeeper.create(path, "".getBytes(),
Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
System.out.println("success to acquire lock for taskid-list-lock");
} catch (Exception e) {
// 如果那个商品对应的锁的node,已经存在了,就是已经被别人加锁了,那么就这里就会报错
// NodeExistsException
int count = 0;
while(true) {
try {
Thread.sleep(1000);
zookeeper.create(path, "".getBytes(),
Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
} catch (Exception e2) {
count++;
System.out.println("the " + count + " times try to acquire lock for taskid-list-lock......");
continue;
}
System.out.println("success to acquire lock for taskid-list-lock after " + count + " times try......");
break;
}
}
} /**
* 释放掉一个分布式锁
* @param productId
*/
public void releaseDistributedLock() {
String path = "/taskid-list-lock";
try {
zookeeper.delete(path, -1);
System.out.println("release the lock for taskid-list-lock......");
} catch (Exception e) {
e.printStackTrace();
}
} public String getNodeData() {
try {
return new String(zookeeper.getData("/taskid-list", false, new Stat()));
} catch (Exception e) {
e.printStackTrace();
}
return "";
} public void setNodeData(String path, String data) {
try {
zookeeper.setData(path, data.getBytes(), -1);
} catch (Exception e) {
e.printStackTrace();
}
} /**
* 建立zk session的watcher
* @author Administrator
*
*/
private class ZooKeeperWatcher implements Watcher { public void process(WatchedEvent event) {
System.out.println("Receive watched event: " + event.getState());
if(KeeperState.SyncConnected == event.getState()) {
connectedSemaphore.countDown();
}
} } /**
* 封装单例的静态内部类
* @author Administrator
*
*/
private static class Singleton { private static ZooKeeperSession instance; static {
instance = new ZooKeeperSession();
} public static ZooKeeperSession getInstance() {
return instance;
} } /**
* 获取单例
* @return
*/
public static ZooKeeperSession getInstance() {
return Singleton.getInstance();
} /**
* 初始化单例的便捷方法
*/
public static void init() {
getInstance();
} }

  于双重zookeeper分布式锁完成分布式并行缓存预热:

1、服务启动的时候,进行缓存预热

2、从zk中读取taskid列表

3、依次遍历每个taskid,尝试获取分布式锁,如果获取不到,快速报错,不要等待,因为说明已经有其他服务实例在预热了

4、直接尝试获取下一个taskid的分布式锁

5、即使获取到了分布式锁,也要检查一下这个taskid的预热状态,如果已经被预热过了,就不再预热了

6、执行预热操作,遍历productid列表,查询数据,然后写ehcache和redis

7、预热完成后,设置taskid对应的预热状态

ZKsession重载两个方法:

/**
* 获取分布式锁
* @param productId
*/
public boolean acquireFastFailedDistributedLock(String path) {
try {
zookeeper.create(path, "".getBytes(),
Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
System.out.println("success to acquire lock for " + path);
return true;
} catch (Exception e) {
System.out.println("fail to acquire lock for " + path);
}
return false;
} /**
* 释放掉一个分布式锁
* @param productId
*/
public void releaseDistributedLock(String path) {
try {
zookeeper.delete(path, -1);
System.out.println("release the lock for " + path + "......");
} catch (Exception e) {
e.printStackTrace();
}
}
public String getNodeData(String path) {
try {
return new String(zookeeper.getData(path, false, new Stat()));
} catch (Exception e) {
e.printStackTrace();
}
return "";
} public void setNodeData(String path, String data) {
try {
zookeeper.setData(path, data.getBytes(), -1);
} catch (Exception e) {
e.printStackTrace();
}
}

  

/**
* 获取分布式锁
*/
public void acquireDistributedLock(String path) {
try {
zookeeper.create(path, "".getBytes(),
Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
System.out.println("success to acquire lock for " + path);
} catch (Exception e) {
// 如果那个商品对应的锁的node,已经存在了,就是已经被别人加锁了,那么就这里就会报错
// NodeExistsException
int count = 0;
while(true) {
try {
Thread.sleep(1000);
zookeeper.create(path, "".getBytes(),
Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
} catch (Exception e2) {
count++;
System.out.println("the " + count + " times try to acquire lock for " + path + "......");
continue;
}
System.out.println("success to acquire lock for " + path + " after " + count + " times try......");
break;
}
}
}

  

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.roncoo.eshop.cache.model.ProductInfo;
import com.roncoo.eshop.cache.service.CacheService;
import com.roncoo.eshop.cache.spring.SpringContext;
import com.roncoo.eshop.cache.zk.ZooKeeperSession; /**
* 缓存预热线程
*/
public class CachePrewarmThread extends Thread { @Override
public void run() {
CacheService cacheService = (CacheService) SpringContext.
getApplicationContext().getBean("cacheService");
ZooKeeperSession zkSession = ZooKeeperSession.getInstance(); // 获取storm taskid列表
String taskidList = zkSession.getNodeData("/taskid-list"); if(taskidList != null && !"".equals(taskidList)) {
String[] taskidListSplited = taskidList.split(",");
for(String taskid : taskidListSplited) {
String taskidLockPath = "/taskid-lock-" + taskid; boolean result = zkSession.acquireFastFailedDistributedLock(taskidLockPath);
if(!result) {
continue;
} String taskidStatusLockPath = "/taskid-status-lock-" + taskid;
zkSession.acquireDistributedLock(taskidStatusLockPath);
//检查越热的状态
String taskidStatus = zkSession.getNodeData("/taskid-status-" + taskid); if("".equals(taskidStatus)) {
String productidList = zkSession.getNodeData("/task-hot-product-list-" + taskid);
JSONArray productidJSONArray = JSONArray.parseArray(productidList); for(int i = 0; i < productidJSONArray.size(); i++) {
Long productId = productidJSONArray.getLong(i);
String productInfoJSON = "{\"id\": " + productId + ", \"name\": \"iphone7手机\", \"price\": 5599, \"pictureList\":\"a.jpg,b.jpg\", \"specification\": \"iphone7的规格\", \"service\": \"iphone7的售后服务\", \"color\": \"红色,白色,黑色\", \"size\": \"5.5\", \"shopId\": 1, \"modifiedTime\": \"2017-01-01 12:00:00\"}";
ProductInfo productInfo = JSONObject.parseObject(productInfoJSON, ProductInfo.class);
cacheService.saveProductInfo2LocalCache(productInfo);
cacheService.saveProductInfo2ReidsCache(productInfo);
} zkSession.setNodeData(taskidStatusLockPath, "success");
} zkSession.releaseDistributedLock(taskidStatusLockPath); zkSession.releaseDistributedLock(taskidLockPath);
}
}
} }

  

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.roncoo.eshop.cache.model.ProductInfo;
import com.roncoo.eshop.cache.service.CacheService;
import com.roncoo.eshop.cache.spring.SpringContext;
import com.roncoo.eshop.cache.zk.ZooKeeperSession; /**
* 缓存预热线程
*/
public class CachePrewarmThread extends Thread { @Override
public void run() {
CacheService cacheService = (CacheService) SpringContext.
getApplicationContext().getBean("cacheService");
ZooKeeperSession zkSession = ZooKeeperSession.getInstance(); // 获取storm taskid列表
String taskidList = zkSession.getNodeData("/taskid-list"); if(taskidList != null && !"".equals(taskidList)) {
String[] taskidListSplited = taskidList.split(",");
for(String taskid : taskidListSplited) {
String taskidLockPath = "/taskid-lock-" + taskid; boolean result = zkSession.acquireFastFailedDistributedLock(taskidLockPath);
if(!result) {
continue;
} String taskidStatusLockPath = "/taskid-status-lock-" + taskid;
zkSession.acquireDistributedLock(taskidStatusLockPath);
//检查越热的状态
String taskidStatus = zkSession.getNodeData("/taskid-status-" + taskid); if("".equals(taskidStatus)) {
String productidList = zkSession.getNodeData("/task-hot-product-list-" + taskid);
JSONArray productidJSONArray = JSONArray.parseArray(productidList); for(int i = 0; i < productidJSONArray.size(); i++) {
Long productId = productidJSONArray.getLong(i);
String productInfoJSON = "{\"id\": " + productId + ", \"name\": \"iphone7手机\", \"price\": 5599, \"pictureList\":\"a.jpg,b.jpg\", \"specification\": \"iphone7的规格\", \"service\": \"iphone7的售后服务\", \"color\": \"红色,白色,黑色\", \"size\": \"5.5\", \"shopId\": 1, \"modifiedTime\": \"2017-01-01 12:00:00\"}";
ProductInfo productInfo = JSONObject.parseObject(productInfoJSON, ProductInfo.class);
cacheService.saveProductInfo2LocalCache(productInfo);
cacheService.saveProductInfo2ReidsCache(productInfo);
} zkSession.setNodeData(taskidStatusLockPath, "success");
} zkSession.releaseDistributedLock(taskidStatusLockPath); zkSession.releaseDistributedLock(taskidLockPath);
}
}
} }

  

nginx+lua访问流量实时上报kafka的更多相关文章

  1. Nginx + LUA下流量拦截算法

    前言 每逢大促必压测,每逢大促必限流,这估计是电商人的常态.每次大促期间,业务流量是平时的几倍十几倍,大促期间大部分业务都会集中在购物车结算,必须限流,才能保证系统不宕机. 限流算法 限流算法一般有三 ...

  2. 简单版nginx lua 完成流量上报于中间件

    本文链接:https://www.cnblogs.com/zhenghongxin/p/9131226.html 公司某些业务下,需要将请求的流量上报于中间件(kafka,rabbitMq等),让st ...

  3. CentOS6.9安装Filebeat监控Nginx的访问日志发送到Kafka

    一.下载地址: 官方:https://www.elastic.co/cn/downloads/beats/filebeat 百度云盘:https://pan.baidu.com/s/1dvhqb0 二 ...

  4. #研发解决方案#基于Apriori算法的Nginx+Lua+ELK异常流量拦截方案

    郑昀 基于杨海波的设计文档 创建于2015/8/13 最后更新于2015/8/25 关键词:异常流量.rate limiting.Nginx.Apriori.频繁项集.先验算法.Lua.ELK 本文档 ...

  5. 基于Apriori算法的Nginx+Lua+ELK异常流量拦截方案 郑昀 基于杨海波的设计文档(转)

    郑昀 基于杨海波的设计文档 创建于2015/8/13 最后更新于2015/8/25 关键词:异常流量.rate limiting.Nginx.Apriori.频繁项集.先验算法.Lua.ELK 本文档 ...

  6. 【原创】运维基础之OpenResty(Nginx+Lua)+Kafka

    使用docker部署 1 下载 # wget https://github.com/doujiang24/lua-resty-kafka/archive/v0.06.tar.gz# tar xvf v ...

  7. nginx lua集成kafka

    NGINX lua集成kafka 第一步:进入opresty目录 [root@node03 openresty]# cd /export/servers/openresty/ [root@node03 ...

  8. flink---实时项目--day01--1. openrestry的安装 2. 使用nginx+lua将日志数据写入指定文件中 3. 使用flume将本地磁盘中的日志数据采集到的kafka中去

    1. openrestry的安装 OpenResty = Nginx + Lua,是⼀一个增强的Nginx,可以编写lua脚本实现⾮非常灵活的逻辑 (1)安装开发库依赖 yum install -y ...

  9. 利用ngxtop实时监控nginx的访问情况

    关于对nginx web server的实时访问的实时监控问题,我很久之前就想实现的,现在虽有nginx自带的status扩展,但那是全局的,无法细分到vhost,并且提供的metric也很少,加之目 ...

随机推荐

  1. planning algorithms chapter 3

    chapter 3 几何表示和变换 P.S: 总算到了 motion planning 部分了 几何建模 几何建模主要有两类方法:边界表示法和实体表示法. 环境模型可以是二维或三维,实体主要包括障碍物 ...

  2. SpringBoot + CXF快速实现SOAP WebService(支持Basic Auth)

    唠叨两句 讲真,SOAP跟现在流行的RESTful WebService比起来显得很难用.冗余的XML文本信息太多,可读性差,它的请求信息有时很难手动构造,不太好调试.不过说归说,对某些企业用户来说S ...

  3. java复制对象之深拷背

    在java开发中,有时我们需要复制对象,并且确保修改复制得到的对象不会影响原来的对象. 于是,有些人可能会写出类似以下的代码: public class CloneTest { public stat ...

  4. 数据库与spring事务传播特性

    一.spring事务管理的实现原理,基于AOP 1) REQUIRED ,这个是默认的属性 Support a current transaction, create a new one if non ...

  5. [Beta]Scrum Meeting#10

    github 本次会议项目由PM召开,时间为5月15日晚上10点30分 时长15分钟 任务表格 人员 昨日工作 下一步工作 木鬼 撰写博客整理文档 撰写博客整理文档 swoip 为适应新功能调整布局前 ...

  6. 范仁义html+css课程---11、html补充知识

    范仁义html+css课程---11.html补充知识 一.总结 一句话总结: 小于号(<):< 大于号(>):> 空格:  二.html 字符实体 1.小于号(<)和大 ...

  7. RSA加密公钥系数获取结果多00

    写在前面 本文是在解决加密和解密用的不是同一套密钥对时找到的一篇, 最后问题不在byte数组, 是自己工具类中生成密钥对的问题, 但是本文RSA加密中公钥指数和公钥系数的获取(byte[]部分)讲解比 ...

  8. C++ list运用实例

    C++ list运用实例 #include <list> #include <iostream> #include <algorithm> #include < ...

  9. Vue基础知识学习笔记

    一.环境搭建1.安装nodejs ((https://nodejs.org/en/)2.安装脚手架 npm install --global vue-cli /cnmp install --globa ...

  10. LeetCode 108. Convert Sorted Array to Binary Search Tree (将有序数组转换成BST)

    108. Convert Sorted Array to Binary Search Tree Given an array where elements are sorted in ascendin ...