当前位置:网站首页>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
边栏推荐
- MySQL index
- Is the brokerage account in qiniu business school safe? Is the account opening rate low
- How to control the display and hiding of layergroup through transparency in leaflet
- How leaflet gracefully displays the bubble window of overlapping points
- 【Matlab】二维曲线
- Machining Industry MES system Mold Industry MES system CNCl Medium Industry MES System MES code scanning and reporting MES data collection
- [matlab] basic operation
- Is the PMP training organization an actual training?
- Do you have to read for PMP?
- How to visit a website
猜你喜欢
Do you really use the buffer buffer in PostGIS?
A detailed explanation of synchronized
3、 Storage system
KAUST:Deyao Zhu | 价值记忆图:基于离线强化学习的图结构世界模型
Will PM (Project Manager) take the PMP Exam?
Vscode实现PHP在浏览器实时预览
Accelerating with Dali modules
Learn to divide subnets in an article
PMP registration conditions, time, cost, new version related information
[matlab] 3D curve and 3D surface
随机推荐
June 11, 2022 diary: Mr. Wang's spring, mixed in
[LeetCode]26. Removes duplicates from a sorted array thirty-three
How to visit a website
Free lottery --- PMP renewal PDU | PMP knowledge map
[hcie discussion] multicast igmp-a
How SAP ui5 uses manifest JSON file defines third-party library dependencies
分公司能与员工签劳动合同么
6.824 Lab 1: MapReduce
在 Golang 中构建 CRUD 应用程序
[vscode]todo tree a to-do plug-in
63. different paths II
[LeetCode]1. Sum of two numbers thirty-four
2022 beautician (technician) certificate title and answer
[hcie discussion] STP-A
leaflet中如何优雅的解决百度、高德地图的偏移问题
[LeetCode]3. The longest substring without duplicate characters forty
一篇文章学会子网划分
The whole process from entering URL to displaying page (interview)
How to quickly query the online status of mobile phones
What are the levels of safety accidents