تانی یک کتابخانه Golang برای ایجاد و مدیریت استخر goroutine است، که به شما اجازه می دهد که با استفاده از رابط های همگام، کار از هر تعداد goroutine را محدود کنید و مدیریت کنید.
وقتی که کارهای شما از تعدادی منابع ناهمزمان می آید اما قابلیت پردازش موازی شما محدود است، یک استخر goroutine ثابت بسیار مفید است. به عنوان مثال، هنگام پردازش کارهای درخواست HTTP با مصرف CPU-منفی، می توانید یک استخر با اندازه تعداد پردازنده ها ایجاد کنید.
## نصب
```shell
go get github.com/Jeffail/tunny
به طور جایگزین، با استفاده از dep:
dep ensure -add github.com/Jeffail/tunny
استفاده
به اکثر موارد، کارهای داغ شما می تواند توسط یک func()
ساده نشان داده شود، در این صورت می توانید از NewFunc
استفاده کنید. بیایید ببینیم چگونه می توانیم از مثال ما از درخواست های HTTP به تعداد پردازنده ها استفاده کنیم:
package main
import (
"io/ioutil"
"net/http"
"runtime"
"github.com/Jeffail/tunny"
)
func main() {
numCPUs := runtime.NumCPU()
pool := tunny.NewFunc(numCPUs, func(payload interface{}) interface{} {
var result []byte
// TODO: انجام عملیات مصرف CPU-منفی با استفاده از داده ورودی
return result
})
defer pool.Close()
http.HandleFunc("/work", func(w http.ResponseWriter, r *http.Request) {
input, err := ioutil.ReadAll(r.Body)
if err != nil {
http.Error(w, "خطای داخلی", http.StatusInternalServerError)
}
defer r.Body.Close()
// وارد کردن این کار به استخر ما. این تماس همگام است و تا زمان اتمام کار بلاک می کند.
result := pool.Process(input)
w.Write(result.([]byte))
})
http.ListenAndServe(":8080", nil)
}
تانی همچنین از زمانبندی پشتیبانی می کند. می توانید فراخوانی Process
فوق را با کد زیر جایگزین کنید:
result, err := pool.ProcessTimed(input, time.Second*5)
if err == tunny.ErrJobTimedOut {
http.Error(w, "زمان درخواست تمام شد", http.StatusRequestTimeout)
}
همچنین می توانید از متن درخواست (یا هر متن دیگر) برای اداره زمانبندی و مهلت ها استفاده کنید. به سادگی فراخوانی Process
را با کد زیر جایگزین کنید:
result, err := pool.ProcessCtx(r.Context(), input)
if err == context.DeadlineExceeded {
http.Error(w, "زمان درخواست تمام شد", http.StatusRequestTimeout)
}
تغییر اندازه استخر
می توانید از SetSize(int)
برای تغییر اندازه استخر تانی در هر زمان استفاده کنید.
pool.SetSize(10) // 10 goroutine
pool.SetSize(100) // 100 goroutine
این کار حتی اگر goroutine های دیگری همچنان در حال پردازش باشند، امن است.
Goroutine از دسترسی
گاهی اوقات، هر goroutine در استخر تانی به وضعیت مدیریت خود نیاز دارد. در این صورت باید tunny.Worker
را پیاده سازی کنید، که شامل فراخوانی های پایان دادن، وقفه (اگر یک کار زمان بندی شده است و دیگر نیازی نیست) و مسدود کردن تخصیص کار بعدی تا زمانی که یک شرط خاص برآورده شود، است.
وقتی یک استخر با نوع Worker
ایجاد می کنید، باید یک سازنده را برای تولید پیاده سازی سفارشی خودتان ارائه دهید:
pool := tunny.New(poolSize, func() Worker {
// TODO: اختصاص وضعیت برای هر goroutine در اینجا
return newCustomWorker()
})
به این ترتیب، تانی می تواند ساخت و از بین بردن نوع Worker
را هنگام تغییر اندازه استخر انجام دهد.
ترتیب
از اینجا که پشتیبانی از ترتیب درجه حیاتی نیست. به دلیل پیاده سازی فعلی کانال ها و بلوک های انتخاب، پشته های کار برگردانده شده به عنوان یک صف FIFO پردازش خواهند شد. با این حال، این رفتار بخشی از مشخصات نیست و باید بر روی آن حساب نکنید.