4.Storm例题,双十一订单题
订单编号-----时间戳----商品编号----数量----店铺ID----单价----用户ID
订单编号----用户ID+时间戳
时间戳-----
商品编号-----店铺编号+随机数【10】
店铺iD----随机生成2位数字【10-99】
单价【1-1000】
用户ID[UUID]前20位
需求:
- 进行了多少次交易?
- 累积到现在总的交易额?
- 统计每种商品卖出去多少件商品?
- 统计每个店铺交易额?
- 每个用户的消费金额?
程序如下:
-
ShoppingCountSpout:模拟上述数据的结构
package com.gcc.shoppingCount; 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 java.util.Map; import java.util.Random; import java.util.UUID; public class ShoppingCountSpout extends BaseRichSpout { //声明一个SpoutOutputcollector 对象 用于发送数据 private SpoutOutputCollector collector; //创建一个数组存放需要发送的数据 private String[] array={"hello world","hello gcc","hello hi welcome to world"}; private Random random=new Random(); @Override public void open(Map conf, TopologyContext context, SpoutOutputCollector collector) { this.collector=collector; } /** * 重复调用这一个方法从源数据获取一条记录 * 我们根据业务需求近期进行封装,然后通过SpoutOutputCollector 发送给下一个Bolt * */ @Override public void nextTuple() { //获取本次需要发送的字符串 //用户编号 String userID= UUID.randomUUID().toString().replace("-","").substring(0,20); //时间戳 long currentTimeMillis = System.currentTimeMillis(); //订单编号 String orderID=userID+currentTimeMillis; //店铺编号 int shopID= (int) (Math.random()*90+10); //商品编号 String goodID=String.valueOf(shopID)+(int)Math.random()*10; //单价 int price= (int)(Math.random()*1000+1); //数量 int num= (int)(Math.random()*100+1); String line=orderID+"--"+currentTimeMillis+"--"+goodID+"--"+num+"--"+shopID+"--"+price+"--"+userID; // System.out.println("ShoppingCountSpout.nextTuple---"+line); collector.emit(new Values(line)); //限制传输速度 try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } /** * 定义输出值对应的属性 * @param declarer */ @Override public void declareOutputFields(OutputFieldsDeclarer declarer) { declarer.declare(new Fields("line")); } }
-
切分:按照商品id划分
package com.gcc.shoppingCount; import org.apache.storm.topology.BasicOutputCollector; import org.apache.storm.topology.OutputFieldsDeclarer; import org.apache.storm.topology.base.BaseBasicBolt; import org.apache.storm.tuple.Fields; import org.apache.storm.tuple.Tuple; import org.apache.storm.tuple.Values; public class GoodSplitBolt extends BaseBasicBolt { /** * 处理数据的业务逻辑 * 切分 并发送给count统计,按照S商品id划分 * * @param input * @param collector */ @Override public void execute(Tuple input, BasicOutputCollector collector) { //获取单词 System.out.println("priceCountBolt--execute:"+input.getStringByField("line")); String[]words=input.getStringByField("line").split("--"); collector.emit(new Values(words[3],words[2])); } /** * 如果需要向下传递数据,需要提前定义数据格式 * @param declarer */ @Override public void declareOutputFields(OutputFieldsDeclarer declarer) { declarer.declare(new Fields("num","goodid")); } }
-
统计每个商品卖出的件数
package com.gcc.shoppingCount; import org.apache.storm.topology.BasicOutputCollector; import org.apache.storm.topology.OutputFieldsDeclarer; import org.apache.storm.topology.base.BaseBasicBolt; import org.apache.storm.tuple.Tuple; import java.util.HashMap; import java.util.Map; public class GoodCountBolt extends BaseBasicBolt { //容器计算每个商品卖出去多少件 private Map<String,Integer>map =new HashMap<>(); /** * 处理数据的业务逻辑 * 进行了多少次交易 * 累计到现在的总交易额 * @param input * @param collector */ @Override public void execute(Tuple input, BasicOutputCollector collector) { //获取单词 String goodID=input.getStringByField("goodid"); int num=Integer.parseInt(input.getStringByField("num")); System.out.println("goodCountBolt--execute: 商品编号"+goodID+"销量:" +num); if(map.containsKey(goodID)){ int count=map.get(goodID); count+=num; map.put(goodID,count); }else{ map.put(goodID,num); } System.out.println("goodCountBolt本次执行完,"+"商品id:"+goodID+"销量:"+map.get(goodID)); } /** * 如果需要向下传递数据,需要提前定义数据格式 * @param declarer */ @Override public void declareOutputFields(OutputFieldsDeclarer declarer) { } }
-
统计当前的总交易次数以及交易额
package com.gcc.shoppingCount; import org.apache.storm.topology.BasicOutputCollector; import org.apache.storm.topology.OutputFieldsDeclarer; import org.apache.storm.topology.base.BaseBasicBolt; import org.apache.storm.tuple.Tuple; public class PriceCountBolt extends BaseBasicBolt { //声明一个容器 存在以前的统计结果 private int count; private int allprice; /** * 处理数据的业务逻辑 * 进行了多少次交易 * 累计到现在的总交易额 * @param input * @param collector */ @Override public void execute(Tuple input, BasicOutputCollector collector) { //获取单词 System.out.println("priceCountBolt--execute:"+input.getStringByField("line")); String[]words=input.getStringByField("line").split("--"); allprice+=Integer.valueOf(words[3])*Integer.valueOf(words[5]); count++; System.out.println("priceCountBolt本次执行完,"+"总交易额:"+allprice+"总交易次数:"+count); } /** * 如果需要向下传递数据,需要提前定义数据格式 * @param declarer */ @Override public void declareOutputFields(OutputFieldsDeclarer declarer) { } }
-
按照店铺ID进行划分
package com.gcc.shoppingCount; import org.apache.storm.topology.BasicOutputCollector; import org.apache.storm.topology.OutputFieldsDeclarer; import org.apache.storm.topology.base.BaseBasicBolt; import org.apache.storm.tuple.Fields; import org.apache.storm.tuple.Tuple; import org.apache.storm.tuple.Values; public class ShopSplitBolt extends BaseBasicBolt { /** * 处理数据的业务逻辑 * 切分 按照店铺id划分 * * @param input * @param collector */ @Override public void execute(Tuple input, BasicOutputCollector collector) { //获取单词 // System.out.println("ShopSplitBolt--execute:"+input.getStringByField("line")); String[]words=input.getStringByField("line").split("--"); System.out.println("数量:"+words[3]+",单价:"+words[5]+",店铺id:"+words[4]); collector.emit(new Values(words[3],words[5],words[4])); } /** * 如果需要向下传递数据,需要提前定义数据格式 * @param declarer */ @Override public void declareOutputFields(OutputFieldsDeclarer declarer) { declarer.declare(new Fields("num","price","shopid")); } }
-
统计每个店铺的总交易额
package com.gcc.shoppingCount; import org.apache.storm.topology.BasicOutputCollector; import org.apache.storm.topology.OutputFieldsDeclarer; import org.apache.storm.topology.base.BaseBasicBolt; import org.apache.storm.tuple.Tuple; import java.util.HashMap; import java.util.Map; public class ShopCountBolt extends BaseBasicBolt { //容器计算每个店铺的总交易额度 private Map<String,Integer>map =new HashMap<>(); /** * 处理数据的业务逻辑 * 进行了多少次交易 * 累计到现在的总交易额 * @param input * @param collector */ @Override public void execute(Tuple input, BasicOutputCollector collector) { //获取单词 String shopID=input.getStringByField("shopid"); int num=Integer.parseInt(input.getStringByField("num")); int price=Integer.parseInt(input.getStringByField("price")); System.out.println("ShopCountBolt--execute: 店铺编号"+shopID+"销量:" +num+"单价:"+price); if(map.containsKey(shopID)){ int sum=map.get(shopID); sum+=num*price; map.put(shopID,sum); }else{ map.put(shopID,num*price); } System.out.println("ShopCountBolt本次执行完,"+"店铺id:"+shopID+",总交易额:"+map.get(shopID)); } /** * 如果需要向下传递数据,需要提前定义数据格式 * @param declarer */ @Override public void declareOutputFields(OutputFieldsDeclarer declarer) { } }
-
按照用户的id进行切分
package com.gcc.shoppingCount; import org.apache.storm.topology.BasicOutputCollector; import org.apache.storm.topology.OutputFieldsDeclarer; import org.apache.storm.topology.base.BaseBasicBolt; import org.apache.storm.tuple.Fields; import org.apache.storm.tuple.Tuple; import org.apache.storm.tuple.Values; public class userSplitBolt extends BaseBasicBolt { /** * 处理数据的业务逻辑 * 切分 按照用户id切分 计算用户的消费金额 * * @param input * @param collector */ @Override public void execute(Tuple input, BasicOutputCollector collector) { //获取单词 // System.out.println("ShopSplitBolt--execute:"+input.getStringByField("line")); String[] words = input.getStringByField("line").split("--"); System.out.println("数量:" + words[3] + ",单价:" + words[5] + ",用户id:" + words[6]); collector.emit(new Values(words[3], words[5], words[6])); } /** * 如果需要向下传递数据,需要提前定义数据格式 * * @param declarer */ @Override public void declareOutputFields(OutputFieldsDeclarer declarer) { declarer.declare(new Fields("num", "price", "userid")); } }
-
统计每个用户的总交易额
package com.gcc.shoppingCount; import org.apache.storm.topology.BasicOutputCollector; import org.apache.storm.topology.OutputFieldsDeclarer; import org.apache.storm.topology.base.BaseBasicBolt; import org.apache.storm.tuple.Tuple; import java.util.HashMap; import java.util.Map; public class UserCountBolt extends BaseBasicBolt { //容器计算每个用户的消费金额 private Map<String,Integer>map =new HashMap<>(); /** * 处理数据的业务逻辑 * @param input * @param collector */ @Override public void execute(Tuple input, BasicOutputCollector collector) { //获取单词 String userID=input.getStringByField("userid"); int num=Integer.parseInt(input.getStringByField("num")); int price=Integer.parseInt(input.getStringByField("price")); System.out.println("UserCountBolt--execute: 用户编号"+userID+"购买数量:" +num+"单价:"+price); if(map.containsKey(userID)){ int sum=map.get(userID); sum+=num*price; map.put(userID,sum); }else{ map.put(userID,num*price); } System.out.println("UserCountBolt本次执行完,"+"用户id:"+userID+",总消费金额:"+map.get(userID)); } /** * 如果需要向下传递数据,需要提前定义数据格式 * @param declarer */ @Override public void declareOutputFields(OutputFieldsDeclarer declarer) { } }
-
设置拓扑结构
package com.gcc.shoppingCount; import org.apache.storm.Config; import org.apache.storm.LocalCluster; import org.apache.storm.generated.StormTopology; import org.apache.storm.topology.TopologyBuilder; import org.apache.storm.tuple.Fields; public class ShoppingCountTopology { public static void main(String[] args) { //1.创建任务的拓扑图 //创建topology的构建起 TopologyBuilder topologyBuilder = new TopologyBuilder(); //设置拓扑关系(Spout) topologyBuilder.setSpout("ShoppingCountSpout",new ShoppingCountSpout()); //设置拓扑关系Bolt 计算交易次数以及交易额 topologyBuilder.setBolt("priceCountBolt",new PriceCountBolt(),1).shuffleGrouping("ShoppingCountSpout"); //设置拓扑关系Bolt 对每种商品的销量进行统计 topologyBuilder.setBolt("goodSplitBolt",new GoodSplitBolt(),2).shuffleGrouping("ShoppingCountSpout"); topologyBuilder.setBolt("goodCountBolt",new GoodCountBolt(),4).fieldsGrouping("goodSplitBolt",new Fields("goodid")); //统计每个店铺的交易额度 topologyBuilder.setBolt("ShopSplitBolt",new ShopSplitBolt(),2).shuffleGrouping("ShoppingCountSpout"); topologyBuilder.setBolt("ShopCountBolt",new ShopCountBolt(),4).fieldsGrouping("ShopSplitBolt",new Fields("shopid")); //统计每个用户的消费总金额 topologyBuilder.setBolt("userSplitBolt",new userSplitBolt(),2).shuffleGrouping("ShoppingCountSpout"); topologyBuilder.setBolt("UserCountBolt",new UserCountBolt(),4).fieldsGrouping("userSplitBolt",new Fields("userid")); //2.配置启动 Config config = new Config(); //创建Topology StormTopology topology = topologyBuilder.createTopology(); //本地模式启动集群 LocalCluster localCluster = new LocalCluster(); localCluster.submitTopology("ShoppingCountTopology",config,topology); } }