Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to understand the concurrent component ​ supported by go-zero to goroutine in Go

2025-01-18 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/03 Report--

This article focuses on "how to understand go-zero 's concurrent components supported by goroutine in Go". Interested friends may wish to take a look. The method introduced in this paper is simple, fast and practical. Let's let the editor take you to learn how to understand the concurrent components supported by goroutine in Go by go-zero.

Threading

Although go func () is already convenient, there are several problems:

If the co-program exits abnormally, the exception stack cannot be traced.

When an abnormal request triggers panic, fault isolation should be done instead of the whole process exiting, so it is easy to be attacked.

Let's take a look at what additional options the core/threading package offers:

Func GoSafe (fn func ()) {go RunSafe (fn)} func RunSafe (fn func ()) {defer rescue.Recover () fn ()} func Recover (cleanups... func ()) {for _, cleanup: = range cleanups {cleanup ()} if p: = recover (); p! = nil {logx.ErrorStack (p)} GoSafe

Threading.GoSafe () helps you solve this problem. Developers can pass in the logic that they need to complete in the process of collaboration in the form of closures, from the internal go func () of GoSafe ().

When the developer's function exits with an exception, the exception stack is printed in Recover () so that the developer can quickly determine the point where the exception occurred and the call stack.

NewWorkerGroup

Let's look at the second one: WaitGroup. Daily development, in fact, WaitGroup has nothing to say, you need N collaborative processes: wg.Add (N), waiting for all collaborative processes to complete the task: wg.Wait (), while completing a task requires manual wg.Done ().

As you can see, when the task starts-> ends-> waits, the whole process requires the developer to pay attention to the status of the task and then modify it manually.

NewWorkerGroup lightens the burden on developers, and developers only need to pay attention to:

Task logic [function]

Number of tasks [workers]

Then start WorkerGroup.Start (), and the corresponding number of tasks will start:

Func (wg WorkerGroup) Start () {/ / packaged sync.WaitGroup group: = NewRoutineGroup () for I: = 0; I

< wg.workers; i++ { // 内部维护了 wg.Add(1) wg.Done() // 同时也是 goroutine 安全模式下进行的 group.RunSafe(wg.job) } group.Wait()} worker 的状态会自动管理,可以用来固定数量的 worker 来处理消息队列的任务,用法如下: func main() { group := NewWorkerGroup(func() { // process tasks }, runtime.NumCPU()) group.Start()}Pool 这里的 Pool 不是 sync.Pool。sync.Pool 有个不方便的地方是它池化的对象可能会被垃圾回收掉,这个就让开发者疑惑了,不知道自己创建并存入的对象什么时候就没了。 go-zero 中的 pool: pool 中的对象会根据使用时间做懒销毁; 使用 cond 做对象消费和生产的通知以及阻塞; 开发者可以自定义自己的生产函数,销毁函数; 那我来看看生产对象,和消费对象在 pool 中时怎么实现的: func (p *Pool) Get() interface{} { // 调用 cond.Wait 时必须要持有c.L的锁 p.lock.Lock() defer p.lock.Unlock() for { // 1. pool中对象池是一个用链表连接的nodelist if p.head != nil { head := p.head p.head = head.next // 1.1 如果当前节点:当前时间 >

= Last usage time + maximum survival time of object if p.maxAge > 0 & & head.lastUsed+p.maxAge

< timex.Now() { p.created-- // 说明当前节点已经过期了 ->

Destroy the object corresponding to the node, and then continue to find the next node / / [⚠️: not destroy the node. Instead, destroy the object corresponding to the node] p.destroy (head.item) continue} else {return head.item} / / 2. Object pool is lazily loaded Create the object linked list if p.created < p.limit {p.createdlists + / / passed in by the developer himself when get: production function return p.create ()} p.cond.Wait ()}} func (P * Pool) Put (x interface {}) {if x = = nil {return} / / mutually exclusive access nodelist p.lock.Lock () defer p.lock.Unlock () p.head = & node {item: X Next: p.head, lastUsed: timex.Now (),} / / put into head Notify other get collaborators [critical] p.cond.Signal ()}

This is the use of Cond by go-zero. It can be compared to the producer-consumer model, but instead of using channel for communication here, we use Cond instead. Here are a few features:

Cond is associated with a Locker that can be used to protect against related dependency changes.

Cond can support both Signal and Broadcast methods, while Channel can only support both.

At this point, I believe you have a deeper understanding of "how to understand go-zero 's concurrent components supported by goroutine in Go". You might as well do it in practice. Here is the website, more related content can enter the relevant channels to inquire, follow us, continue to learn!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report