568
技術社區[雲棲]
基於阿裏雲生態構建網聚寶業務監控係統
伊始 -- 網聚寶業務監控係統
今年網聚寶開始推進服務化進程,我有幸分在架構組,在公司產品服務化的過程中負責業務監控模塊。在以前,我們發展工程還未服務化的時候,我們可能隻單單關注單個請求的耗時等基本指標,對其作出優化或者業務上的調整,其內容往往也隻是一人從頂到底,一人即可了解其中的邏輯層次。但隨著服務化的到來以及業務邏輯愈來愈複雜,一個前端 web 層的請求需要調用很多服務才可以完成一次請求,當請求變的比較慢或者發生故障,我們很難看出是哪個服務或者哪台機器發生的問題,所以需要一個監控服務,來快速複原出完整的請求鏈,以及請求中的耗時、異常等信息。從而判斷是哪裏出現了問題,哪裏我們還有改進的空間,所以服務化監控模塊應運而生。
而我們的監控過程中,部分模塊基於了阿裏雲的基礎設施,使得我們在上業務監控的過程中如虎添翼。阿裏雲的基礎設施在使用過程中具有使用非常便捷快速的優勢,真正做到了隻關注業務邏輯,阿裏雲也將其旗下各個產品鏈路打通,我們可以根據自己的需要自由選擇組合,完成我們的構想,這種一體化的體驗,讓我們在上雲的時間過程中,真真切切的感受到了雲生態。
下麵,我將帶大家一起來看看,我們在做監控部分中,如何玩轉阿裏雲生態鏈,構建我們的項目異常監控信息收集。我們使用阿裏雲數加流計算(Ali Stream)為核心中樞,上下遊使用到 阿裏雲日誌服務(SLS) 、 消息隊列(ONS) 、阿裏雲數據庫(RDS) 這些產品。SLS + Ali Stream + ONS + RDS 的鏈路打通也為我們開發過程中帶來了極大的便捷。
尤其我們在選擇以數加流計算平台作為數據流中樞,數據流的傳輸過程中我們都不需要寫過多的代碼,即可完成 上下遊數據傳輸,是不是相當的炫酷呢?下麵,我將帶領大家一同探究其中的奧秘,選擇一些實現細節與大家一同分享,領略下 “無代碼編程” 的魅力所在。
構建 -- “無代碼編程” 上雲
前文提到,我們在針對異常監控的模塊中 使用到了 SLS + Ali Stream + ONS + RDS 這條產品鏈路,那麼有看官會好奇,我們是如何使用到這條鏈路從而達到 “無代碼編程” 的呢,在上雲過程中我們有遭遇哪些困難呢?
現在,我們從我們工程中的幾個模塊來探究這條鏈路的實現細節:
監控客戶端
我們使用在我們的 Dubbo 服務中依賴了網聚寶的自有監控客戶端,裏麵嵌入了諸如調用鏈監控埋點,異常截獲等模塊,其主要作用是代碼切麵攔截等功能,我們對未捕獲異常攔截也在此,我們使用 Java 自帶的 Thread.UncaughtExceptionHandler
接口 下的 void uncaughtException(Thread t, Throwable ex)
方法對異常進行攔截,並獲取異常信息以及異常堆棧。
```java
public class ExceptionLoggerHandler implements Thread.UncaughtExceptionHandler {
private static Logger log = Logger.getLogger(ExceptionLoggerHandler.class);
@Value(value = "${dubbo.application.name}")
private String exceptionDubboName;
public ExceptionLoggerHandler() {
}
public void uncaughtException(Thread t, Throwable ex) {
log.error("Uncaught exception in Application: " + exceptionDubboName, ex);
}
}
```
將異常信息使用阿裏雲日誌服務 com.aliyun.openservices.log.log4j.LoghubAppender
進行收集,並根據 log4j.xml 發送到 相對應的 logstore中去。
log4j.xml 關於SLS部分的配置:
```
<!-- 阿裏雲監控日誌 -->
<appender name="loghub" >
<!--阿裏雲日誌服務信息配置-->
<param name="projectName" value="${projectName}" />
<param name="logstore" value="${logstore}" />
<param name="endpoint" value="${endpoint}" />
<param name="accessKeyId" value="${accessKeyId}"/>
<param name="accessKey" value="${accessKey}"/>
<!-- 填寫監控的dubbo application名稱 -->
<param name="topic" value="${your dubbo application name}"/>
<param name="packageTimeoutInMS" value="3000"/>
<param name="logsCountPerPackage" value="4096"/>
<param name="logsBytesPerPackage" value="5242880"/>
<param name="memPoolSizeInByte" value="1048576000"/>
<param name="ioThreadsCount" value="1"/>
<param name="timeFormat" value="yyyy-MM-dd HH:mm:ss"/>
<param name="timeZone" value="GMT+8"/>
</appender>
<logger name="loghub" additivity="false">
<level value="ERROR" />
<appender-ref ref="loghub" />
</logger>
<root>
<level value="WARN" />
<appender-ref ref="loghub" />
</root>
```
根據上麵的配置,當項目中發生異常時,就可以在日誌服務中就可以收到日誌信息了。
到這裏數據收集的工作就算完成了,下一站,Ali Stream!
阿裏雲流計算配置
現在我們數據到達了流計算這個中樞神經中,在 流計算中 我們在開發平台構建源表,數據源當然是 日誌服務啦。
SLS 源表:
```
CREATE STREAM TABLE monitor_client_log_input (
message STRING,
time STRING ,
level STRING,
`location` STRING,
thread STRING
) WITH (
type='loghub',
endpoint='${endpoint}',
roleArn='${roleArn}',
projectName='${projectName}',
logstore='${logstore}',
allowKeyNotExists=TRUE
);
```
流計算 “數據中樞” 的工作目前非常簡單,收集到數據,重組數據,一邊通知 ONS ,一邊存儲到 RDS 中,所以為了達成這個目的,我們需要構建兩張結果表,分別指向不同的地址。
根據需要通知監控服務端的內容建立 ONS 結果表:
```
CREATE RESULT TABLE monitor_server_log_collect_exception_ons_result (
message STRING,
time STRING ,
level STRING,
`location` STRING,
thread STRING,
`topic` STRING
) WITH (
type='mq',
endpoint='${endpoint}',
topic='${topic}',
producerId='${producerId}',
accessId='${accessId}',
accessKey='${accessKey}',
fieldDelimiter=",",
domainSubGroup="nsaddr4client-internet"
);
```
根據RDS的對應列建立 RDS 結果表:
```
CREATE RESULT TABLE wjb_application_exceptions_rds_result
(
`error_application_name` string,
`error_stack` STRING,
`gmt_create` timestamp,
`status` int
) with (
type = 'rds',
url = '${url}',
username = '${username}',
password = '${password}',
tableName = '${tableName}',
cacheTTL = '120000',
cacheType = 'LRU'
);
```
OK ,表的構建就結束了,下麵我們當數據到來的時候,我們需要將數據插入進表格就可以了。
```
--通知 ONS
INSERT INTO TABLE monitor_server_log_collect_exception_ons_result
SELECT
`message` as message,
`time` as time,
`level` as level,
`location` as `location`,
`thread` as `thread`,
prop_get('__topic__') as `topic`
FROM monitor_client_log_input
WHERE
level = 'ERROR';
--插入 rds 異常表
INSERT INTO TABLE wjb_application_exceptions_rds_result
SELECT
prop_get('__topic__') as error_application_name,
`message` as error_stack,
`time` as gmt_create,
1 as `status`
FROM monitor_client_log_input
WHERE
level = 'ERROR';
```
TIPS:
我們在 日誌服務 中,使用 topic 作為標識符 標示不同的異常服務,所以這個是loghub的係統字段 topic, 在 獲取數據時 使用 prop_get('__topic__')
獲得字段值。使用係統參數,還需要配置下任務參數(右邊欄)。
在任務參數中添加:
`galaxy.input.props.keylist=string,__topic__`
好了,到此為止,這個 “數據中樞” 就構建完了,隻需要點擊 上線,啟動,就OK了,是不是 so easy ?
監控服務端
服務端的工作隻有一件事:
通過 建立 ONS 消費者監聽,實時獲得 異常信息,通知前端,以及響應及時處理機製。這樣,我們就可以比客戶反饋,快一步去處理去處理這些異常。
```java
Properties properties = new Properties();
properties.put(PropertyKeyConst.ConsumerId, MonitorConstants.ONS_CID_EXCEPTION_HANDLER);
properties.put(PropertyKeyConst.AccessKey, MonitorConstants.ACCESS_KEY_ID);
properties.put(PropertyKeyConst.SecretKey,MonitorConstants.ACCESS_KEY_SECRET);
Consumer consumer = ONSFactory.createConsumer(properties);
consumer.subscribe(MonitorConstants.ONS_TOPIC_MONITOR, "*", (message, context) -> {
//啟動異常處理機製
return Action.CommitMessage;
});
consumer.start();
```
成果 -- 先客戶一步
到這裏,異常監控的一條 基於阿裏雲的 “無代碼編程” 鏈路就打通了,在我們的開發過程中,我們基本不需要寫過多的代碼,就可以將我們需要做的事情融入到 網聚寶的係統中,我們隻需要真正關注我們的業務邏輯,我們的 異常監控數據 “騰雲駕霧”,先客戶一步到達我們的眼前,當客戶來因為異常問題找到我們的時候,我們已經找到問題,處理完畢了,減少了交流的成本,讓客戶使用我們產品體驗也得到巨大的提升。
網聚寶服務化的進程還在推進,我們雲上的架構也在逐步完善擴充,根據阿裏雲生態的體係,我們相信可以找到更多適用於我們自己的“最佳實踐“。
上海雲貝網絡科技有限公司
架構師 童煜
最後更新:2017-08-13 22:49:35