当前位置:网站首页>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
边栏推荐
- [LeetCode]13. Roman numerals to integers thirty
- How to make maputnik, a vector tile matching artifact, support GeoServer
- [LeetCode]21. Merge two ordered linked lists twenty-nine
- 进程间通信-共享内存shmat
- 哲学和文学的区别
- 【Matlab】多项式计算
- Is the newly graduated college student taking BEC or PMP? PM who wants to transfer to another job in the future
- 2022年3月11日记:王老师的春天,奇异的模板模式
- On the parameters of main function in C language
- June 11, 2022 diary: Mr. Wang's spring, mixed in
猜你喜欢

On the parameters of main function in C language

How to pass the PMP review?

63. 不同路径 II

How leaflet gracefully displays the bubble window of overlapping points

USTC of China University of science and technology: Minrui Wang | distribution network voltage stabilization based on transformer Multi-Agent Reinforcement Learning

MySql索引

Basics of network security (1)

浏览器缓存的执行流程

Start of u-boot S analysis (III)

How to control the display and hiding of layergroup through transparency in leaflet
随机推荐
USTC of China University of science and technology: Minrui Wang | distribution network voltage stabilization based on transformer Multi-Agent Reinforcement Learning
ik分词器的安装
Matlab【路径规划】—— 无人机药品配送路线最优化
如何快速查询手机号码归属地和运营商
[supersocket 2.0] supersocket 2.0 from the beginning to the end
启牛商学院里面的券商账户是安全的吗?开户费率低吗
Will PM (Project Manager) take the PMP Exam?
SAP Business Technology Platform (BTP) workflow function introduction
Do you really use the buffer buffer in PostGIS?
Can branches sign labor contracts with employees
1115. alternate printing foobar
63. different paths II
How to publish OSM maps locally and customize the mapping
String类中split()方法的使用
PLC也能制作小遊戲----Codesys編寫猜數字小遊戲
H5時代leaflet中還在用DivIcon?
[LeetCode]21. Merge two ordered linked lists twenty-nine
2022 constructor - Equipment direction - General Foundation (constructor) operation certificate examination questions and simulation examination
[matlab] 3D curve and 3D surface
[LeetCode]26. Removes duplicates from a sorted array thirty-three