分散式系統監控(五)- 日誌分析
背景
前面一章節介紹瞭如何使用rocketmq來歸集資料資訊,下面將介紹如何使用storm從rocketmq中獲取日誌資訊,並將訊息轉換為流資訊進行統計分析。
storm簡介
Storm叢集和Hadoop叢集表面上看很類似。但是Hadoop上執行的是MapReduce jobs,而在Storm上執行的是拓撲(topology),這兩者之間是非常不一樣的。一個關鍵的區別是: 一個MapReduce job最終會結束, 而一個topology永遠會執行(除非你手動kill掉)。
在Storm的叢集裡面有兩種節點: 控制節點(master node)和工作節點(worker node)。控制節點上面執行一個叫Nimbus後臺程式,它的作用類似Hadoop裡面的JobTracker。Nimbus負責在叢集裡面分發程式碼,分配計算任務給機器,並且監控狀態。
每一個工作節點上面執行一個叫做Supervisor的節點。Supervisor會監聽分配給它那臺機器的工作,根據需要啟動/關閉工作程式worker。每一個工作程式執行一個topology的一個子集;一個執行的topology由執行在很多機器上的很多工作程式worker組成。
Nimbus和Supervisor之間的所有協調工作都是通過Zookeeper叢集完成。另外,Nimbus程式和Supervisor程式都是快速失敗(fail-fast)和無狀態的。所有的狀態要麼在zookeeper裡面, 要麼在本地磁碟上。這也就意味著你可以用kill -9來殺死Nimbus和Supervisor程式, 然後再重啟它們,就好像什麼都沒有發生過。這個設計使得Storm異常的穩定。
Topology
計算任務Topology是由不同的Spouts和Bolts,通過資料流(Stream)連線起來的圖。下面是一個Topology的結構示意圖:
其中包含有:
Spout
Storm中的訊息源,用於為Topology生產訊息(資料),一般是從外部資料來源(如Message Queue、RDBMS、NoSQL、Realtime Log)不間斷地讀取資料併傳送給Topology訊息(tuple元組)。Spout可以是可靠的,也可以是不可靠的。如果這個tuple沒有被Storm完全處理,可靠的訊息源可以重新發射一個tuple,但是不可靠的訊息源一旦發出一個tuple就不能重發了。(可靠性會在下面介紹)
Spout類裡面最重要的方法是nextTuple。要麼發射一個新的tuple到topology裡面或者簡單的返回(如果已經沒有新的tuple)。要注意的是nextTuple方法不能阻塞,因為storm在同一個執行緒上面呼叫所有訊息源spout的方法。
另外兩個比較重要的spout方法是ack和fail。storm在檢測到一個tuple被整個topology成功處理的時候呼叫ack,否則呼叫fail。storm只對可靠的spout呼叫ack和fail。
Bolt
Storm中的訊息處理者,用於為Topology進行訊息的處理,Bolt可以執行過濾, 聚合, 查詢資料庫等操作,而且可以一級一級的進行處理。
storm安裝及開發
將下載的包解壓即可。
storm開發
開發環境搭建。
建立一個常規的java工程或maven工程就可以,並引入storm包的依賴。
<dependency>
<groupId>org.apache.storm</groupId>
<artifactId>storm-core</artifactId>
<version>${storm.version}</version>
<scope>provided</scope>
</dependency>
spout開發
由於我們的日誌歸集元件使用的RocketMq,所以我們需要使用RocketMq開發spout類,在storm執行環境中執行RocketMq的消費端,獲取指定主題的訊息佇列資料。由於storm發行釋出的穩定版預設沒有整合RocketMq元件,所以需要將RocketMq整合到storm中,使用RocketMq定義的spout來獲取rocketmq的中訊息資訊。
由於storm最新開發的主幹上已經整合了RocketMq,但中因為與1.2.2版本的核心介面不一致。所以需要將工程原始碼下載下來進行修改一下。
修改步驟為:
1.匯入\external\storm-rocketmq工程
2.修改工程的pom.xml檔案,將storm-core的依賴版本修改為1.2.2
3.修復編譯異常,主是是將介面中Map<String,Object>修改為Map。
4.為了能在Spout中輸出的Tuple中獲取RocketMq的tags和keys屬性資訊,將org.apache.storm.rocketmq.RocketMqUtils.java進行了重構。
/**
* Generate Storm tuple values by Message and Scheme.
* @param msg RocketMQ Message
* @param scheme Scheme for deserializing
* @return tuple values
*/
public static List<Object> generateTuples(Message msg, Scheme scheme) {
List<Object> tup;
String rawKey = msg.getKeys();
ByteBuffer body = ByteBuffer.wrap(msg.getBody());
if (rawKey != null && scheme instanceof KeyValueScheme) {
ByteBuffer key = ByteBuffer.wrap(rawKey.getBytes(StandardCharsets.UTF_8));
tup = ((KeyValueScheme)scheme).deserializeKeyAndValue(key, body);
//ADD BEGIN
} if (scheme instanceof MessageScheme) {
tup = ((MessageScheme)scheme).deserializeValue(msg);
//ADD END
} else {
tup = scheme.deserialize(body);
}
return tup;
}
並新增一個介面MessageScheme:
package org.apache.storm.rocketmq.spout.scheme;
import java.util.List;
import org.apache.rocketmq.common.message.Message;
import org.apache.storm.spout.Scheme;
public interface MessageScheme extends Scheme {
List<Object> deserializeValue(Message msg);
}
和一個實現類 DefaultMessageScheme:
package org.apache.storm.rocketmq.spout.scheme;
import java.nio.ByteBuffer;
import java.util.List;
import org.apache.rocketmq.common.message.Message;
import org.apache.storm.tuple.Fields;
import org.apache.storm.tuple.Values;
public class DefaultMessageScheme extends StringScheme implements MessageScheme {
public static final String FIELD_TAGS = "Tags";
public static final String FIELD_TEYS = "Keys";
public static final String FIELD_BODY = "Body";
public static final Fields DEFAULT_FIELDS = new Fields("Tags", "Keys", "Body");
@Override
public List<Object> deserializeValue(Message msg) {
ByteBuffer body = ByteBuffer.wrap(msg.getBody());
String bodyStr = deserializeString(body);
return new Values(msg.getTags(), msg.getKeys(), bodyStr);
}
@Override
public Fields getOutputFields() {
return DEFAULT_FIELDS;
}
}
最終將工程編譯的jar包放在storm的lib目錄下,並且在工程中引入該元件包。
<dependency>
<!-- 由storm最新主幹的\external\storm-rocketmq工程改造而來 -->
<groupId>com.going.saas</groupId>
<artifactId>going-storm-rocketmq</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.alibaba.rocketmq</groupId>
<artifactId>rocketmq-client</artifactId>
<version>3.6.2.Final</version>
</dependency>
到這一步就可以直接使用RocketMqSpout了,首先建立一個Properties類,設定建立RocketMq訊息端所需要的引數。
Properties properties = new Properties();
properties.setProperty(SpoutConfig.NAME_SERVER_ADDR, "10.209.8.126:9876");
properties.setProperty(SpoutConfig.CONSUMER_GROUP, "RESOURCE_INFOS_CONSUMER_GRP");
properties.setProperty(SpoutConfig.CONSUMER_TOPIC, "RESOURCES_INFO_TOPIC");
properties.setProperty(SpoutConfig.SCHEME,SpoutConfig.MESSAGE_SCHEME);
再根據引數建立RocketMqSpout物件即可。
new RocketMqSpout(properties)
Bolt開發
該例子中開發一個Bolt,處理從Spout中獲取轉為Tuple物件的訊息資訊。將資訊存在Redis中。
import org.apache.storm.redis.bolt.AbstractRedisBolt;
import org.apache.storm.redis.common.config.JedisPoolConfig;
import org.apache.storm.rocketmq.spout.scheme.DefaultMessageScheme;
import org.apache.storm.topology.OutputFieldsDeclarer;
import org.apache.storm.tuple.Tuple;
import redis.clients.jedis.JedisCommands;
/**
* 獲取終端發來的資源利用資訊, 將新獲取的資源資訊替換舊的資源資訊。
*
* @author Administrator
*
*/
public class ResourcesInfoSplitBolt extends AbstractRedisBolt {
private static final String REDIS_KEY_PREFIX = "RESOURCE_INFO_";
public ResourcesInfoSplitBolt(JedisPoolConfig config) {
super(config);
}
@Override
public void declareOutputFields(OutputFieldsDeclarer declarer) {
}
@Override
protected void process(Tuple tuple) {
JedisCommands jedisCommands = null;
try {
String body = tuple.getStringByField(DefaultMessageScheme.FIELD_BODY);
String tags = tuple.getStringByField(DefaultMessageScheme.FIELD_TAGS).trim();
jedisCommands = getInstance();
jedisCommands.lpush(REDIS_KEY_PREFIX+tags, body);
} finally {
if (jedisCommands != null) {
returnInstance(jedisCommands);
}
this.collector.ack(tuple);
}
}
Topology開發
Spout和Bolt開發完成以後,就需要開發Topology將它們串連起來,具體示例程式碼如下:
import java.util.Properties;
import org.apache.storm.Config;
import org.apache.storm.LocalCluster;
import org.apache.storm.redis.common.config.JedisPoolConfig;
import org.apache.storm.rocketmq.SpoutConfig;
import org.apache.storm.rocketmq.spout.RocketMqSpout;
import org.apache.storm.topology.TopologyBuilder;
import com.going.storm.bolt.ResourcesInfoSplitBolt;
public class ResourceInfosTopology {
public static void main(String[] args) throws InterruptedException {
Properties properties = new Properties();
properties.setProperty(SpoutConfig.NAME_SERVER_ADDR, "10.209.8.126:9876");
properties.setProperty(SpoutConfig.CONSUMER_GROUP, "RESOURCE_INFOS_CONSUMER_GRP");
properties.setProperty(SpoutConfig.CONSUMER_TOPIC, "RESOURCES_INFO_TOPIC");
properties.setProperty(SpoutConfig.SCHEME,SpoutConfig.MESSAGE_SCHEME);
// RocketMqSpout spout = new RocketMqSpout(properties);
properties.setProperty("REDIS_HOST", "10.209.8.126");
properties.setProperty("REDIS_PORT", "6379");
// 定義拓撲
TopologyBuilder builder = new TopologyBuilder();
builder.setSpout("resouece-info-reader", new RocketMqSpout(properties));
JedisPoolConfig poolConfig = new JedisPoolConfig.Builder()//
.setHost(properties.getProperty("REDIS_HOST"))//
.setPort(Integer.valueOf(properties.getProperty("REDIS_PORT")))//
.build();
builder.setBolt("word-normalizer", new ResourcesInfoSplitBolt(poolConfig)).shuffleGrouping("resouece-info-reader");
// builder.setBolt("word-counter", new WordCounter(),2).fieldsGrouping("word-normalizer", new Fields("word"));
// 配置
Config conf = new Config();
// conf.put("wordsFile", args[0]);
conf.setDebug(false);
// 執行拓撲
conf.put(Config.TOPOLOGY_MAX_SPOUT_PENDING, 1);
LocalCluster cluster = new LocalCluster();
cluster.submitTopology("Getting-Started-Resource-Infos-Topologie", conf, builder.createTopology());
Thread.sleep(1000000000);
cluster.shutdown();
}
}
storm部署執行
工程開發完成以後就需要將工程進行部署執行。我這裡以docker為例對開發的功能進行部署。
這裡基於storm官方的docker映象進行部署。
我們基於storm的1.2.2版本的映象(與本地開發的storm版本保持 一致就好),將工程依賴的第三方包加入到映象中storm元件的extlib目錄下。
FROM storm:1.2.2
ADD extlib/dubbo-2.5.8.jar extlib/dubbo-2.5.8.jar
ADD extlib/fastjson-1.2.29.jar extlib/fastjson-1.2.29.jar
ADD extlib/going-storm-rocketmq-0.0.1-SNAPSHOT.jar extlib/going-storm-rocketmq-0.0.1-SNAPSHOT.jar
ADD extlib/guava-13.0.1.jar extlib/guava-13.0.1.jar
ADD extlib/jackson-annotations-2.9.0.jar extlib/jackson-annotations-2.9.0.jar
ADD extlib/jackson-core-2.9.4.jar extlib/jackson-core-2.9.4.jar
ADD extlib/jackson-databind-2.9.4.jar extlib/jackson-databind-2.9.4.jar
ADD extlib/javassist-3.20.0-GA.jar extlib/javassist-3.20.0-GA.jar
ADD extlib/jedis-2.9.0.jar extlib/jedis-2.9.0.jar
ADD extlib/netty-3.2.5.Final.jar extlib/netty-3.2.5.Final.jar
ADD extlib/netty-all-4.0.42.Final.jar extlib/netty-all-4.0.42.Final.jar
ADD extlib/rocketmq-client-3.6.2.Final.jar extlib/rocketmq-client-3.6.2.Final.jar
ADD extlib/rocketmq-client-4.2.0.jar extlib/rocketmq-client-4.2.0.jar
ADD extlib/rocketmq-common-4.2.0.jar extlib/rocketmq-common-4.2.0.jar
ADD extlib/rocketmq-remoting-4.2.0.jar extlib/rocketmq-remoting-4.2.0.jar
ADD extlib/storm-redis-1.2.2.jar extlib/storm-redis-1.2.2.jar
然後通過生成好的映象ab/storm生成例項
docker run -d --name storm-resources -it -v ${LOCAL_PATH}/going-storm-0.0.1-SNAPSHOT.jar:/topology.jar ab/storm storm jar /topology.jar com.going.storm.topology.ResourceInfosTopology
到這一步日誌統計功能即開發完成了,對應的分析功能也可以通過Bolt來完成。
相關文章
- 部署Sentry日誌監控系統
- 日誌: 分散式系統的核心分散式
- 分散式監控系統之Zabbix proxy分散式
- 黑盒監控、日誌監控
- 分散式監控系統之Zabbix基礎分散式
- 一種分散式預寫日誌系統分散式
- 分散式監控系統之Zabbix主動、被動及web監控分散式Web
- 分散式監控系統ganglia的詳細配置分散式
- 分散式監控系統之Zabbix基礎使用分散式
- 分散式日誌傳輸系統Databus(一)--系統介紹分散式
- 分散式監控系統之Zabbix網路發現分散式
- 分散式監控系統Zabbix3.4-針對MongoDB效能監控操作筆記分散式MongoDB筆記
- Linux系統中五款好用的日誌分析工具Linux
- Mysql事件監控日誌MySql事件
- ELK日誌分析系統
- (4)分散式系統關鍵技術:全棧監控分散式全棧
- Kubernetes Ingress 日誌分析與監控的最佳實踐
- 影片監控ai分析系統AI
- 影片監控智慧分析系統
- 新增橋接連線狀態監控、重構日誌系統橋接
- 小程式日誌監控工具
- 03-Loki 日誌監控Loki
- 分散式監控系統之Zabbix巨集、模板和自定義item分散式
- 分散式系統關注點(22)——360°的全方位監控分散式
- ELK-日誌分析系統
- SpringBoot開發案例構建分散式日誌處理系統Spring Boot分散式
- Elasticsearch+Fluentd+Kafka搭建分散式日誌系ElasticsearchKafka分散式
- 監控影片行為分析系統
- 煤礦影片監控分析系統
- 分散式監控系統Zabbix3.4-釘釘告警配置記錄分散式
- 構建基於 HarmonyOS Next 的分散式工業監控系統分散式
- Java後端分散式系統的服務監控:Zabbix與NagiosJava後端分散式iOS
- ELK監控nginx日誌總結Nginx
- Grafana、Prometheus、mtail-日誌監控GrafanaPrometheusAI
- 打造雲原生大型分散式監控系統(四): Kvass+Thanos 監控超大規模容器叢集分散式
- ELK+FileBeat日誌分析系統
- ELK日誌分析系統詳解
- 典型分散式系統分析:Dynamo分散式