次のチュートリアル コラムでは、Go タイムアウト制御の実装方法を紹介します。
なぜタイムアウト制御が必要なのでしょうか?
リクエスト時間が長すぎます。ユーザーはこのページから離れた可能性があります。サーバーはまだ処理のためにリソースを消費しており、得られる結果は無意味です。
サーバー側の処理時間がかかりすぎる 占有するリソースが多すぎるため、同時実行性が低下し、さらには利用不能になる事故も発生する- #Go タイムアウト制御の必要性
#サーバー側の共通タイムアウト制御
読み取りおよびクライアント側リクエストの作成 (HTTP または RPC リクエストなど)
他のサーバー側リクエストの呼び出し (RPC の呼び出しや DB へのアクセスなど)- 何が行われるかタイムアウト制御がない場合はどうなるでしょうか?
- この記事を簡略化するために、リクエスト関数
を例として取り上げます。これが何に使用されるかは関係ありません。名前が示すように、処理が遅くなる可能性があります。 func hardWork(job interface{}) error {
time.Sleep(time.Minute)
return nil}func requestWork(ctx context.Context, job interface{}) error {
return hardWork(job)}
現時点で、クライアントが見ているのは常に見慣れた写真です
最初のバージョンの実装
読むのをやめて、この関数のタイムアウトを実装する方法を考えてみてください。最初に試してみましょう:
func requestWork(ctx context.Context, job interface{}) error { ctx, cancel := context.WithTimeout(ctx, time.Second*2) defer cancel() done := make(chan error) go func() { done <h2>Let'sテストするために main 関数を作成してください<span class="header-link octicon octicon-link"><pre class="brush:php;toolbar:false">func main() { const total = 1000 var wg sync.WaitGroup wg.Add(total) now := time.Now() for i := 0; i実行して効果を確認してください
➜ go run timeout.go elapsed: 2.005725931s
タイムアウトが発生しました。しかし、これは終わったでしょうか?
ゴルーチンのリーク
main 関数の最後にコード行を追加して、実行されたゴルーチンの数を確認しましょう
time.Sleep(time.Minute*2)fmt.Println("number of goroutines:", runtime.NumGoroutine())
sleep 2 分間待つとすべてのタスクが終了し、現在のゴルーチン数を出力します。実行して結果を見てみましょう➜ go run timeout.go
elapsed: 2.005725931s
number of goroutines: 1001
groutin がリークされています。なぜこれが起こるのか見てみましょう。まず、
requestWork関数は 2 秒のタイムアウト後に終了します。
requestWork関数が終了すると、
done チャネル にはそれを受信するゴルーチンがなくなります。実行done このコード行はスタックして書き込めなくなり、各タイムアウト要求がゴルーチンを占有することになります。これは大きなバグです。リソースが使い果たされると、時間が経過すると、サービス全体が応答しなくなります。 <code>
それではどうやって修正すればいいのでしょうか?実際、これは非常に簡単で、次のように make chan
のときに バッファ サイズ
を 1 に設定するだけです:
done := make(chan error, 1)
This way, done タイムアウトに関係なく、ゴルーチンをブロックせずに書き込むことができます。この時点で、受信するゴルーチンがないチャネルに書き込んでも問題はないのかと疑問に思う人もいるかもしれませんが、Go では、チャネルは一般的なファイル記述子とは異なります。閉じる必要はありません。 <code>close(channel)
は、書き込むものが何もないことを受信者に伝えるためにのみ使用され、他の目的はありません。
このコード行を変更した後、もう一度テストしてみましょう: <pre class="brush:php;toolbar:false">➜ go run timeout.go
elapsed: 2.005655146s
number of goroutines: 1</pre>
Goroutine リークの問題は解決されました。
パニックは捕捉できません
hardWork 関数の実装を panic("oops")
Modify
main## に変更しましょう# 関数と例外をキャッチするコードは次のとおりです: go func() { defer func() { if p := recover(); p != nil { fmt.Println("oops, panic") } }() defer wg.Done() requestWork(context.Background(), "any")}()
この時点で実行すると、パニックをキャプチャできないことがわかります。これは ## 内のゴルーチンで他のパニックが生成されているためです。 #requestWork
goroutine がキャッチできません。 解決策は、処理のために panicChan
を
に追加することです。同様に、panicChan
の
が必要です次のように 1 になります:<pre class="brush:php;toolbar:false">func requestWork(ctx context.Context, job interface{}) error {
ctx, cancel := context.WithTimeout(ctx, time.Second*2)
defer cancel()
done := make(chan error, 1)
panicChan := make(chan interface{}, 1)
go func() {
defer func() {
if p := recover(); p != nil {
panicChan <p>改完就可以在 <code>requestWork</code> 的调用方处理 <code>panic</code> 了。</p><h2>
<span class="header-link octicon octicon-link"></span>超时时长一定对吗?</h2><p>上面的 <code>requestWork</code> 实现忽略了传入的 <code>ctx</code> 参数,如果 <code>ctx</code> 已有超时设置,我们一定要关注此传入的超时是不是小于这里给的2秒,如果小于,就需要用传入的超时,<code>go-zero/core/contextx</code> 已经提供了方法帮我们一行代码搞定,只需修改如下:</p><pre class="brush:php;toolbar:false">ctx, cancel := contextx.ShrinkDeadline(ctx, time.Second*2)</pre><h2>
<span class="header-link octicon octicon-link"></span>Data race</h2><p>这里 <code>requestWork
只是返回了一个 error
参数,如果需要返回多个参数,那么我们就需要注意 data race
,此时可以通过锁来解决,具体实现参考 go-zero/zrpc/internal/serverinterceptors/timeoutinterceptor.go
,这里不做赘述。
完整示例
package mainimport ( "context" "fmt" "runtime" "sync" "time" "github.com/tal-tech/go-zero/core/contextx")func hardWork(job interface{}) error { time.Sleep(time.Second * 10) return nil}func requestWork(ctx context.Context, job interface{}) error { ctx, cancel := contextx.ShrinkDeadline(ctx, time.Second*2) defer cancel() done := make(chan error, 1) panicChan := make(chan interface{}, 1) go func() { defer func() { if p := recover(); p != nil { panicChan <h2> <span class="header-link octicon octicon-link"></span>更多细节</h2><p>请参考 <code>go-zero</code> 源码:</p>
go-zero/core/fx/timeout.go
go-zero/zrpc/internal/clientinterceptors/timeoutinterceptor.go
go-zero/zrpc/internal/serverinterceptors/timeoutinterceptor.go
项目地址
github.com/tal-tech/go-zero
欢迎使用 go-zero
并 star 支持我们!
以上がGoのタイムアウト制御の実装方法を詳しく解説の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

GolangisidealforBuildingsCalables Systemsduetoitsefficiency andConcurrency、Whilepythonexcelsinquickscriptinganddataanalysisduetoitssimplicityand vastecosystem.golang'ssignencouragesclean、readisinediteNeditinesinedinediseNabletinedinedinedisedisedioncourase

Golangは並行性がCよりも優れていますが、Cは生の速度ではGolangよりも優れています。 1)Golangは、GoroutineとChannelを通じて効率的な並行性を達成します。これは、多数の同時タスクの処理に適しています。 2)Cコンパイラの最適化と標準ライブラリを介して、極端な最適化を必要とするアプリケーションに適したハードウェアに近い高性能を提供します。

Golangを選択する理由には、1)高い並行性パフォーマンス、2)静的タイプシステム、3)ガベージ収集メカニズム、4)豊富な標準ライブラリとエコシステムは、効率的で信頼できるソフトウェアを開発するための理想的な選択肢となります。

Golangは迅速な発展と同時シナリオに適しており、Cは極端なパフォーマンスと低レベルの制御が必要なシナリオに適しています。 1)Golangは、ごみ収集と並行機関のメカニズムを通じてパフォーマンスを向上させ、高配列Webサービス開発に適しています。 2)Cは、手動のメモリ管理とコンパイラの最適化を通じて究極のパフォーマンスを実現し、埋め込みシステム開発に適しています。

Golangは、コンピレーション時間と同時処理においてより良いパフォーマンスを発揮しますが、Cはランニング速度とメモリ管理においてより多くの利点があります。 1.Golangの編集速度は速く、迅速な発展に適しています。 2.Cは速く実行され、パフォーマンスクリティカルなアプリケーションに適しています。 3. Golangは、同時処理においてシンプルで効率的で、同時プログラミングに適しています。 4.Cマニュアルメモリ管理により、パフォーマンスが高くなりますが、開発の複雑さが向上します。

WebサービスとシステムプログラミングへのGolangのアプリケーションは、主にそのシンプルさ、効率性、並行性に反映されています。 1)Webサービスでは、Golangは、強力なHTTPライブラリと同時処理機能を介して、高性能WebアプリケーションとAPIの作成をサポートしています。 2)システムプログラミングでは、Golangはハードウェアに近い機能とC言語との互換性を使用して、オペレーティングシステムの開発と組み込みシステムに適しています。

GolangとCには、パフォーマンスの比較に独自の利点と欠点があります。1。ゴーランは、高い並行性と迅速な発展に適していますが、ごみ収集はパフォーマンスに影響を与える可能性があります。 2.Cは、パフォーマンスとハードウェア制御を高くしますが、開発の複雑さが高くなります。選択を行うときは、プロジェクトの要件とチームのスキルを包括的な方法で考慮する必要があります。

Golangは、高性能および同時プログラミングシナリオに適していますが、Pythonは迅速な開発とデータ処理に適しています。 1.Golangは、シンプルさと効率性を強調し、バックエンドサービスとマイクロサービスに適しています。 2。Pythonは、データサイエンスと機械学習に適した簡潔な構文とリッチライブラリで知られています。


ホットAIツール

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

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

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

Video Face Swap
完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

DVWA
Damn Vulnerable Web App (DVWA) は、非常に脆弱な PHP/MySQL Web アプリケーションです。その主な目的は、セキュリティ専門家が法的環境でスキルとツールをテストするのに役立ち、Web 開発者が Web アプリケーションを保護するプロセスをより深く理解できるようにし、教師/生徒が教室環境で Web アプリケーションを教え/学習できるようにすることです。安全。 DVWA の目標は、シンプルでわかりやすいインターフェイスを通じて、さまざまな難易度で最も一般的な Web 脆弱性のいくつかを実践することです。このソフトウェアは、

MantisBT
Mantis は、製品の欠陥追跡を支援するために設計された、導入が簡単な Web ベースの欠陥追跡ツールです。 PHP、MySQL、Web サーバーが必要です。デモおよびホスティング サービスをチェックしてください。

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

mPDF
mPDF は、UTF-8 でエンコードされた HTML から PDF ファイルを生成できる PHP ライブラリです。オリジナルの作者である Ian Back は、Web サイトから「オンザフライ」で PDF ファイルを出力し、さまざまな言語を処理するために mPDF を作成しました。 HTML2FPDF などのオリジナルのスクリプトよりも遅く、Unicode フォントを使用すると生成されるファイルが大きくなりますが、CSS スタイルなどをサポートし、多くの機能強化が施されています。 RTL (アラビア語とヘブライ語) や CJK (中国語、日本語、韓国語) を含むほぼすべての言語をサポートします。ネストされたブロックレベル要素 (P、DIV など) をサポートします。
