Skip to content

Commit

Permalink
Circuit Breaking Per Method (#773)
Browse files Browse the repository at this point in the history
* Check for unnecessary file changes

* Fix circuit breaker method name for http client
  • Loading branch information
Neha Konjeti authored and isopropylcyanide committed Jul 28, 2021
1 parent 9232e35 commit d83f2df
Show file tree
Hide file tree
Showing 15 changed files with 434 additions and 402 deletions.
99 changes: 52 additions & 47 deletions codegen/template_bundle/template_files.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

30 changes: 16 additions & 14 deletions codegen/templates/grpc_client.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,18 @@ func {{$exportName}}(deps *module.Dependencies) Client {
{{- end -}}
{{- end}}
}

// circuitBreakerDisabled sets whether circuit-breaker should be disabled
circuitBreakerDisabled := false
if deps.Default.Config.ContainsKey("clients.{{$clientID}}.circuitBreakerDisabled") {
circuitBreakerDisabled = deps.Default.Config.MustGetBoolean("clients.{{$clientID}}.circuitBreakerDisabled")
}
if !circuitBreakerDisabled {
for methodKey := range methodNames {
configureCircuitBreaker(deps, timeoutInMS, methodNames[methodKey])
}
}

return &{{$clientName}}{
{{range $i, $s := $services -}}
{{camel $s.Name}}Client: gen.New{{pascal $s.Name}}YARPCClient(oc),
Expand All @@ -81,21 +93,13 @@ func {{$exportName}}(deps *module.Dependencies) Client {
"{{$clientID}}",
routingKey,
requestUUIDHeaderKey,
!configureCircuitBreaker(deps, timeoutInMS),
circuitBreakerDisabled,
timeoutInMS,
),
}
}

func configureCircuitBreaker(deps *module.Dependencies, timeoutVal int) bool {
// circuitBreakerDisabled sets whether circuit-breaker should be disabled
circuitBreakerDisabled := false
if deps.Default.Config.ContainsKey("clients.{{$clientID}}.circuitBreakerDisabled") {
circuitBreakerDisabled = deps.Default.Config.MustGetBoolean("clients.{{$clientID}}.circuitBreakerDisabled")
}
if circuitBreakerDisabled {
return false
}
func configureCircuitBreaker(deps *module.Dependencies, timeoutVal int, method string) {
// sleepWindowInMilliseconds sets the amount of time, after tripping the circuit,
// to reject requests before allowing attempts again to determine if the circuit should again be closed
sleepWindowInMilliseconds := 5000
Expand All @@ -119,15 +123,13 @@ func configureCircuitBreaker(deps *module.Dependencies, timeoutVal int) bool {
if deps.Default.Config.ContainsKey("clients.{{$clientID}}.requestVolumeThreshold") {
requestVolumeThreshold = int(deps.Default.Config.MustGetInt("clients.{{$clientID}}.requestVolumeThreshold"))
}

hystrix.ConfigureCommand("{{$clientID}}", hystrix.CommandConfig{
hystrix.ConfigureCommand(method, hystrix.CommandConfig{
MaxConcurrentRequests: maxConcurrentRequests,
ErrorPercentThreshold: errorPercentThreshold,
SleepWindow: sleepWindowInMilliseconds,
RequestVolumeThreshold: requestVolumeThreshold,
Timeout: timeoutVal,
})
return true
}

{{range $i, $svc := .ProtoServices -}}
Expand Down Expand Up @@ -163,7 +165,7 @@ func (e *{{$clientName}}) {{$methodName}}(
if e.opts.CircuitBreakerDisabled {
result, err = runFunc(ctx, request, opts...)
} else {
err = hystrix.DoC(ctx, "{{$clientID}}", func(ctx context.Context) error {
err = hystrix.DoC(ctx, "{{$methodName}}", func(ctx context.Context) error {
result, err = runFunc(ctx, request, opts...)
return err
}, nil)
Expand Down
37 changes: 19 additions & 18 deletions codegen/templates/http_client.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,21 @@ func {{$exportName}}(deps *module.Dependencies) Client {
followRedirect = deps.Default.Config.MustGetBoolean("clients.{{$clientID}}.followRedirect")
}


circuitBreakerDisabled := configureCircuitBreaker(deps, timeoutVal)
methodNames := map[string]string{
{{range $serviceMethod, $methodName := $exposedMethods -}}
"{{$methodName}}": "{{$serviceMethod}}",
{{end}}
}
// circuitBreakerDisabled sets whether circuit-breaker should be disabled
circuitBreakerDisabled := false
if deps.Default.Config.ContainsKey("clients.{{$clientID}}.circuitBreakerDisabled") {
circuitBreakerDisabled = deps.Default.Config.MustGetBoolean("clients.{{$clientID}}.circuitBreakerDisabled")
}
if !circuitBreakerDisabled {
for methodKey := range methodNames {
configureCircuitBreaker(deps, timeoutVal, methodKey)
}
}

return &{{$clientName}}{
clientID: "{{$clientID}}",
Expand All @@ -124,11 +137,7 @@ func {{$exportName}}(deps *module.Dependencies) Client {
httpClient: zanzibar.NewHTTPClientContext(
deps.Default.ContextLogger, deps.Default.ContextMetrics, deps.Default.JSONWrapper,
"{{$clientID}}",
map[string]string{
{{range $serviceMethod, $methodName := $exposedMethods -}}
"{{$methodName}}": "{{$serviceMethod}}",
{{end}}
},
methodNames,
baseURL,
defaultHeaders,
timeout,
Expand All @@ -155,12 +164,7 @@ func initializeAltRoutingMap(altServiceDetail config.AlternateServiceDetail) map
}
{{end -}}

func configureCircuitBreaker(deps *module.Dependencies, timeoutVal int) bool {
// circuitBreakerDisabled sets whether circuit-breaker should be disabled
circuitBreakerDisabled := false
if deps.Default.Config.ContainsKey("clients.{{$clientID}}.circuitBreakerDisabled") {
circuitBreakerDisabled = deps.Default.Config.MustGetBoolean("clients.{{$clientID}}.circuitBreakerDisabled")
}
func configureCircuitBreaker(deps *module.Dependencies, timeoutVal int, method string) {
// sleepWindowInMilliseconds sets the amount of time, after tripping the circuit,
// to reject requests before allowing attempts again to determine if the circuit should again be closed
sleepWindowInMilliseconds := 5000
Expand All @@ -184,16 +188,13 @@ func configureCircuitBreaker(deps *module.Dependencies, timeoutVal int) bool {
if deps.Default.Config.ContainsKey("clients.{{$clientID}}.requestVolumeThreshold") {
requestVolumeThreshold = int(deps.Default.Config.MustGetInt("clients.{{$clientID}}.requestVolumeThreshold"))
}
if !circuitBreakerDisabled {
hystrix.ConfigureCommand("{{$clientID}}", hystrix.CommandConfig{
hystrix.ConfigureCommand(method, hystrix.CommandConfig{
MaxConcurrentRequests: maxConcurrentRequests,
ErrorPercentThreshold: errorPercentThreshold,
SleepWindow: sleepWindowInMilliseconds,
RequestVolumeThreshold: requestVolumeThreshold,
Timeout: timeoutVal,
})
}
return circuitBreakerDisabled
}

// HTTPClient returns the underlying HTTP client, should only be
Expand Down Expand Up @@ -302,7 +303,7 @@ func (c *{{$clientName}}) {{$methodName}}(
} else {
// We want hystrix ckt-breaker to count errors only for system issues
var clientErr error
err = hystrix.DoC(ctx, "{{$clientID}}", func(ctx context.Context) error {
err = hystrix.DoC(ctx, "{{$methodName}}", func(ctx context.Context) error {
res, clientErr = req.Do()
if res != nil {
// This is not a system error/issue. Downstream responded
Expand Down
Loading

0 comments on commit d83f2df

Please sign in to comment.