blog

go-kitマイクロサービス

1.マイクロサービスの定義: 1人のプログラマが設計、実装、デプロイ、保守できるアプリケーションとして理解できます。モノリシックなアプリケーションでは、コンポーネントは言語レベルのメソッドや関数を通じ...

Oct 18, 2020 · 5 min. read
シェア

マイクロサービスの定義:

これは、一人のプログラマが設計、実装、デプロイ、保守できるアプリケーションとして理解できます。モノリシックなアプリケーションでは、コンポーネントは言語レベルのメソッドや関数を通してお互いを呼び出します。対照的に、マイクロサービスベースのアプリケーションは、複数のマシン上で動作する分散システムであり、各サービスインスタンスは異なるプロセスです。したがって、これらのサービスはプロセス間通信を使用して相互作用する必要があります。

サービス間通信の最もシンプルなソリューションは、gRPC、pub/subなどに加えて、HTTPプロトコルに基づいたJSON形式のデータを使用して対話することです。

マイクロサービスにも多くの課題があります:

  • シリアライズ
  • ロギング
  • 融合
  • リクエストトラッキング
  • サービス発見

go-kit

go-kitはgo言語関連のマイクロサービス・ツールキットで、フレームワークではなくツールキットと名乗っています。つまり、go-kit は、開発者が独自のマイクロサービスプロジェクトを自由に構築できるように、インターフェイスを提供するサービスの集合体です。

go-kit

Service

具体的なビジネス処理ロジックはここに置かれ、サービスは一般的にインターフェースとしてモデル化されます:

// StringService provides operations on strings.
type StringService interface {
 Uppercase(string) (string, error)
 Count(string) int
}

このインターフェイスは

type stringService struct{}
func (stringService) Uppercase(s string) (string, error) {
 if s == "" {
 return "", ErrEmpty
 }
 return strings.ToUpper(s), nil
}
func (stringService) Count(s string) int {
 return len(s)
}
// ErrEmpty is returned when input string is empty
var ErrEmpty = errors.New("Empty string")
Endpoint
type Endpoint func(ctx context.Context, request interface{}) (response interface{}, err error)
func makeUppercaseEndpoint(svc StringService) endpoint.Endpoint {
 return func(ctx context.Context, request interface{}) (interface{}, error) {
 req := request.(uppercaseRequest)
 v, err := svc.Uppercase(req.S)
 if err != nil {
 return uppercaseResponse{v, err.Error()}, nil
 }
 return uppercaseResponse{v, ""}, nil
 }
}
Transport

トランスポートの主な目的は、何らかのトランスポートを通じてサービスを外部世界に公開し、これらのサービスを呼び出せるようにすることです。go-kitは、一般的にhttpやrpcなど、すぐに使えるさまざまなトランスポートをサポートしています。

import (
 httptransport "github.com/http"
)
func main() {
 ctx := context.Background()
 svc := stringService{}
 uppercaseHandler := httptransport.NewServer(
 ctx,
 makeUppercaseEndpoint(svc),
 decodeUppercaseRequest,
 encodeResponse,
 )
 
 countHandler := httptransport.NewServer(
 ctx,
 makeCountEndpoint(svc),
 decodeCountRequest,
 encodeResponse,
 )
 
 http.Handle("/uppercase", uppercaseHandler)
 http.Handle("/count", countHandler)
}
func decodeUppercaseRequest(_ context.Context, r *http.Request) (interface{}, error) {
 var request uppercaseRequest
 if err := json.NewDecoder(r.Body).Decode(&request); err != nil {
 return nil, err
 }
 return request, nil
}
func decodeCountRequest(_ context.Context, r *http.Request) (interface{}, error) {
 var request countRequest
 if err := json.NewDecoder(r.Body).Decode(&request); err != nil {
 return nil, err
 }
 return request, nil
}
 func encodeResponse(_ context.Context, w http.ResponseWriter, response interface{}) error {
 return json.NewEncoder(w).Encode(response)
}
リクエスト追跡

go-kitには、opentracingとzipkinの2種類のリンクトレースがあります。

ZIPKINについて簡単にご紹介します:

zipkinは時間データの収集を支援し、分散システムの時間データの収集とクエリの機能を提供します:

ZipkinはCollector、Storage、API、UIの合計4つのコンポーネントで構成され、Reporterはアプリケーションシステムによって提供され、データを収集します:

  • トラッカーをアプリケーションに組み込み、Spanを使用してアプリケーションのアクションに関するタイミングとメタデータ情報を記録します;
  • ReporterはSpanをZipkinのデータコレクターであるCollectorに送信します;
  • Collectorは、Storageコンポーネントを通じてデータベースにデータを保存します;
  • UIコンポーネントはトラッキングデータを照会し、APIインターフェースを通じて表示します;

ZIPKINはトレース構造を通してリクエストのトレースを表現します。リクエストはいくつかのサービスによって処理され、各サービスはスパンを生成し、同じリクエストのスパン間の関連があり、それはUIコンポーネントでツリーとして表示されます:

API

マイクロサービスでは、APIがサービスと外部とのほぼ唯一のインタラクションチャネルであり、APIの安定性・信頼性は無視できない部分になってきています。APIのリアルタイムの稼働状況を把握し、過去のデータ分析を通じて、どのAPIがパフォーマンスのボトルネックになっているかを把握し、後の最適化につなげることが必要です。したがって、システムが優れたサービスを提供することを保証するために、マイクロサービス・フレームワークの大部分はAPIモニタリング・コンポーネントとも統合されています。プロメテウス(Prometheus)は、オープンソースのシステム監視アラームフレームワークのセットです。新世代の監視フレームワークとして、以下の特徴があります:

  • カウンター、ゲージ、ヒストグラム、サマリーなどの強力な多次元データモデルを提供します。
  • 強力で柔軟なクエリ文により、時系列データに対するクエリや集計操作を簡単に実行できます;
  • 管理が簡単で効率的;
  • プルモード、プッシュゲートウェイを提供し、時系列データの収集を実現します;
  • Grafana、Web UI、APIクライアントなど、複数のビジュアルグラフィカルインターフェースをサポートします;
  • アラームルール管理、アラーム検知、アラームプッシュ機能

main.goを修正して、メトリクス・コレクション・オブジェクトを作成します。

count := kitprometheus.NewCounterFrom(stdprometheus.CounterOpts{
	Namespace: "51world",
	Subsystem: "stringService",
	Name: "request_count",
	Help: "Number of requests received.",
}, fieldKeys)
latency := kitprometheus.NewSummaryFrom(stdprometheus.SummaryOpts{
	Namespace: "51world",
	Subsystem: "stringService",
	Name: "request_latency_seconds",
	Help: "Total duration of requests in seconds.",
}, fieldKeys)
Read next

VAVR:Javaエクスペリエンスを破壊する

ご存知のように、Java8は関数型プログラミングをある程度サポートしていますが、標準ライブラリによって提供される関数型APIはあまり完全でフレンドリーではありません。 より良い関数型プログラミングを行うためには、サードパーティのライブラリを使用する必要がありますが、VAVR はこの点で最も優れており、コードの量を効果的に減らし、コードの質を向上させることができます。 VAVR は無名なライブラリではなく、その前身は ...

Oct 18, 2020 · 16 min read