Tunny เป็นไลบรารี Golang สำหรับสร้างและการจัดการกับ goroutine pools ซึ่งช่วยให้คุณจำกัดงานจากจำนวน goroutines ด้วย APIs ที่เป็นการทำงานแบบเสถียร
เมื่องานของคุณมาจากจำนวนของแหล่งที่มีการทำงานแบบไม่สม่ำเสมอ แต่ความสามารถในการประมวลผลแบบพร้อมกันของคุณจำกัดอยู่ ก็จะมีการใช้ fixed goroutine pool ที่มีประโยชน์มาก ตัวอย่างเช่น เมื่อประมวลกิจกรรม HTTP request ที่ใช้ CPU-intensive คุณสามารถสร้าง pool ที่มีขนาดเท่ากับจำนวนของ CPU
การติดตั้ง
go get github.com/Jeffail/tunny
หรือหากใช้ dep:
dep ensure -add github.com/Jeffail/tunny
การใช้
สำหรับกรณีส่วนใหญ่ งานที่มีน้ำหนักมากของคุณสามารถแสดงได้ด้วย func()
ที่ง่าย ในกรณีนี้คุณสามารถใช้ NewFunc
ให้ดูการใช้ตัวอย่างของเราโดยใช้ HTTP requests ไปยังการนับ CPU:
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
// งาน CPU-intensive ที่ใช้ payload
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, "Internal error", http.StatusInternalServerError)
}
defer r.Body.Close()
// นำงานเข้าไปใน pool ของเรา การเรียกใช้นี้จะเป็นการทำงานแบบเสถียรและจะ block จนกว่างานจะเสร็จสิ้น
result := pool.Process(input)
w.Write(result.([]byte))
})
http.ListenAndServe(":8080", nil)
}
Tunny ยังรองรับการตั้งเวลาหมดเวลา คุณสามารถแทนที่การเรียกใช้ Process
ด้านบนด้วยโค้ดต่อไปนี้:
result, err := pool.ProcessTimed(input, time.Second*5)
if err == tunny.ErrJobTimedOut {
http.Error(w, "Request timed out", http.StatusRequestTimeout)
}
คุณสามารถใช้ context ของคำขอ (หรือ context อื่น) เพื่อจัดการเวลาหมดเวลา และเวลาตามกำหนด Simply แทน Process
ด้วยโค้ดต่อไปนี้:
result, err := pool.ProcessCtx(r.Context(), input)
if err == context.DeadlineExceeded {
http.Error(w, "Request timed out", http.StatusRequestTimeout)
}
การปรับแต่งขนาดของ Pool
คุณสามารถใช้ SetSize(int)
เพื่อเปลี่ยนขนาดของ Tunny pool ได้ทุกเมื่อ
pool.SetSize(10) // 10 goroutines
pool.SetSize(100) // 100 goroutines
นี้ปลอดภัยแม้ว่า goroutines ที่เหลืออยู่จะยังคงประมวลผล
การทำงานของ Goroutine ที่มีสตรีมของการทำงาน
บางครั้ง แต่ละ goroutine ใน Tunny pool ต้องมีสถานะการจัดการของตัวเอง ในกรณีนี้ คุณควรสร้าง tunny.Worker
ซึ่งรวมถึงการเรียกรอให้สิ้นสุด ห้าม (หากงานหมดเวลาและไม่ได้ต้องการ), และบล็อกการจัดสรรงานที่ต่อมาจนกว่าเงื่อนไขบางประการกำหนดจะถูกตอบสนอง
เมื่อสร้าง pool ด้วยชนิด Worker
คุณต้องให้ค่าสร้างเป็นแบบกำหนดเองของคุณ:
pool := tunny.New(poolSize, func() Worker {
// งานการจัดสร้างสำหรับแต่ละ goroutine ที่นี่
return newCustomWorker()
})
ดีอย่างนั้น Tunny สามารถทำความสะอาดการสร้างและการทำลายของชนิด Worker
เมื่อขนาดของ pool มีการเปลี่ยนแปลง
การเรียงลำดับ
งานที่ค้างคงไว้ (backlogged jobs) ไม่สามารถคาดการณ์ได้ว่าจะถูกประมวลผลตามลำดับ เนื่องจากการสร้างปัจจุบันของช่องและการเลือกบล็อค ลำดับงานที่ค้างไว้จะถูกประมวลตาม FIFO queue แต่พฤติกรรมนี้ไม่ได้อยู่ในสเปคและไม่ควรให้การพฤติกรรมลำดับขึ้นอยู่กับมัน