D21 flume/kafka/storm/redis综合

来源:互联网 发布:visual studio php 编辑:程序博客网 时间:2024/05/02 04:23
需求:
①日志生成:采集订单系统应用打印的日志文件日志文件使用log4j生成,滚动生成
     
处理流程:
1、Spout获取外部数据源,数据源是订单的mq,mq有固定的格式,比如json串。
2、对订单mq进行解析,得到一个对象->JavaBean
订单编号、订单时间、支付编号、支付时间、商品编号、商家名称、商品价格、优惠价格、支付金额
3、对指标进行计数
//业务中一个订单包含多个商品,需要对每个商品进行指标计算
//创建订单和取消订单两种类型,在计算总数据的是考虑将取消订单的金额减掉
//订单中有拆单的逻辑,该如何计算
4、保存指标数据到Redis

sz file.type  将文件下载到本地磁盘c盘。


日志监控:
需求分析:①用flume监控日志文件;②用Kafka读取日志数据;③storm数据处理后输出到redis;④redis存储数据查看!

实现流程:
(一)实现flume监控log文件夹下的text.log文件
实现flume的exec.conf脚本如下:
  1. # Name the components on this agent
  2. a1.sources = r1
  3. a1.sinks = k1
  4. a1.channels = c1
  5. a1.sources.r1.type = exec
  6. a1.sources.r1.command = tail -F /home/hadoop/log/1.log        #指定了监控的日志文件
  7. a1.sources.r1.channels = c1
  8. # Describe the sink
  9. #下沉目标
  10. a1.sinks.k1.type =org.apache.flume.sink.kafka.KafkaSink                       #指定了下沉目标是Kafka
  11. a1.sinks.k1.topic=bbb #指定了flume输入到Kafka的数据的topic
  12. a1.sinks.k1.brokerList=server:9092
  13. a1.sinks.k1.requiredAcks=1
  14. a1.sinks.k1.batchSize=20
  15. a1.sinks.k1.channel = c1
  16. # Use a channel which buffers events in memory
  17. a1.channels.c1.type = memory
  18. a1.channels.c1.capacity = 10000
  19. a1.channels.c1.transactionCapacity = 100

保存后执行: ./bin/flume-ng agent -n a1 -c conf -f conf/myconf/exec.conf -Dflume.root.logger=INFO,console           
即完成对指定日志文件的监控!!
备注:对于Kafka来说,flume就是数据的producer,对Kafka一直生产数据

(二)Kafka消费数据
①启动Kafka消费命令之前,先在每台机器上启动zookeeper
执行:zkServer.sh start      然后用zkServer.sh status来查看状态
②在三台机器上启动Kafka服务:nohup bin/kafka-server-start.sh config/server.properties &
③在主机的客户端执行消费的console命令:bin/kafka-console-consumer.sh --zookeeper server:2181--topic bbb          #即在客户端看到添加的数据。

总体数据的流向: 日志文件--> source --flume_channel -- sink -->Kafka的consumer-->KafkaSpout--storm-->Bolt---->redis

<测试好以上两步,接下来需要写的是storm的逻辑代码:Spout采用KafkaSpout实例,Bolt的executor()方法将数据输出测试,或其他逻辑>

(三)storm处理数据
编写好代码后
首先启动storm,(zookeeper已经启动)
server: nohup ./storm nimbus &
三台机器上server,server02,server03执行:nohup ./storm supervisor &
server:执行nohup ./storm ui &

接下来完成storm端的处理:可以本地运行,也可以打包集群运行。
备注:此处的打包是maven打包,打包方法:maven工程的pom.xml右击选择maven install才是在target里打包!
集群运行模式:上传该依赖包到服务器。执行storm jar test.jar pacakge.class
注意:provided调整,集群运行模式调整
至此storm启动完成,数据由Kafka的consumer--输入到Spout--Bolt处理


(四)数据输出到redis数据库

视频中测试的内容是:
①编写了Kafka的producer程序,即将订单数据远远不断的生产,发送到消费者。(并且例子中用消费者控制台也观察到数据的写入)
  1. public class OrderMqSender {
  2. public static void main(String[] args) {
  3. String TOPIC = "ccc";
  4.  
  5. Properties props = new Properties();
  6. props.put("serializer.class", "kafka.serializer.StringEncoder");
  7. props.put("metadata.broker.list", "server:9092,server02:9092,server03:9092"); //配置Kafka的集群, 端口:9092
  8. props.put("request.required.acks", "1");
  9. props.put("partitioner.class", "kafka.producer.DefaultPartitioner");
  1. //配置好集群,创建一个producer向Kafka写入数据
  2. Producer<String, String> producer = new Producer<String, String>(new ProducerConfig(props));
  3. for (int messageNo = 1; messageNo < 100000; messageNo++) {
  4. producer.send(new KeyedMessage<String, String>(TOPIC, messageNo + "",new OrderInfo().random() ));
  5. try {
  6. Thread.sleep(100);
  7. } catch (InterruptedException e) {
  8. e.printStackTrace();
  9. }
  10. }
  11. }
  12. }
②消费者:没用到,主要是在客户端启动来查看是否已经写入数据
  1. bin/kafka-console-consumer.sh --zookeeper server:2181 --topic ccc
③storm中编写spout,用KafkaSpout实例,即将Kafka的consumer作为输入的数据源来读取。所有的集群topic信息都已经在KafkaSpout中配置好
  1. public class KafkaAndStormTopologyMain {
  2. public static void main(String[] args) throws Exception{
  3.  //和普通storm程序设置相同,只是spout源改掉,改为KafkaSpout
  4. TopologyBuilder topologyBuilder = new TopologyBuilder();
  5. topologyBuilder.setSpout("kafkaSpout",new KafkaSpout(new SpoutConfig(
  6. new ZkHosts("server:2181,server02:2181,server03:2181"),
  7. "ccc", "/myKafka", "kafkaSpout")),1);
  8. topologyBuilder.setBolt("mybolt1",new ParserOrderMqBolt(),1).shuffleGrouping("kafkaSpout");
  9. Config config = new Config();
  10. config.setNumWorkers(1);
  11. //3、提交任务 -----两种模式 本地模式和集群模式
  12. if (args.length>0) {
  13. StormSubmitter.submitTopology(args[0], config, topologyBuilder.createTopology());
  14. }else {
  15. LocalCluster localCluster = new LocalCluster();
  16. localCluster.submitTopology("storm2kafka", config, topologyBuilder.createTopology());
  17. }
  18. }
  19. }
③在Bolt组件中,主要设定bolt的执行以及输出为redis的window的客户端
  1. public class ParserOrderMqBolt extends BaseRichBolt {
  2. private JedisPool pool;
  3. @Override
  4. public void prepare(Map stormConf, TopologyContext context, OutputCollector collector) {
  5. //change "maxActive" -> "maxTotal" and "maxWait" -> "maxWaitMillis" in all examples
  6. JedisPoolConfig config = new JedisPoolConfig();
  7. //控制一个pool最多有多少个状态为idle(空闲的)的jedis实例。
  8. config.setMaxIdle(5);
  9. //控制一个pool可分配多少个jedis实例,通过pool.getResource()来获取;
  10. //如果赋值为-1,则表示不限制;如果pool已经分配了maxActive个jedis实例,则此时pool的状态为exhausted(耗尽)。
  11. //在borrow一个jedis实例时,是否提前进行validate操作;如果为true,则得到的jedis实例均是可用的;
  12. config.setMaxTotal(1000 * 100);
  13. //表示当borrow(引入)一个jedis实例时,最大的等待时间,如果超过等待时间,则直接抛出JedisConnectionException;
  14. config.setMaxWaitMillis(30);
  15. config.setTestOnBorrow(true);
  16. config.setTestOnReturn(true);
  17. /**
  18. *如果你遇到 java.net.SocketTimeoutException: Read timed out exception的异常信息
  19. *请尝试在构造JedisPool的时候设置自己的超时值. JedisPool默认的超时时间是2秒(单位毫秒)
  20. */
  21. pool = new JedisPool(config, "127.0.0.1", 6379);
  22. }
  23. @Override
  24. public void execute(Tuple input) {
  25. Jedis jedis = pool.getResource();
  26. //获取kafkaSpout发送过来的数据,是一个json
  27. String string = new String((byte[]) input.getValue(0));
  28. //解析json
  29. OrderInfo orderInfo = (OrderInfo) new Gson().fromJson(string, OrderInfo.class);
  30. //整个网站,各个业务线,各个品类,各个店铺,各个品牌,每个商品
  31. //获取整个网站的金额统计指标 //redis中执行 get totalAmount
  32. // String totalAmount = jedis.get("totalAmount");
  33. jedis.incrBy("totalAmount",orderInfo.getProductPrice());
  34. //获取商品所属业务线的指标信息
  35. String bid = getBubyProductId(orderInfo.getProductId(),"b");
  36. // String bAmout = jedis.get(bid+"Amout");
  37. jedis.incrBy(bid+"Amount",orderInfo.getProductPrice());
  38. // jedis.close();
  39. }
  1. private String getBubyProductId(String productId,String type) {
  2. // key:value
  3. //index:productID:info---->Map
  4. // productId-----<各个业务线,各个品类,各个店铺,各个品牌,每个商品>
  5. Map<String,String> map = new HashMap<>();
  6. map.put("b","3c");
  7. map.put("c","phone");
  8. map.put("s","121");
  9. map.put("p","iphone");
  10. return map.get(type);
  11. }
  12. @Override
  13. public void declareOutputFields(OutputFieldsDeclarer declarer) {
  14. }
  15. }
在Windows客户端执行get  totalAmountget Amount 来获取key-Value键值对信息
prepare()初始化方法里设置redis以及



(五)LearnRedis
先启动redis-server 再启动redis-cli  即先启动服务,后启动客户端查询!
get  totalAmount //获得简键值对信息
getAmount