问题描述
我有一个带有单个节点的ASP.Net Core 3.1 WebAPI。 (从本质上讲,这是一个代理终结点,不必在此链的最后端处理噩梦般的白名单。)我同样控制的客户端,都以编程方式将相同的请求发送到代理。有时或经常,kestral服务器在Linux服务器的系统日志中报告以下错误。
Oct 2 19:06:52 CCBD-Status-API-East CCBD-Status-API[979]: An unhandled exception has occurred while executing the request.
Oct 2 19:06:52 CCBD-Status-API-East CCBD-Status-API[979]: Microsoft.AspNetCore.Server.Kestrel.Core.BadHttpRequestException: Unexpected end of request content.
Oct 2 19:06:52 CCBD-Status-API-East CCBD-Status-API[979]: at Microsoft.AspNetCore.Server.Kestrel.Core.BadHttpRequestException.Throw(RequestRejectionReason reason)
Oct 2 19:06:52 CCBD-Status-API-East CCBD-Status-API[979]: at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.Http1ContentLengthMessageBody.ReadAsyncInternal(CancellationToken cancellationToken)
Oct 2 19:06:52 CCBD-Status-API-East CCBD-Status-API[979]: at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpRequestStream.ReadAsyncInternal(Memory`1 buffer,CancellationToken cancellationToken)
Oct 2 19:06:52 CCBD-Status-API-East CCBD-Status-API[979]: at System.Text.Json.JsonSerializer.ReadAsync[TValue](Stream utf8Json,Type returnType,JsonSerializerOptions options,CancellationToken cancellationToken)
Oct 2 19:06:52 CCBD-Status-API-East CCBD-Status-API[979]: at Microsoft.AspNetCore.Mvc.Formatters.SystemTextJsonInputFormatter.ReadRequestBodyAsync(InputFormatterContext context,Encoding encoding)
Oct 2 19:06:52 CCBD-Status-API-East CCBD-Status-API[979]: at Microsoft.AspNetCore.Mvc.Formatters.SystemTextJsonInputFormatter.ReadRequestBodyAsync(InputFormatterContext context,Encoding encoding)
Oct 2 19:06:52 CCBD-Status-API-East CCBD-Status-API[979]: at Microsoft.AspNetCore.Mvc.ModelBinding.Binders.BodyModelBinder.BindModelAsync(ModelBindingContext bindingContext)
Oct 2 19:06:52 CCBD-Status-API-East CCBD-Status-API[979]: at Microsoft.AspNetCore.Mvc.ModelBinding.ParameterBinder.BindModelAsync(ActionContext actionContext,IModelBinder modelBinder,IValueProvider valueProvider,ParameterDescriptor parameter,ModelMeta
data Metadata,Object value)
Oct 2 19:06:52 CCBD-Status-API-East CCBD-Status-API[979]: at Microsoft.AspNetCore.Mvc.Controllers.ControllerBinderDelegateProvider.<>c__displayClass0_0.<<CreateBinderDelegate>g__Bind|0>d.MoveNext()
Oct 2 19:06:52 CCBD-Status-API-East CCBD-Status-API[979]: --- End of stack trace from prevIoUs location where exception was thrown ---
Oct 2 19:06:52 CCBD-Status-API-East CCBD-Status-API[979]: at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeInnerFilterasync>g__Awaited|13_0(ControllerActionInvoker invoker,Task lastTask,State next,Scope scope,Object state,Boo
lean isCompleted)
Oct 2 19:06:52 CCBD-Status-API-East CCBD-Status-API[979]: at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|19_0(ResourceInvoker invoker,Boolean isComple
ted)
Oct 2 19:06:52 CCBD-Status-API-East CCBD-Status-API[979]: at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker,Task task,Idisposable scope)
Oct 2 19:06:52 CCBD-Status-API-East CCBD-Status-API[979]: at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint,Task requestTask,ILogger logger)
Oct 2 19:06:52 CCBD-Status-API-East CCBD-Status-API[979]: at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.<Invoke>g__Awaited|6_0(ExceptionHandlerMiddleware middleware,HttpContext context,Task task)
请求很小
{'Url': '<URL data>','Status': 0}
API控制器代码:
public IActionResult GetStreamStatus([FromBody] StreamInfo input)
{
try
{
if (!ModelState.IsValid) return BadRequest();
NetworkCredential netCred = new NetworkCredential(_config.Value.User,_config.Value.Pass);
var cred = new CredentialCache();
cred.Add(new Uri(input.Url),"Digest",netCred);
_logger.Log@R_917_4045@ion($"Attempting to get status from: {input.Url}");
var httpClient = new HttpClient(new httpclienthandler {Credentials = cred,PreAuthenticate = true});
var resp = httpClient.GetAsync(new Uri(input.Url));
_logger.Log@R_917_4045@ion($"{input.Url} returned: {resp.Result.StatusCode}");
input.Status = (int) resp.Result.StatusCode;
return Ok(input);
}
catch (Exception e)
{
_logger.LogError(e.ToString());
return BadRequest();
}
}
Startup.cs配置方法
public void Configure(IApplicationBuilder app,IWebHostEnvironment env)
{
app.UseExceptionHandler(a => a.Run(async context =>
{
var exceptionHandlerPathFeature = context.Features.Get<IExceptionHandlerPathFeature>();
var exception = exceptionHandlerPathFeature.Error;
var result = JsonConvert.SerializeObject(new {error = exception.Message});
context.Response.ContentType = "application/json";
await context.Response.WriteAsync(result);
}));
app.UseForwardedHeaders(new ForwardedHeadersOptions
{
ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto
});
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
def check_stream(tc,app,Feed,server):
try:
logger.info("Check Stream: {}".format(server))
stream_url = ""
if server == 'pri':
stream_url = <Building URL>
elif server == 'bak':
stream_url = <Building URL>
json_input = {"Url": stream_url,"Status": 0}
logger.info(json_input)
headers = {'Content-Type': 'application/json'}
resp = requests.post(<Proxy URL>,data=json.dumps(json_input),headers=headers)
logger.info(resp.headers)
logger.info("Response Text: {}".format(resp.text))
results = json.loads(resp.text)
code = results.get('status')
return code
except Exception as e:
logger.error("Stream Check exception: {} {}".format(type(e).__name__,str(e.args)))
解决方法
我知道了。我将节点转移到异步状态,并且可以正常工作。
public async Task<IActionResult> GetStreamStatusAsync([FromBody] StreamInfo input)
{
try
{
if (!ModelState.IsValid) return BadRequest();
NetworkCredential netCred = new NetworkCredential(_config.Value.User,_config.Value.Pass);
var cred = new CredentialCache();
cred.Add(new Uri(input.Url),"Digest",netCred);
_logger.LogInformation($"Attempting to get status from: {input.Url}");
var httpClient = new HttpClient(new HttpClientHandler {Credentials = cred,PreAuthenticate = true});
var resp = await httpClient.GetAsync(new Uri(input.Url));
_logger.LogInformation($"{input.Url} returned: {resp.StatusCode}");
input.Status = (int) resp.StatusCode;
return Ok(input);
}
catch (Exception e)
{
_logger.LogError(e.ToString());
return BadRequest();
}
}