Browse Source
dedicated upload processor
dedicated upload processor
avoid thundering effect of overloading volume serverspull/1960/head
Chris Lu
4 years ago
3 changed files with 167 additions and 52 deletions
-
61weed/operation/upload_processor.go
-
2weed/server/filer_server.go
-
134weed/server/filer_server_handlers_write_upload.go
@ -0,0 +1,61 @@ |
|||
package operation |
|||
|
|||
import ( |
|||
"reflect" |
|||
"runtime" |
|||
"sync" |
|||
"sync/atomic" |
|||
) |
|||
|
|||
type OperationRequest func() |
|||
|
|||
var ( |
|||
requestSlots = uint32(32) |
|||
requests = make([]chan OperationRequest, requestSlots) // increase slots to increase fairness
|
|||
ConcurrentUploadLimit = int32(runtime.NumCPU()) // directly related to memory usage
|
|||
concurrentLimitCond = sync.NewCond(new(sync.Mutex)) |
|||
concurrentUpload int32 |
|||
) |
|||
|
|||
func init() { |
|||
|
|||
for i := 0; i < int(requestSlots); i++ { |
|||
requests[i] = make(chan OperationRequest) |
|||
} |
|||
|
|||
cases := make([]reflect.SelectCase, requestSlots) |
|||
for i, ch := range requests { |
|||
cases[i] = reflect.SelectCase{Dir: reflect.SelectRecv, Chan: reflect.ValueOf(ch)} |
|||
} |
|||
|
|||
go func() { |
|||
for { |
|||
_, value, ok := reflect.Select(cases) |
|||
if !ok { |
|||
continue |
|||
} |
|||
|
|||
request := value.Interface().(OperationRequest) |
|||
|
|||
concurrentLimitCond.L.Lock() |
|||
for atomic.LoadInt32(&concurrentUpload) > ConcurrentUploadLimit { |
|||
concurrentLimitCond.Wait() |
|||
} |
|||
atomic.AddInt32(&concurrentUpload, 1) |
|||
concurrentLimitCond.L.Unlock() |
|||
|
|||
go func() { |
|||
defer atomic.AddInt32(&concurrentUpload, -1) |
|||
defer concurrentLimitCond.Signal() |
|||
request() |
|||
}() |
|||
|
|||
} |
|||
}() |
|||
|
|||
} |
|||
|
|||
func AsyncOutOfOrderProcess(slotKey uint32, request OperationRequest) { |
|||
index := slotKey % requestSlots |
|||
requests[index] <- request |
|||
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue