摘要:是用于服務監控以及服務降級基礎組件,主要為了解決調用外部接口的時候進行成功率,響應時間,指標的監控,同時在成功率下降到預設的閾值以下的時候自動切斷外部接口的調用,外部接口成功率恢復后自動恢復請求。
meerkat 是用于服務監控以及服務降級基礎組件,主要為了解決調用外部接口的時候進行成功率,響應時間,QPS指標的監控,同時在成功率下降到預設的閾值以下的時候自動切斷外部接口的調用,外部接口成功率恢復后自動恢復請求。本文將對使用方式以及進階特性進行介紹。
項目主頁: https://github.com/ChanningBJ...
為什么要進行監控和熔斷在我們的Java服務中,經常會調用外部的一些接口進行數據的獲取操作,當這些外部接口的成功率比較低的時候會直接影響到服務本身的成功率,因此我們添加了對外部接口調用的成功率和響應時間監控,這樣可以在造成大量用戶影響之前預先發現并解決問題。同時,對于接口中的非關鍵數據,我們采取了更具成功率判斷進行觸發熔斷的方式,當成功率下降到預定的閥值以下的時候自動停止對這個外部接口的訪問以便保證關鍵數據能夠正常提供,當成功率恢復以后自動恢復請求。
meerkat主要功能監控:監控Java內部操作的成功率以及響應時間指標
上報:log文件和Grafhite兩種監控指標上報方式,支持擴展其他的上報方式
熔斷:(可選功能)成功率下降到預設的閾值以下觸發熔斷保護,暫定對外部接口的訪問,成功率恢復以后自動恢復訪問
基本使用 maven定義受監控的操作com.github.channingbj meerkat 1.2
假設我們的服務中需要從HTTP接口查詢一個節目的播放次數,為了防止這個HTTP接口大量超時影響我們自身服務的質量,可以定義一個查詢Command:
public class GetPlayCountCommand extends FusingCommand{ private final Long videoID; public GetPlayCountCommand(Long videoID) { this.videoID = videoID; } protected Optional run() { Long result = 0l; ? ? ? ?// 調用HTTP接口獲取視頻的播放次數信息 ? ? ? ?// 如果調用失敗,返回 null 或者拋出異常,會將這次操作記錄為失敗 ? ? ? ?// 如果ID非法,返回 Optional.absent(),會將這次操作記錄為成功 ? ? ? ?return Optional.fromNullable(result); } }
執行查詢:
//獲取視頻ID為123的視頻的播放次數 GetPlayCountCommand command = new GetPlayCountCommand(123l); Long result = command.execute(); // 執行查詢操作,如果執行失敗或者處于熔斷狀態,返回 null配置監控上報
在服務初始化的時候需要對監控上報進行設置。下面的例子中開啟了監控數據向日志文件的打印
MeterCenter.INSTANCE .enableReporter(new EnablingLogReporter("org.apache.log4j.RollingFileAppender")) .init();查看統計結果
統計結果會以熔斷命令類名為進行分組。例如前面我們定義的 GetPlayCountCommand 類,package name 是 com.test,那么在日志中的輸出將會是這個樣子:
type=GAUGE, name=com.test.GetPlayCountCommand.normal-rate, value=0.0 type=GAUGE, name=com.test.GetPlayCountCommand.success-rate, value=61.0 type=TIMER, name=com.test.GetPlayCountCommand.time, count=25866500, min=0.0, max=0.001, mean=3.963926781047921E-5, stddev=1.951102156677818E-4, median=0.0, p75=0.0, p95=0.0, p98=0.001, p99=0.001, p999=0.001, mean_rate=649806.0831335272, m1=1665370.7316699813, m5=2315813.300713087, m15=2446572.324069477, rate_unit=events/second, duration_unit=milliseconds
監控項 | 含義 |
---|---|
[classname].success-rate | 成功率 |
[classname].time.m1 | QPS |
[classname].time.mean | 平均響應時間 |
[classname].normal-rate | 過去1分鐘內處于正常訪問(非熔斷)的時間比例 |
如果不想使用熔斷功能,只是想監控Java方法調用的耗時和成功率,可以直接使用 OperationMeter 進行實現,只需要在函數調用的前后添加開始和結束的調用即可:
//創建一個操作的計數器 OperationMeter meter = MeterCenter.INSTANCE.getOrCreateMeter(OperationMeterTest.class, OperationMeter.class); //模擬成功率60% for(int k=0; k<100; k++){ Timer.Context context = meter.startOperation(); if(k%10<6){ meter.endOperation(context, OperationMeter.Result.SUCCESS); } else { meter.endOperation(context, OperationMeter.Result.FAILURE); } }
# 開啟熔斷并配置閥值和持續時間
首先創建一個接口,繼承自FusingConfig,用于指定配置文件的加載路徑,同時還可以設定配置文件的刷新時間,具體定義方法請參照 owner 文檔
@Config.Sources("classpath:app_config.properties") @Config.HotReload( value = 1, unit = java.util.concurrent.TimeUnit.MINUTES, type = Config.HotReloadType.ASYNC) public interface APPFusingConfig extends FusingConfig { }
創建查詢Command的時候在構造函數中傳入
public class GetPlayCountCommand extends FusingCommand{ private final Long videoID; public GetPlayCountCommand(Long videoID) { super( APPFusingConfig.class); //設定配置文件 this.videoID = videoID; } protected Optional run() { Long result = 0l; ? ? ? ?// 調用HTTP接口獲取視頻的播放次數信息 ? ? ? ?// 如果調用失敗,返回 null 或者拋出異常,會將這次操作記錄為失敗 ? ? ? ?// 如果ID非法,返回 Optional.absent(),會將這次操作記錄為成功 ? ? ? ?return Optional.fromNullable(result); } }
配置文件內容如下:
監控項 | 含義 | 默認值 |
---|---|---|
fusing.[CommandClassName].mode | 熔斷模式: FORCE_NORMAL-關閉熔斷功能; AUTO_FUSING-自動進入熔斷模式; FORCE_NORMAL-強制進行熔斷 |
FORCE_NORMAL |
fusing.[CommandClassName].duration | 觸發一次熔斷以后持續的時間,支持ms,sec,min 單位。例如 10sec | 50sec |
fusing.[CommandClassName].success_rate_threshold | 觸發熔斷的成功率閥值,降低到這個成功率以下將觸發熔斷,例如0.9表示成功率90% | 0.9 |
配置文件中的 CommandClassName 是每個操作類的名稱,可以為每個操作多帶帶設置上述參數。同時,這個配置文件支持動態加載,樂意通過修改fusing.[CommandClassName].mode 手工觸發或者關閉熔斷。
監控指標上報Graphite我們的服務中使用的是Metric+Graphite+Gafana進行監控數據的采集存儲和展現,下面將介紹如何配置監控數據上報Grafana,關于Graphite+Grafana的配置,可以參考文章:使用graphite和grafana進行應用程序監控
定義配置文件首先定義一個接口,繼承自GraphiteReporterConfig,通過這個接口定義配置文件的加載路徑。配置文件路徑的定義方法請參照 owner 文檔, 下面是一個例子:
@Config.Sources("classpath:config.properties") public interface MyConfig extends GraphiteReporterConfig { }
配置文件中需要定義下列內容:
配置項 | 含義 |
---|---|
meter.reporter.enabled.hosts | 開啟監控上報的服務器列表 |
meter.reporter.perfix | 上報使用的前綴 |
meter.reporter.carbon.host | grafana(carbon-cache) 的 IP 地址,用于存儲監控數據 |
meter.reporter.carbon.port | grafana(carbon-cache) 的端口 |
下面這個例子是在192.168.0.0.1和192.168.0.0.2兩臺服務器上開啟監控數據上報,上報監控指標的前綴是project_name.dc:
meter.reporter.enabled.hosts = 192.168.0.0.1,192.168.0.0.2 meter.reporter.perfix = project_name.dc meter.reporter.carbon.host = hostname.graphite
由于相同機房的不同服務器對外部接口的訪問情況一般比較類似,所以僅選取部分機器上報,也是為了節省資源。僅選擇部分機器上報不影響熔斷效果。
初始化配置上報在服務初始化的時候需要對監控上報進行設置。下面的例子中開啟了監控數據向日志文件的打印,同時通過MyConfig指定的配置文件加載Graphite配置信息。
MeterCenter.INSTANCE .enableReporter(new EnablingLogReporter("org.apache.log4j.RollingFileAppender")) .enableReporter(new EnablingGraphiteReporter(MyConfig.class)) //監控數據上報Grafana .init();查看統計結果
統計結果會以熔斷命令類名為進行分組。例如前面我們定義的 GetPlayCountCommand 類,package name 是 com.test,那么在日志中的輸出將會是這個樣子:
type=GAUGE, name=com.test.GetPlayCountCommand.normal-rate, value=0.0 type=GAUGE, name=com.test.GetPlayCountCommand.success-rate, value=61.0 type=TIMER, name=com.test.GetPlayCountCommand.time, count=25866500, min=0.0, max=0.001, mean=3.963926781047921E-5, stddev=1.951102156677818E-4, median=0.0, p75=0.0, p95=0.0, p98=0.001, p99=0.001, p999=0.001, mean_rate=649806.0831335272, m1=1665370.7316699813, m5=2315813.300713087, m15=2446572.324069477, rate_unit=events/second, duration_unit=milliseconds
監控項 | 含義 |
---|---|
[classname].success-rate | 成功率 |
[classname].time.m1 | QPS |
[classname].time.mean | 平均響應時間 |
[classname].normal-rate | 過去1分鐘內處于正常訪問(非熔斷)的時間比例 |
在Grafanna中可以看到下面的監控圖:
自定義監控上報meerkat使用Metrics進行監控數據的統計,因此可以使用Metrics支持的所有reporter進行上報。添加一種上報的時候,只需要實現 EnablingReporter 并在 MeterCenter 初始化之前進行調用即可。下面是log reporter的實現,可以作為參考
public class EnablingLogReporter implements EnablingReporter { private String loggername; public EnablingLogReporter(String loggername) { this.loggername = loggername; } @Override public void invoke(MetricRegistry metricRegistry, long period, TimeUnit timeUnit) { Slf4jReporter.forRegistry(metricRegistry) .outputTo(LoggerFactory.getLogger(loggername)) .convertRatesTo(java.util.concurrent.TimeUnit.SECONDS) .convertDurationsTo(java.util.concurrent.TimeUnit.MILLISECONDS) .build().start(period, timeUnit); } }
MeterCenter 初始化的時候開啟reporter
MeterCenter.INSTANCE .enableReporter(new EnablingLogReporter("org.apache.log4j.RollingFileAppender")) .init();多實例監控
多實例監控主要是為了解決一個被監控操作的實現類需要根據輸入參數的不同分別進行監控和熔斷的情況,通過定義實例的名稱進行實現。例如獲取視頻播放次數的例子,獲取視頻播放次數的接口對于不同的視頻類型而言請求邏輯是一樣的,所以使用同一個類進行實現;但是對于不同的視頻類型,接口實現的復雜程度不同導致成功率不同,當用戶上傳的視頻的播次接口大量失敗的時候我們不希望同時熔斷電影電視劇這類視頻的播放次數獲取,這時就需要使用多實例這種特性進行監控和熔斷。
下面是一個單實例的實現:
public class GetPlayCountCommand extends FusingCommand{ private final Long videoID; public GetPlayCountCommand(Long videoID) { super( APPFusingConfig.class); this.videoID = videoID; } protected Optional run() { Long result = 0l; // 調用HTTP接口獲取視頻的播放次數信息 // 如果調用失敗,返回 null 或者拋出異常,會將這次操作記錄為失敗 // 如果ID非法,返回 Optional.absent(),會將這次操作記錄為成功 return Optional.fromNullable(result); } }
假設業務上我們可以根據視頻ID判斷視頻類型,可以在類初始化的時候根據類型創建多種監控實例,添加了多實例支持的實現如下:
public class GetPlayCountCommand extends FusingCommand{ private final Long videoID; public GetPlayCountCommand(Long videoID) { super( getVideoType(videoID), APPFusingConfig.class); this.videoID = videoID; } private static String getVideoType(Long videoID){ return "PGC"; //根據videoID進行判斷,返回 "PGC" 或者 "UGC" 這兩個類別 } protected Optional run() { Long result = 0l; // 調用HTTP接口獲取視頻的播放次數信息 // 如果調用失敗,返回 null 或者拋出異常,會將這次操作記錄為失敗 // 如果ID非法,返回 Optional.absent(),會將這次操作記錄為成功 return Optional.fromNullable(result); }
由于每個實例獨享一個監控指標,日志中的監控個結果是這個樣子:
type=GAUGE, name=com.test.GetPlayCountCommand.PGC.normal-rate, value=100.0 type=GAUGE, name=com.test.GetPlayCountCommand.PGC.success-rate, value=100.0 type=GAUGE, name=com.test.GetPlayCountCommand.UGC.normal-rate, value=100.0 type=GAUGE, name=com.test.GetPlayCountCommand.UGC.success-rate, value=60.0 type=TIMER, name=com.test.GetPlayCountCommand.PGC.time, count=100, min=0.0, max=0.509, mean=0.00635, stddev=0.05052135687013958, median=0.001, p75=0.002, p95=0.002, p98=0.003, p99=0.003, p999=0.509, mean_rate=1.6680162586215173, m1=8.691964170141569, m5=16.929634497812284, m15=18.919189378135307, rate_unit=events/second, duration_unit=milliseconds type=TIMER, name=com.test.GetPlayCountCommand.UGC.time, count=100, min=0.0, max=0.027, mean=0.00132, stddev=0.0026939933184772376, median=0.001, p75=0.001, p95=0.002, p98=0.005, p99=0.006, p999=0.027, mean_rate=1.6715904477699361, m1=8.691964170141569, m5=16.929634497812284, m15=18.919189378135307, rate_unit=events/second, duration_unit=milliseconds
相應的,對熔斷閥值以及持續時間的配置也需要明確指出實例的名字:
fusing.GetPlayCountCommand.UGC.mode = AUTO_FUSING fusing.GetPlayCountCommand.UGC.duration = 50sec fusing.GetPlayCountCommand.UGC.success_rate_threshold = 0.9 fusing.GetPlayCountCommand.PGC.mode = AUTO_FUSING fusing.GetPlayCountCommand.PGC.duration = 50sec fusing.GetPlayCountCommand.PGC.success_rate_threshold = 0.9
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/71138.html
摘要:有了分布式數據庫可以使數據庫的性能可以隨著節點增加線性地增加。分布式數據庫最最下面是,是主備的,通過的內核開發能力,我們能夠實現主備切換數據零丟失,所以數據落在這個里面,是非常放心的,哪怕是掛了一個節點,切換完了以后,你的數據也是不會丟的。 此文已由作者劉超授權網易云社區發布。 歡迎訪問網易云社區,了解更多網易技術產品運營經驗 三、微服務化的十個設計要點 微服務有哪些要點呢?第一張圖是...
時間:2017年07月06日星期四說明:本文部分內容均來自慕課網。@慕課網:http://www.imooc.com教學示例源碼:無學習學習源碼:無 第一章:微服務架構在二手交易平臺(轉轉)中的實踐 1-1 微服務架構特點 分享要點-微服務架構 特點 使用原因 演進 通信協議、服務注冊與發現 柔性可用實踐 服務治理 什么是微服務 微服務是一系列小服務的組合 微服務可以單獨運行,獨立的進程 微服務整...
摘要:系統需要支持命令的撤銷。第步計算斷路器的健康度會將成功失敗拒絕超時等信息報告給斷路器,斷路器會維護一組計數器來統計這些數據。第步,當前命令的線程池請求隊列或者信號量被占滿的時候。 斷路由器模式 在分布式架構中,當某個服務單元發生故障之后,通過斷路由器的故障監控(類似熔斷保險絲),向調用方返回一個錯誤響應,而不是長時間的等待。這樣就不會使得線程因調用故障服務被長時間占用不釋放,避免了故障...
閱讀 1173·2021-09-27 13:34
閱讀 981·2021-09-13 10:25
閱讀 511·2019-08-30 15:52
閱讀 3450·2019-08-30 13:48
閱讀 648·2019-08-30 11:07
閱讀 2167·2019-08-29 16:23
閱讀 1993·2019-08-29 13:51
閱讀 2327·2019-08-26 17:42