转载请注明出处:http://blog.youkuaiyun.com/lonelytrooper/article/details/9970543
第六章 一个真实的示例
本章要阐述一个典型的web分析解决方案,一个经常使用hadoop批量作业来解决的问题。不同于hadoop的实现,基于storm的解决方案将显示实时刷新的结果。
我们的示例包含三个主要的组件(见图6-1):
﹒一个Node.js网络应用,用来测试系统
﹒一个Redis服务器,用来持久化数据。
﹒一个storm topology,用于实时分布式数据处理。
图6-1. 架构总述
如果你希望通过实现示例来学习这一章,你应该先看看附录C。
Node.js Web应用
我们使用三个页面来模拟了一个电子商务网站:一个主页,一个产品页以及一个产品统计页。这个应用通过使用Express Framework 和Socket.io Framework向浏览器推送更新来实现。该应用的目的是使你运行集群并看到结果,但它并不是本书的关注点,因此我们除了页面本身的描述没有其他任何的细节深入。
主页
本页提供平台所有可用商品的链接来简化他们的导航。它从Redis服务器读取并列举了所有的项。本页的URL地址是http://localhost:3000/。(见图6-2)。
图6-2. 主页
产品页
产品页显示了一个与特定产品相关的信息,例如价格,标题及分类。本页的URL地址是http://localhost:3000/product/:id。(见6-3)。
图6-3. 产品页
产品统计页
本页展示storm集群计算的信息,这些信息是用户浏览页面时被收集的。可以如此总结:浏览了这件产品的用户同时观察了N次该类别的产品。本页的URL地址是http://localhost:3000/product/:id/stats。(见图6-4 )。
图6-4. 产品状态视图
开始Node.js Web应用
在开始Redis服务器之前,通过运行工程路径上的如下命令来启动web应用:
Nodewebapp/app.js
该web应用会自动植入包含示例产品的Redis供你实践。
The Storm Topology
Storm topology在本系统中的目的是当用户浏览页面时实时的更新产品统计数据。产品统计页显示一个关联了计数器的分类列表,显示访问了同一类目下其他产品的用户个数。这有助于卖家了解他们客户的需求。Topology收到一条浏览日志并且更新产品的统计数据,正如在图6-5中显示的。
图6-5. Storm topology输入和输出
我们的storm topology包含五个组件:一个用于供给它的spout及四个用于完成工作的bolts。
UsersNavigationSpout
读取用户浏览队列并发送至topology
GetCategoryBolt
从Redis服务器读取产品信息并添加其类目到流
UserHistoryBolt
读取用户之前的产品浏览信息并发送Product:Category对来更新下一阶段的计数器
ProductCategoriesCounterBolt
记录用户浏览的某一特定分类的某产品的次数。
NewsNotifierBolt
通知web应用立即更新用户界面。
这里是topology的构建(见图6-6):
package storm.analytics;
...
public class TopologyStarter{
public static voidmain(String[]args) {
Logger.getRootLogger().removeAllAppenders();
TopologyBuilder builder =new TopologyBuilder();
builder.setSpout("read-feed",new UsersNavigationSpout(),3);
builder.setBolt("get-categ",new GetCategoryBolt(),3)
.shuffleGrouping("read-feed");
builder.setBolt("user-history",new UserHistoryBolt(),5)
.fieldsGrouping("get-categ",new Fields("user"));
builder.setBolt("product-categ-counter",new ProductCategoriesCounterBolt(),5)
.fieldsGrouping("user-history",new Fields("product"));
builder.setBolt("news-notifier",new NewsNotifierBolt(),5)
.shuffleGrouping("product-categ-counter");
Config conf =new Config();
conf.setDebug(true);
conf.put("redis-host",REDIS_HOST);
conf.put("redis-port",REDIS_PORT);
conf.put("webserver",WEBSERVER);
LocalCluster cluster =new LocalCluster();
cluster.submitTopology("analytics",conf, builder.createTopology());
}
}
图6-6. Stormtopology