当前位置:网站首页>Context of go concurrency mode
Context of go concurrency mode
2022-06-13 00:16:00 【Ethan97】
brief introduction
stay Go Language implementation of the server , Each incoming request is given a new go Process processing . The request processor often turns on additional go The coroutine accesses the backend , Like databases 、RPC service . These are created to serve the same request go A coroutine usually needs to access certain values of the request scope , For example, the identity of the end user 、 jurisdiction token、 Request deadline .context Packages that allow the same request to be processed go It is more convenient to transfer values between processes . It can also process a set of requests go The cancellation signal is passed between processes 、 By the time deadline.
Context
Context The source of the interface is as follows :
// Context Methods of can be called concurrently
type Context interface {
// Deadline Return to the Context Time to be cancelled
Deadline() (deadline time.Time, ok bool)
// If it's time to Context Cancelled or timed out .Done A closed channel will be returned
Done() <-chan struct{
}
// Err Return to why Context Be cancelled
Err() error
// Value Return and key Related key values
Value(key interface{
}) interface{
}
}
Why can you only check whether to cancel , And can not take the initiative to cancel :
One Context No, Cancel Method , also Done The channel returned by the method is one-way , receive calls only , Can't send . This is because A method of receiving a cancellation signal is usually not responsible for sending a cancellation signal . such as , A parent operation opens some go coroutines , these go A coroutine should not be able to cancel a parent go The work of the collaborative process .
One Context Can be multiple go Concurrent concurrent access of coroutines . You can put a Context To multiple go coroutines , Then by canceling the Context To cancel all go The work of the collaborative process .
derivative Context
context Packages provide methods from existing Context Derive new Context. these Context Form a tree . When one Context When cancelled , All the derivations from it Context All cancelled .Background yes Context The root of a tree , It will never be cancelled . It is usually main function 、 Initialize or test using , And as the top level of the arrival request Context.Background function :
// Background returns a non-nil, empty Context. It is never canceled, has no
// values, and has no deadline. It is typically used by the main function,
// initialization, and tests, and as the top-level Context for incoming
// requests.
func Background() Context {
return background
}
WithCancel and WithTimeout The function uses the given Context Derive new Context. Usually when processing requests handler Cancel the... Related to the request after returning Context.WithCancel You can use multiple replica Cancel redundancy request . Besides ,WithTimeout You can set the deadline when requesting back-end services deadline.WithCancel Source code is as follows :
// WithCancel Return to one parent And a new one Done passageway , If returned cancelFunc Called ,
// Back to Context Of Done The passage will be closed , Or be a father Context Of Done The passage is closed , Back to Context Of Done The channel will also be closed .
func WithCancel(parent Context) (ctx Context, cancel CancelFunc) {
if parent == nil {
panic("cannot create context from nil parent")
}
// from parent Context Construct a Cancel Context
c := newCancelCtx(parent)
// spread cancel, Be a father Context On cancellation , Son Context Will also cancel
propagateCancel(parent, &c)
return &c, func() {
c.cancel(true, Canceled) }
}
It calls for newCancelCtx:
// newCancelCtx returns an initialized cancelCtx.
func newCancelCtx(parent Context) cancelCtx {
return cancelCtx{
Context: parent}
}
newCancelCtx Simple will Context Encapsulated in the CancelCtx.cancelCtx Is defined as follows :
// A cancelCtx can be canceled. When canceled, it also cancels any children
// that implement canceler.
type cancelCtx struct {
Context
mu sync.Mutex // protects following fields
done atomic.Value // of chan struct{}, created lazily, closed by first cancel call
children map[canceler]struct{
} // set to nil by the first cancel call
err error // set to non-nil by the first cancel call
}
Continue to look at WithCancel Another function called propagateCancel,propagateCancel It means to multiply 、 spread cancel. This function sets when the parent Context Cancel when cancelled Context. The source code is as follows :
// propagateCancel arranges for child to be canceled when parent is.
func propagateCancel(parent Context, child canceler) {
// Done Will return a receive only channel , If done It's empty , Then father Context It will never be cancelled
done := parent.Done()
if done == nil {
return // parent is never canceled
}
select {
case <-done:
// Father Context Has been cancelled , Jiangzi Context Also cancel
child.cancel(false, parent.Err())
return
default:
}
// parentCancelCtx return parent Corresponding cancelCtx
if p, ok := parentCancelCtx(parent); ok {
p.mu.Lock()
if p.err != nil {
// Father Context Has been cancelled , Jiangzi Context Cancel
child.cancel(false, p.err)
} else {
// Father Context Not cancelled , Initialize the parent Context Of children Domain , And add yourself to the parent CancelCtx Of children domain
if p.children == nil {
p.children = make(map[canceler]struct{
})
}
p.children[child] = struct{
}{
}
}
p.mu.Unlock()
} else {
// parentCancelCtx
atomic.AddInt32(&goroutines, +1)
// Can't find parent Of CancelCtx, Then open a go The process monitors the parent Context, When it is found that it is cancelled, cancel the sub Context
go func() {
select {
case <-parent.Done():
child.cancel(false, parent.Err())
case <-child.Done():
}
}()
}
}
cancel The method comes from canceler Interface .canceler Can be used to cancel Context、 Check Context Is it cancelled :
// A canceler is a context type that can be canceled directly. The
// implementations are *cancelCtx and *timerCtx.
type canceler interface {
cancel(removeFromParent bool, err error)
Done() <-chan struct{
}
}
cancelCtx The interface is implemented . comparison Context, It adds a mutex 、 A passage 、 A record Context Of children、 A record is cancelled err:
// A cancelCtx can be canceled. When canceled, it also cancels any children
// that implement canceler.
type cancelCtx struct {
Context
mu sync.Mutex // protects following fields
done atomic.Value // of chan struct{}, created lazily, closed by first cancel call
children map[canceler]struct{
} // set to nil by the first cancel call
err error // set to non-nil by the first cancel call
}
see cancel The logic of the method :
// cancel The method is closed cancelCtx The passage of , Cancel method receiver c The son of Context,
// If removeFromParent Set to true, Will c From his father Context remove
func (c *cancelCtx) cancel(removeFromParent bool, err error) {
if err == nil {
panic("context: internal error: missing cancel error")
}
c.mu.Lock()
if c.err != nil {
c.mu.Unlock()
return // already canceled
}
c.err = err
// From the above done The type of atomic.Value, The actual saved type is chan struct{},
// Load Method will return the last Store Method to save the value , Otherwise it returns nil
d, _ := c.done.Load().(chan struct{
})
if d == nil {
// c.done No channels saved , Save a closed channel
c.done.Store(closedchan)
} else {
// Close channel
close(d)
}
// take children Domain saved child Context Cancel
for child := range c.children {
// NOTE: acquiring the child's lock while holding parent's lock.
child.cancel(false, err)
}
c.children = nil
c.mu.Unlock()
if removeFromParent {
removeChild(c.Context, c)
}
}
go back to WithCancel Method , This method actually uses cancelCtx Encapsulates the incoming Context, The return type is still Context, And the encapsulated CancelCtx Of cancel Method returns , To master the parent Context Of go coroutines , Let it decide whether to cancel .
// WithCancel Returned a Context And cancel the Context Function of
func WithCancel(parent Context) (ctx Context, cancel CancelFunc) {
if parent == nil {
panic("cannot create context from nil parent")
}
// from parent Context Construct a Cancel Context
c := newCancelCtx(parent)
// Spread down cancel, Be a father Context On cancellation , Son Context Will also cancel
propagateCancel(parent, &c)
return &c, func() {
c.cancel(true, Canceled) }
}
Example
The following example is a server that processes requests . It's registered handleSearch To deal with it /search request . The processor creates an initial Context, And schedule it to cancel after the processor returns . If the request contains timeout Field ,Context stay timeout Automatically cancel after the time .
func handleSearch(w http.ResponseWriter, req *http.Request) {
var (
ctx context.Context
cancel context.CancelFunc
)
timeout, err := time.ParseDuration(req.FormValue("timeout"))
// Take root Context Call the above WithTimeout, Get son Context And cancellation methods cancel
if err == nil {
ctx, cancel = context.WithTimeout(context.Background(), timeout)
} else {
ctx, cancel = context.WithCancel(context.Background())
}
// stay handleSearch The cancel method is called when the method returns , Will cancel the Context All the children under Context
defer cancel()
Another example shows Context Cascade cancellation of :
func main() {
route := gin.Default()
route.GET("/hello", func(c *gin.Context) {
// gin Default returned Context Namely context Under bag Background context
ctx, cancel := context.WithCancel(c.Request.Context())
// Turn on additional go To process a request
go doSomething(ctx)
time.Sleep(5 * time.Second)
cancel()
})
route.Run(":8080")
}
// doSomething Will recursively create Context, But it does not turn off recursively created Context,
// Father Context Cancel will cause all Context Cancel .
func doSomething(ctx context.Context) {
for {
time.Sleep(time.Second)
select {
case <-ctx.Done():
fmt.Println("context is done.")
return
default:
fmt.Println("context is not done...")
// No grandchildren Context Cancel , Dan sun Context Because of my father Context Cancel and cancel
c, _ := context.WithCancel(ctx)
doSomething(c)
}
}
}
summary
context Package provides an interface for sharing values within the request domain , It also provides a set of open go The method of coordination process management , adopt Done Method can be easily implemented go Exit of coprocessor , adopt Deadline Ways to make go The coroutine determines whether to continue processing the request , adopt Err Method can record Context Reason for cancellation .
Reference material
边栏推荐
- Interprocess communication - shared memory shmat
- 3、 Storage system
- La différence entre philosophie et littérature
- Explain bio, NiO, AIO in detail
- [LeetCode]7. Integer inversion thirty-nine
- MySql索引
- leaflet中如何优雅的解决百度、高德地图的偏移问题
- Is divicon still used in leaflet in H5 era?
- Go custom collation
- On the parameters of main function in C language
猜你喜欢
![[matlab] symbol calculation](/img/a5/7682a465ca2813a83114c091580c53.png)
[matlab] symbol calculation

3、 Storage system

PMP training organization
![[matlab] two dimensional curve](/img/5a/bd69c78513fe4b59b2c63dc3679841.png)
[matlab] two dimensional curve

How to visit a website

PMP renewal | PDU specific operation diagram

Interprocess communication - shared memory shmat

Divicon est toujours utilisé dans le leaflet de l'ère H5?
![[vscode]todo tree a to-do plug-in](/img/52/c977bc9cd021ca6fd12bcc22ae9f78.jpg)
[vscode]todo tree a to-do plug-in

【HCIE论述】组播IGMP-A
随机推荐
【Matlab】矩阵操作
APISpace 空号检测API接口 免费好用
Summary of individual NLP internship experience
Is the revised PMP worth testing?
TypeError: wave. ensureState is not a function
Huawei cloud elastic ECS use [Huawei cloud to jianzhiyuan]
[LeetCode]13. Roman numerals to integers thirty
VHDL编程实验练习题合集
2022 beautician (technician) certificate title and answer
睡前小故事之MySQL起源
How to control the display and hiding of layergroup through transparency in leaflet
63. 不同路径 II
21 Chundong University blasting safety online peacetime operation 123 [standard answer]
Is divicon still used in leaflet in H5 era?
Is the newly graduated college student taking BEC or PMP? PM who wants to transfer to another job in the future
VHDL programming experiment exercises collection
Matlab【路径规划】—— 无人机药品配送路线最优化
Browser cache execution process
What occupation is suitable for PMP?
3、 Storage system