SpringBoot +ダボ統合ELK戦闘

序文

すべてに沿って、ログが開発・運用・保守手順で私たちといつも一緒です。システムは、多くの場合、Xshellを介してサーバに接続され、バグが出現すると、ログファイル、調査と問題の発生源の少しに移動します。

インターネットの急速な発展に伴い、私たちのシステムはますます大。道徐々に問題のいくつかを強調して問題のトラブルシューティングにログファイルを解析するために肉眼に頼っするには:

  • クラスタ環境では、分散型、数は、サーバの数百または数千に達する可能性があり、どのように正確な位置決め?
  • お互いコンテキスト情報サービスを検索する方法、異常に基づくマイクロサービスアーキテクチャ、?
  • ログファイルの継続的な増加に伴い、サーバーを直接開くことができない恥ずかしさに直面する可能性があります。
  • テキスト検索では、多次元の問い合わせ遅すぎることはできないです

これらの問題に直面し、我々は収集、管理、アクセスを統一し、すべてのサーバー・ノードにログオン、集中ログ管理を必要としています。

今日、私たちの手段が使用することですElastic Stack、それらを解決するために。

まず、弾性スタックは何ですか?

おそらく誰か弾性が少し奇妙に感じ、それが弾性スタックがELKスタックの置換である、事前に存在ELKです。

弾性スタックは、4つのオープンソース・プロジェクトに対応しています。

  • ビート

様々なタイプのデータを収集するための責任があるインターネットデータコレクタ、複数の使い捨てセットを打ちます。このようなファイルは、システム監視、Windowsイベントログなど。

  • Logstash

Logstashサーバ側のデータ処理パイプラインは、同時に複数のソース、データ変換からデータを収集することが可能です。はい、あなたはまた、データを変換することができ、データを収集することができます。非構造化データは、彼の書式設定に優しいタイプのフィルターによって収集します。

  • Elasticsearch

ElasticsearchはJSONベースの分散検索・分析エンジンです。データの集中格納を担当された弾性積層体のコア、など。ビートは、我々が収集した上記データを使用し、Logstash変換を通過した後、それはElasticsearch格納することができます。

  • Kibana

最後に、あなたができる、Kibanaにより可視化し、そのElasticsearchのデータの。

本稿の例としては、あるSpringBoot+Dubbo組み合わせ、マイクロサービスアーキテクチャElastic Stackのログを統合します。アーキテクチャ次のように:

注意,阅读本文需要了解ELK组件的基本概念和安装。本文不涉及安装和基本配置过程,重点是如何与项目集成,达成上面的需求。

第二に、収集、変換

1、FileBeat

SpringBootプロジェクトでは、まず、Logbackを設定し、ログファイルの場所を決定します。

<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
	<file>${user.dir}/logs/order.log</file>
	<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
	    <fileNamePattern>${user.dir}/logs/order.%d{yyyy-MM-dd}.log</fileNamePattern>
	    <maxHistory>7</maxHistory>
	</rollingPolicy>
	<encoder>
	    <pattern></pattern>
	</encoder>
</appender>
复制代码

Filebeatこれは、転送と要約ログファイルの軽量な方法を提供します。

そこで、我々は指示する必要がありFileBeat、ログファイルの場所、どこでコンテンツを転送する方法を。

以下に示すように、我々は配置されているFileBeat読み取るためにusr/local/logs、パス内のすべてのログファイルを。

- type: log
  # Change to true to enable this input configuration.
  enabled: true
  # Paths that should be crawled and fetched. Glob based paths.
  paths:
    - /usr/local/logs/*.log
复制代码

その後、言うFileBeatに転送し、収集したデータをLogstash

#----------------------------- Logstash output --------------------------------
output.logstash:
  # The Logstash hosts
  hosts: ["192.168.159.128:5044"]
复制代码

さらに、FileBeat時にデータ収集ファイル、行の読み取りによってライン。しかし、FileBeat収集されたファイルは、全体のテキストメッセージの複数行を含めることができます。

例えば、オープンラップ意図的なフレームで:

2019-10-29 20:36:04.427  INFO  org.apache.dubbo.spring.boot.context.event.WelcomeLogoApplicationListener 
 :: Dubbo Spring Boot (v2.7.1) : https://github.com/apache/incubator-dubbo-spring-boot-project
 :: Dubbo (v2.7.1) : https://github.com/apache/incubator-dubbo
 :: Discuss group : [email protected]
复制代码

またはJava例外スタック情報:

2019-10-29 21:30:59.849 INFO com.viewscenes.order.controller.OrderController http-nio-8011-exec-2 开始获取数组内容...
java.lang.IndexOutOfBoundsException: Index: 3, Size: 0
	at java.util.ArrayList.rangeCheck(ArrayList.java:657)
	at java.util.ArrayList.get(ArrayList.java:433)
复制代码

したがって、我々はまた、設定する必要がありmultiline、単一のイベントの一部である行を指定します。

multiline.pattern 正規表現パターンマッチングを指定します。

multiline.negate ネガティブモードかどうかを定義します。

multiline.match 後または前に設定されたイベントにラインの組み合わせを一致させる方法。

ラオの口は、私たちがコンフィギュレーションのセットを見て、聞こえることがあります。

# The regexp Pattern that has to be matched. The example pattern matches all lines starting with [
multiline.pattern: '^\<|^[[:space:]]|^[[:space:]]+(at|\.{3})\b|^java.'

# Defines if the pattern set under pattern should be negated or not. Default is false.
multiline.negate: false

# Match can be set to "after" or "before". It is used to define if lines should be append to a pattern
# that was (not) matched before or after or as long as a pattern is not matched based on negate.
# Note: After is the equivalent to previous and before is the equivalent to to next in Logstash
multiline.match: after
复制代码

それが言うプロファイルは、テキストがある場合ということである< 或 空格 或空格+at+包路径 或 java.ライン上のフォローアップとしてではなく、新しい行としてこの行の内容は、その後、最初に。

Javaの例外スタック情報の上に定期的に沿ったものです。だから、FileBeat意志

java.lang.IndexOutOfBoundsException: Index: 3, Size: 0
	at java.util.ArrayList.rangeCheck(ArrayList.java:657)
	at java.util.ArrayList.get(ArrayList.java:433)
复制代码

これらのコンテンツを开始获取数组内容...、それの一部。

2、Logstash

ではLogback、中央、我々はログを印刷し、一般的には、ログレベル、クラスパス、スレッド名やその他の情報の実装をもたらすでしょう。

重要なメッセージは、私たちがいることであるELKあなたが上記の条件やる統計や正確なクエリを分離するかどうか、時間のログを表示しますか?

そう、必要が使用する場合はLogstash、フィルタを、フィールドという名前の構築物の構造を特定するために、個々のイベントを解決することができ、かつ共通のフォーマットに変換します。

さて、今回は、ログの出力形式を設定するプロジェクト、で私たちをご覧ください。

例えば、我々はJSON形式に最も精通しています。初見のLogback設定:

<pattern>
    {"log_time":"%d{yyyy-MM-dd HH:mm:ss.SSS}","level":"%level","logger":"%logger","thread":"%thread","msg":"%m"}
</pattern>
复制代码

はい、Logstashフィルタは単にJSONの解析プラグインを持っています。私たちは、それを構成することができます。

input{ 
   stdin{}
}
filter{
   json {
      source => "message"
   }
}
output {
  stdout {}
}
复制代码

そうJSONパーサーを使用してデータをフォーマットされた構成。我々は、この行を入力します。

{
    "log_time":"2019-10-29 21:45:12.821",
    "level":"INFO",
    "logger":"com.viewscenes.order.controller.OrderController",
    "thread":"http-nio-8011-exec-1",
    "msg":"接收到订单数据."
}
复制代码

Logstashフォーマット後のコンテンツを返します。

しかし、JSONパーサーと我々はログMSGフィールド自体は、おそらくJSONデータ形式で印刷するので、適用されません。

例えば:

{
    "log_time":"2019-10-29 21:57:38.008",
    "level":"INFO",
    "logger":"com.viewscenes.order.controller.OrderController",
    "thread":"http-nio-8011-exec-1",
    "msg":"接收到订单数据.{"amount":1000.0,"commodityCode":"MK66923","count":5,"id":1,"orderNo":"1001"}"
}
复制代码

今回はJSONパーサーエラー。どのようにそれを行うには?

Logstashこれは、フィルタプラグインライブラリの富を持っている、またはあなたが肯定的に自信を持っている場合、あなたも一致する式を書くことができます。

私たちがしたようLogbackな構成が好き、私たちのログ形式のコンテンツは、JSON形式またはその他の形式か、すでに決定しています。

だから、私は今日、別のをお勧めします:解剖します。

解剖フィルタは、分割操作です。デリミタは、文字列全体異なる操作の従来の分解能が印加され、この操作は、文字列値の区切り文字のセットに適用されます。正規表現を使用しないで解剖し、非常に高速。

たとえば、著者はここで|区切り文字として。

input{ 
   stdin{}
}
filter{  
   dissect {
      mapping => {
	  "message" => "%{log_time}|%{level}|%{logger}|%{thread}|%{msg}"
     }
   }   
}
output {
  stdout {}
}
复制代码

そして、Logbackこの構成のログ形式に:

<pattern>
    %d{yyyy-MM-dd HH:mm:ss.SSS}|%level|%logger|%thread|%m%n
</pattern>
复制代码

最後に、あなたはまた、右の結果を得ることができます:

これは、データの収集とフォーマット変換に関して完了しています。もちろん、上記の構成は、コンソール入力、出力されます。

のは、8人の子供の設定を見てみましょう、それはからであるFileBeat経て、データの収集dissectデータを変換するための出力フォーマットelasticsearch

input {
  beats {
    port => 5044
  }
}
filter{
   dissect {
      mapping => {
        "message" => "%{log_time}|%{level}|%{logger}|%{thread}|%{msg}"
     }
   }
   date{
      match => ["log_time", "yyyy-MM-dd HH:mm:ss.SSS"]
      target => "@timestamp"
   }
}
output {
  elasticsearch {
    hosts => ["192.168.216.128:9200"]
    index => "logs-%{+YYYY.MM.dd}"
  }
}
复制代码

驚くことではない、そして、我々はKibanaを表示するには、ログインしてブラウザを開くことができます。例えば、我々はのためのログレベルを表示DEBUGエントリを:

第三に、トラック

我々は、フロントでの注文要求を送信、想像してみてください。バックエンドシステムは、マイクロサービスアーキテクチャである場合は、在庫システム、クーポンシステム、会計システム、注文システム、及び他のサービスを介してもよいです。これを呼び出すリンクを追跡する方法、それを要求しますか?

1、MDC機構

まず第一に、我々は、MDCのメカニズムを調べる必要があります。

MDC - マップされた診断コンテキストは、基本的にロギングフレームワークマッピングによって維持します。前記アプリケーション・コードは、ログメッセージに挿入され、フレームは、ロギングで作ることができる、キーと値のペアを提供します。

要するに、我々が使用するMDC.PUT(key,value)、それがLogback自動的にログにこの値を印刷することができます。

SpringBoot真ん中、我々は最初に書くことができるHandlerInterceptorすべてのリクエストが1を生成するためのインターセプトをtraceId

@Component
public class TraceIdInterceptor implements HandlerInterceptor {

    Snowflake snowflake = new Snowflake(1,0);

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler){
        MDC.put("traceId",snowflake.nextIdStr());
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView){
        MDC.remove("traceId");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex){}
}
复制代码

そして、Logbackそれを設定し、これが作るtraceIdログメッセージに表示されます。

<pattern>
    %d{yyyy-MM-dd HH:mm:ss.SSS}|%level|%logger|%thread|%X{traceId}|%m%n
</pattern>
复制代码

2、ダボフィルター

もう一つの問題は、マイクロ・サービス・アーキテクチャでは、我々はこのましょうかということであるtraceIdラウンドパススルーを。

おなじみのDubbo友人は暗黙のパラメータを考えるかもしれません。はい、私達はちょうど完了するためにそれを使用してtraceId転送を。

@Activate(group = {Constants.PROVIDER, Constants.CONSUMER}, order = 99)
public class TraceIdFilter implements Filter {
    @Override
    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {

        String tid = MDC.get("traceId");
        String rpcTid = RpcContext.getContext().getAttachment("traceId");

        boolean bind = false;
        if (tid != null) {
            RpcContext.getContext().setAttachment("traceId", tid);
        } else {
            if (rpcTid != null) {
                MDC.put("traceId",rpcTid);
                bind = true;
            }
        }
        try{
            return invoker.invoke(invocation);
        }finally {
            if (bind){
                MDC.remove("traceId");
            }
        }
    }
}
复制代码

終了このように、我々は最初の要求にそれをログに記録し、すべての情報を見て幸せになります。例えば、二つのシステムの以下のログ要求、サービスの注文や在庫サービス。

IVの概要

本論文では紹介しElastic Stack、基本的な概念を。そしてを通じてSpringBoot+Dubbo集中管理ログを行う方法を示していたプロジェクト、追跡します。

実際には、Kibanaより多くの分析や統計関数を持ちます。だから、その役割は、ロギングに限定されるものではありません。

また、Elastic Stackパフォーマンスは非常に良いです。仮想マシン内の著者は、100の+1万ユーザデータを記録し、インデックスサイズは1.1G、クエリと統計スピード劣らずです。

おすすめ

転載: juejin.im/post/5db57e856fb9a020664fc00e