検索
ホームページバックエンド開発Golanghystrix-goの使い方と原理を詳しく解説

次のコラム golang チュートリアルでは、bash コマンド解析を実行するための bash 関数をカプセル化する golang について紹介します。

hystrix-goの使い方と原理を詳しく解説

冒頭

今週、内部回路ブレーカーの電流制限パッケージを調べていたところ、それがオープンソース プロジェクトに基づいていることがわかりましたhystrix-go それが実現したので、この記事を作成します。

Hystrix

Hystrix は、Netflex によって開発されたオープン ソース コンポーネントであり、基本的な融合機能を提供します。 Hystrix は、ダウングレード戦略を Command にカプセル化し、runfallback という 2 つのメソッドを提供します。前者は、間の呼び出しなどの通常のロジックを表します。 microservices... 障害が発生した場合、fallback メソッドが実行されて結果が返されるため、動作が保証されていると理解できます。通常のロジックが短期間に頻繁に失敗すると、短絡がトリガーされる可能性があります。つまり、後続のリクエストは run を実行せず、fallback を直接実行します。 Hystrix の詳細については、https://github.com/NETFLIX/Hystrix を参照してください。
hystrix-go が使用されています go 実装の hystrix バージョン、より正確には、簡易バージョン。それは単なる最後の更新ですか、それとも 2018 年の pr、つまり卒業を意味しますか?

なぜこれらのツールが必要なのでしょうか?
たとえば、マイクロサービス ベースの製品ラインでは、以下に示すように、各サービスは独自のビジネスに焦点を当て、対応するサービス インターフェイスを外部に提供するか、外部サービスの特定の論理インターフェイスに依存します。

現在 サービス A であるとします。一部のロジックは サービス C に依存し、 サービス C に依存します。サービス E、現在のマイクロサービスは rpc または http と通信しています。タイムアウトなどの理由で、この時点で サービス C がサービス E の呼び出しに失敗すると想定されます。またはネットワークの変動により、サービス E の過負荷によりシステム E がダウンしました。

呼び出しが失敗した場合、通常は失敗時の再試行などのメカニズムがあります。しかし、もう一度考えてみてください。サービス E がすでに利用できなくなっていると仮定すると、この時点でも新しいコールが生成され続け、コール待機や再試行の失敗が伴い、サービス C からサービス E へのコールの大量のバックログが発生することになります。サービス C のリソースが枯渇すると、サービス C もダウンしてしまい、この悪循環はマイクロサービス システム全体に影響を及ぼし、雪崩現象を引き起こします。

雪崩の原因はこれだけではありませんが、この悪夢が起こらないようにするためには、何らかの対策を講じる必要があります。 hystrix-go は、非常に優れたサーキット ブレーカーとダウングレード対策を提供します。その主なアイデアは、同時実行の最大数 (同時実行の数が設定された同時実行の数よりも大きい場合、インターセプト)、エラー率のパーセンテージ (リクエストの数が設定された同時実行数以上の場合) など、いくつかのしきい値を設定することです。設定されたしきい値、エラー率が設定されたパーセンテージに達する、ヒューズのトリガー)、およびヒューズの試行回復時間など。

使用方法

hystrix-go は非常に簡単に使用でき、Go または Do と呼び出すことができます。 メソッド、Go メソッドだけが非同期です。 Do メソッドは同期です。簡単な例から始めましょう。

_ = hystrix.Do("wuqq", func() error {
        // talk to other services
        _, err := http.Get("https://www.baidu.com/")
        if err != nil {
            fmt.Println("get error:%v",err)
            return err        }
        return nil
    }, func(err error) error {
        fmt.Printf("handle  error:%v\n", err)
        return nil
    })

Do この関数には 3 つのパラメータが必要です。最初のパラメータは commmand 名前です。各名前を独立したサービスとして扱うことができます。2 番目のパラメータはプロセスの通常のロジックですサービスを呼び出す http など、戻りパラメータは err です。 | 処理呼び出しが失敗した場合、保証された操作と呼ばれる 3 番目のパラメーター ロジックが実行されます。サービス エラー率が高すぎてヒューズが開いているため、後続のリクエストもこの関数を直接コールバックします。

ヒューズは設定されたルールに従ってオンまたはオフになるため、もちろん必要な値を設定できます。

hystrix.ConfigureCommand("wuqq", hystrix.CommandConfig{
        Timeout:                int(3 * time.Second),
        MaxConcurrentRequests:  10,
        SleepWindow:            5000,
        RequestVolumeThreshold: 10,
        ErrorPercentThreshold:  30,
    })
    _ = hystrix.Do("wuqq", func() error {
        // talk to other services
        _, err := http.Get("https://www.baidu.com/")
        if err != nil {
            fmt.Println("get error:%v",err)
            return err        }
        return nil
    }, func(err error) error {
        fmt.Printf("handle  error:%v\n", err)
        return nil
    })

上記で設定した値の意味を簡単に説明しましょう:

  • Timeout: 执行 command 的超时时间。
  • MaxConcurrentRequests:command 的最大并发量 。
  • SleepWindow:当熔断器被打开后,SleepWindow 的时间就是控制过多久后去尝试服务是否可用了。
  • RequestVolumeThreshold: 一个统计窗口10秒内请求数量。达到这个请求数量后才去判断是否要开启熔断
  • ErrorPercentThreshold:错误百分比,请求数量大于等于RequestVolumeThreshold并且错误率到达这个百分比后就会启动熔断

当然你不设置的话,那么自动走的默认值。

我们再来看一个简单的例子:

package mainimport (
   "fmt"
 "github.com/afex/hystrix-go/hystrix" "net/http" "time")type Handle struct{}func (h *Handle) ServeHTTP(r http.ResponseWriter, request *http.Request) {
   h.Common(r, request)}func (h *Handle) Common(r http.ResponseWriter, request *http.Request) {
   hystrix.ConfigureCommand("mycommand", hystrix.CommandConfig{
      Timeout:                int(3 * time.Second),
      MaxConcurrentRequests:  10,
      SleepWindow:            5000,
      RequestVolumeThreshold: 20,
      ErrorPercentThreshold:  30,
   })
   msg := "success"

  _ = hystrix.Do("mycommand", func() error {
      _, err := http.Get("https://www.baidu.com")
      if err != nil {
         fmt.Printf("请求失败:%v", err)
         return err  }
      return nil
  }, func(err error) error {
      fmt.Printf("handle  error:%v\n", err)
      msg = "error"
  return nil
  })
   r.Write([]byte(msg))}func main() {
   http.ListenAndServe(":8090", &Handle{})}

我们开启了一个 http 服务,监听端口号 8090,所有请求的处理逻辑都在  Common 方法中,在这个方法中,我们主要是发起一次 http请求,请求成功响应success,如果失败,响应失败原因。

我们再写另一个简单程序,并发 11 次的请求 8090 端口。

package mainimport (
    "fmt"
    "io/ioutil"
    "net/http"
    "sync"
    "time")var client *http.Clientfunc init() {
    tr := &http.Transport{
        MaxIdleConns:    100,
        IdleConnTimeout: 1 * time.Second,
    }
    client = &http.Client{Transport: tr}}type info struct {
    Data interface{} `json:"data"`}func main() {
    var wg sync.WaitGroup    for i := 0; i <p>由于我们配置 <code>MaxConcurrentRequests</code> 为10,那么意味着还有个 g 请求会失败:<br><img src="/static/imghwm/default1.png" data-src="https://img.php.cn/upload/article/000/000/020/a47bae3dcfa1730bb3b1136eddb4f59b-5.png?x-oss-process=image/resize,p_40" class="lazy" alt=""><br>和我们想的一样。</p><p>接着我们把网络断开,并发请求改成10次。再次运行程序并发请求 <code>8090</code> 端口,此时由于网络已关闭,导致请求百度失败:<br><img src="/static/imghwm/default1.png" data-src="https://img.php.cn/upload/article/000/000/020/a47bae3dcfa1730bb3b1136eddb4f59b-6.png?x-oss-process=image/resize,p_40" class="lazy" alt=""><br>接着继续请求:<br><img src="/static/imghwm/default1.png" data-src="https://img.php.cn/upload/article/000/000/020/a47bae3dcfa1730bb3b1136eddb4f59b-7.png?x-oss-process=image/resize,p_40" class="lazy" alt=""><br>熔断器已开启,上面我们配置的<code>RequestVolumeThreshold</code> 和 <code>ErrorPercentThreshold</code> 生效。</p><p>然后我们把网连上,五秒后 (<code>SleepWindow</code>的值)继续并发调用,当前熔断器处于半开的状态,此时请求允许调用依赖,如果成功则关闭,失败则继续开启熔断器。<br><img src="/static/imghwm/default1.png" data-src="https://img.php.cn/upload/article/000/000/020/a47bae3dcfa1730bb3b1136eddb4f59b-8.png?x-oss-process=image/resize,p_40" class="lazy" alt=""><br>可以看到,有一个成功了,那么此时熔断器已关闭,接下来继续运行函数并发调用:<br><img src="/static/imghwm/default1.png" data-src="https://img.php.cn/upload/article/000/000/020/24be5795ca6d697af3d1d7ffdfdafc03-9.png?x-oss-process=image/resize,p_40" class="lazy" alt=""><br>可以看到,10个都已经是正常成功的状态了。</p><p>那么问题来了,为什么最上面的图只有一个是成功的?5秒已经过了,并且当前网络正常,应该是10个请求都成功,但是我们看到的只有一个是成功状态。通过源码我们可以找到答案:<br>具体逻辑在判断当前请求是否可以调用依赖</p><pre class="brush:php;toolbar:false">if !cmd.circuit.AllowRequest() {
            ......
            return
        }
func (circuit *CircuitBreaker) AllowRequest() bool {
    return !circuit.IsOpen() || circuit.allowSingleTest()}func (circuit *CircuitBreaker) allowSingleTest() bool {
    circuit.mutex.RLock()
    defer circuit.mutex.RUnlock()

    now := time.Now().UnixNano()
    openedOrLastTestedTime := atomic.LoadInt64(&circuit.openedOrLastTestedTime)
    if circuit.open && now > openedOrLastTestedTime+getSettings(circuit.Name).SleepWindow.Nanoseconds() {
    /
        swapped := atomic.CompareAndSwapInt64(&circuit.openedOrLastTestedTime, openedOrLastTestedTime, now) //这一句才是关键
        if swapped {
            log.Printf("hystrix-go: allowing single test to possibly close circuit %v", circuit.Name)
        }
        return swapped    }

    return false}

这段代码首先判断了熔断器是否开启,并且当前时间大于 上一次开启熔断器的时间+ SleepWindow 的时间,如果条件都符合的话,更新此熔断器最新的 openedOrLastTestedTime ,是通过  CompareAndSwapInt64 原子操作完成的,意外着必然只会有一个成功。
此时熔断器还是半开的状态,接着如果能拿到令牌,执行run 函数(也就是Do传入的第二个简单封装后的函数),发起 http 请求,如果成功,上报成功状态,关闭熔断器。如果失败,那么熔断器依旧开启。

hystrix-goの使い方と原理を詳しく解説

以上就是大体的流程讲解,下一篇文章将解读核心源码以及进一步当思考。

更多相关技术文章,请访问go语言教程栏目!                                                  

以上がhystrix-goの使い方と原理を詳しく解説の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明
この記事はlearnkuで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。
CとGolang:パフォーマンスが重要な場合CとGolang:パフォーマンスが重要な場合Apr 13, 2025 am 12:11 AM

Cは、ハードウェアリソースと高性能の最適化が必要なシナリオにより適していますが、Golangは迅速な開発と高い並行性処理が必要なシナリオにより適しています。 1.Cの利点は、ハードウェア特性と高い最適化機能に近いものにあります。これは、ゲーム開発などの高性能ニーズに適しています。 2.Golangの利点は、その簡潔な構文と自然な並行性サポートにあり、これは高い並行性サービス開発に適しています。

Golang in Action:実際の例とアプリケーションGolang in Action:実際の例とアプリケーションApr 12, 2025 am 12:11 AM

Golangは実際のアプリケーションに優れており、そのシンプルさ、効率性、並行性で知られています。 1)同時プログラミングはゴルチンとチャネルを通じて実装されます。2)柔軟なコードは、インターフェイスと多型を使用して記述されます。3)ネット/HTTPパッケージを使用したネットワークプログラミングを簡素化、4)効率的な同時クローラーを構築する、5)ツールと最高の実践を通じてデバッグと最適化。

Golang:Goプログラミング言語が説明しましたGolang:Goプログラミング言語が説明しましたApr 10, 2025 am 11:18 AM

GOのコア機能には、ガベージコレクション、静的リンク、並行性サポートが含まれます。 1. GO言語の並行性モデルは、GoroutineとChannelを通じて効率的な同時プログラミングを実現します。 2.インターフェイスと多型は、インターフェイスメソッドを介して実装されているため、異なるタイプを統一された方法で処理できます。 3.基本的な使用法は、関数定義と呼び出しの効率を示しています。 4。高度な使用法では、スライスは動的なサイズ変更の強力な機能を提供します。 5.人種条件などの一般的なエラーは、Getest Raceを通じて検出および解決できます。 6.パフォーマンス最適化Sync.Poolを通じてオブジェクトを再利用して、ゴミ収集圧力を軽減します。

Golangの目的:効率的でスケーラブルなシステムの構築Golangの目的:効率的でスケーラブルなシステムの構築Apr 09, 2025 pm 05:17 PM

GO言語は、効率的でスケーラブルなシステムの構築においてうまく機能します。その利点には次のものがあります。1。高性能:マシンコードにコンパイルされ、速度速度が速い。 2。同時プログラミング:ゴルチンとチャネルを介してマルチタスクを簡素化します。 3。シンプルさ:簡潔な構文、学習コストとメンテナンスコストの削減。 4。クロスプラットフォーム:クロスプラットフォームのコンパイル、簡単な展開をサポートします。

SQLソートのステートメントによる順序の結果がランダムに見えるのはなぜですか?SQLソートのステートメントによる順序の結果がランダムに見えるのはなぜですか?Apr 02, 2025 pm 05:24 PM

SQLクエリの結果の並べ替えについて混乱しています。 SQLを学習する過程で、しばしば混乱する問題に遭遇します。最近、著者は「Mick-SQL Basics」を読んでいます...

テクノロジースタックの収束は、テクノロジースタック選択のプロセスにすぎませんか?テクノロジースタックの収束は、テクノロジースタック選択のプロセスにすぎませんか?Apr 02, 2025 pm 05:21 PM

テクノロジースタックの収束とテクノロジーの選択の関係ソフトウェア開発におけるテクノロジーの選択、テクノロジースタックの選択と管理は非常に重要な問題です。最近、一部の読者が提案しています...

反射比較を使用し、GOの3つの構造の違いを処理する方法は?反射比較を使用し、GOの3つの構造の違いを処理する方法は?Apr 02, 2025 pm 05:15 PM

GO言語で3つの構造を比較および処理する方法。 GOプログラミングでは、2つの構造の違いを比較し、これらの違いを...

See all articles

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

AtomエディタMac版ダウンロード

AtomエディタMac版ダウンロード

最も人気のあるオープンソースエディター

ZendStudio 13.5.1 Mac

ZendStudio 13.5.1 Mac

強力な PHP 統合開発環境

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

WebStorm Mac版

WebStorm Mac版

便利なJavaScript開発ツール

VSCode Windows 64 ビットのダウンロード

VSCode Windows 64 ビットのダウンロード

Microsoft によって発売された無料で強力な IDE エディター