protected override async Task <HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { var ctx = new HandlingContext { Request = request, HandleAsync = base.SendAsync, ResponsSource = new TaskCompletionSource <HttpResponseMessage>(cancellationToken), CancellationToken = cancellationToken }; try { await _dispather.AcceptThenDispatchAsync(ctx); } catch (Exception ex) { _logger.LogError(ex, ex.Message); ctx.ResponsSource.SetException(ex); } return(await ctx.ResponsSource.Task); }
/// <returns>是否尝试了“下一个”上游服务端</returns> private async Task <bool> NextPeerAsync( HandlingContext handlingContext, UpstreamPeer peer, HttpResponseMessage response, Uri originUri, bool isTimeout = false) { if (peer == null) { return(false); } if (handlingContext.IsSingle) { return(false); } handlingContext.Start = handlingContext.Start ?? DateTime.Now; if (NextWhen.Never == (peer.NextWhen & NextWhen.Never)) { return(false); } var request = handlingContext.Request; if (request.Method != HttpMethod.Get && NextWhen.GetOnly == (peer.NextWhen & NextWhen.GetOnly)) { return(false); } handlingContext.Tries = handlingContext.Tries ?? (peer.NextTries == 0 ? int.MaxValue : peer.NextTries); if (handlingContext.Tries == 0) { return(false); } var when = NextWhen.None; if (isTimeout) { when |= NextWhen.Timeout; } else if (response == null) { when |= NextWhen.Error; } else { if (response.IsSuccessStatusCode) { return(false); } switch (response.StatusCode) { case HttpStatusCode.InternalServerError: when |= NextWhen.Http500; break; case HttpStatusCode.BadGateway: when |= NextWhen.Http502; break; case HttpStatusCode.ServiceUnavailable: when |= NextWhen.Http503; break; case HttpStatusCode.RequestTimeout: case HttpStatusCode.GatewayTimeout: when |= NextWhen.Timeout; break; case HttpStatusCode.Forbidden: when |= NextWhen.Http403; break; case HttpStatusCode.NotFound: when |= NextWhen.Http404; break; default: return(false); } } #if NETSTANDARD2_0 if (request.Method == HttpMethod.Post || request.Method.Method == "PATCH") #elif NETSTANDARD2_1 if (request.Method == HttpMethod.Post || request.Method == HttpMethod.Patch) #endif { when |= NextWhen.NonIdemponent; } if (when != (when & peer.NextWhen)) { return(false); } if (DateTime.Now - handlingContext.Start >= peer.NextTimeout) { return(false); } handlingContext.Request = request.Clone(originUri); //保持上下文重试 var next = await _dispatcher.AcceptThenDispatchAsync(handlingContext); handlingContext.Tries--; return(next); }