在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. Nginx服务器作反向代理实现内部局域网的url转发配置

    情景 由于公司内网有多台服务器的http服务要映射到公司外网静态IP,如果用路由的端口映射来做,就只能一台内网服务器的80端口映射到外网80端口,其他服务器的80端口只能映射到外网的非80端口.非80 ...

  2. 区间DP复习

    区间DP复习 (难度排序:(A,B),(F,G,E,D,H,I,K),(C),(J,L)) 这是一个基本全在bzoj上的复习专题 没有什么可以说的,都是一些基本的dp思想 A [BZOJ1996] [ ...

  3. 东芝300D粉盒清零

    东芝300D粉盒清零 1:打开前盖 2:按"OK"键3秒,等 显示 "更换硒鼓"(注:不用选 是/否,直接进入第3步) 3:按"启用"键 4 ...

  4. 设计模式 桥梁模式 JDBC

    桥梁模式是对象的结构模式.又称为柄体(Handle and Body)模式或接口(Interface)模式.桥梁模式的用意是“将抽象化(Abstraction)与实现化(Implementation) ...

  5. FZU Monthly-201905 tutorial

    FZU Monthly-201905 tutorial 题目(难度递增) easy easy-medium medium medium-hard hard 思维难度 AB H DG CE F A. C ...

  6. Future home of something quite cool.

    我绑定二级域名的时候显示内页如下,怎么办??一级主域名没问题呀~ Future home of something quite cool.If you're the site owner, log i ...

  7. Java的面向对象的原则

    1.单一职责原则: /* * (有且只有一个引起功能变化的原因) * 如果在一个类中,承载的功能越多. * 交融的耦合性越高,被复用的可能性越低. * 耦合性高的话,当一个类的职责发生变化的时候,会引 ...

  8. linux安装redis时报collect2: fatal error: cannot find 'ld'和In file included from adlist.c:34:0:

    如题,看了下该ld命令所在文件: [root@centos redis-]# whereis ld ld: /usr/bin/ld.gold /usr/bin/ld /usr/bin/ld.bfd / ...

  9. 深入浅出依赖注入容器——Autofac

    1.写在前面 相信大家对IOC和DI都耳熟能详,它们在项目里面带来的便利大家也都知道,微软新出的.NetCore也大量采用了这种手法. 如今.NetCore也是大势所趋了,基本上以.Net为技术主导的 ...

  10. CentOS 7上重新编译安装nginx

    CentOS 7的源所提供的nginx几乎不包含任何扩展模块:为了能够使用一些扩展模块,我们需要从源代码重新编译安装nginx. 目前最新版的源代码是1.6.1.下载解压后先不要急着configure ...