private HttpWebRequest PrepareWebRequest(ClientExecutionContext context) { NameValueCollection addHeaders = null; HttpWebRequest client = PrepareWebRequest(context, addHeaders); using (var requestStream = client.GetRequestStream()) { Stopwatch serializationWatch = new Stopwatch(); try { serializationWatch.Start(); context.CallFormat.StreamSerializer(context.Request, requestStream); } catch (WebException ex) { var webEx = ExceptionFactory.CreateWebException(ex); throw webEx; } catch (Exception) { throw; } finally { serializationWatch.Stop(); context.Metrics.SerializationTime = serializationWatch.ElapsedMilliseconds; } } context.Metrics.RequestSize = client.ContentLength; return(client); }
public static void CheckServerAvailability(ClientExecutionContext context, Exception exception = null) { try { if (exception == null) { return; } if (exception is WebException) { var webException = (WebException)exception; bool available = webException.Status != WebExceptionStatus.ProtocolError ? CheckGenericWebException(context, webException) : CheckProtocolWebException(context, webException); if (!available) { return; } } } catch (Exception ex) { log.Warn("Failed to check server availability", ex); } }
private void Validate(ClientExecutionContext context) { Exception ex = null; if (string.IsNullOrWhiteSpace(context.Format)) { ex = new ArgumentNullException("Format was not supplied"); } else if (CurrentCallFormat == null) { ex = new NotSupportedException(string.Format("Not supported call format : {0}", context.Format)); } else if (string.IsNullOrWhiteSpace(context.ServiceUrl) || !(context.ServiceUrl.StartsWith("http://") || context.ServiceUrl.StartsWith("https://"))) { ex = new NotSupportedException(string.Format("BaseUri was not supplied or invalid : {0}", context.ServiceUrl)); } else if (string.IsNullOrWhiteSpace(context.Operation)) { ex = new ArgumentNullException("Operation name was not supplied"); } else if (context.Request == null) { ex = new ArgumentNullException("Request object was not supplied"); } if (ex != null) { LogGeneralException(context, ex); throw ex; } }
/// <summary> /// 创建异步请求Task,非IOCP实现 /// </summary> /// <typeparam name="TRequest">服务请求</typeparam> /// <typeparam name="TResponse">服务响应</typeparam> /// <param name="operationName">目标服务操作名</param> /// <param name="requestObject">服务请求对象</param> /// <param name="cancellationToken"></param> /// <param name="taskCreationOptions"></param> /// <returns>异步请求Task</returns> public Task <TResponse> CreateAsyncTask <TRequest, TResponse>(string operationName, object requestObject, CancellationToken?cancellationToken = null, TaskCreationOptions?taskCreationOptions = null) { ClientExecutionContext context = CreateExecutionContext(operationName, requestObject, ExecutionModes.AsyncMode); TimeSpan?timeout = CurrentRequestTimeout; TimeSpan?readWriteTimeout = CurrentRequestReadWriteTimeout; ResetCurrentRequestTimeoutSetting(); Func <TResponse> sendWebRequest = () => { try { InitThreadLocalBaseUri(context); if (timeout.HasValue) { CurrentRequestTimeout = timeout.Value; } if (readWriteTimeout.HasValue) { CurrentRequestReadWriteTimeout = readWriteTimeout.Value; } return(Invoke <TResponse>(context)); } catch (Exception ex) { context.IsSuccess = false; context.Error = ex; throw; } finally { ApplyRequestEndFilterSafe(context); } }; Task <TResponse> task = null; if (!cancellationToken.HasValue && !taskCreationOptions.HasValue) { task = new Task <TResponse>(sendWebRequest); } else if (cancellationToken.HasValue && !taskCreationOptions.HasValue) { task = new Task <TResponse>(sendWebRequest, cancellationToken.Value); } else if (!cancellationToken.HasValue && taskCreationOptions.HasValue) { task = new Task <TResponse>(sendWebRequest, taskCreationOptions.Value); } else { task = new Task <TResponse>(sendWebRequest, cancellationToken.Value, taskCreationOptions.Value); } task.Start(); return(TryAddFaultHandler(task)); }
private void BeginGetResponse(ClientExecutionContext context, HttpWebRequest httpRequest, AsyncCallback responseCallback) { try { httpRequest.BeginGetResponse(responseCallback, null); } catch (Exception) { throw; } }
private HttpWebRequest PrepareWebRequest(ClientExecutionContext context, NameValueCollection addHeaders = null) { if (!string.IsNullOrWhiteSpace(AppId)) { if (addHeaders == null) { addHeaders = new NameValueCollection(); } addHeaders[ServiceUtils.AppIdHttpHeaderKey] = AppId; } string requestUri; if (IsSLBService) { requestUri = context.ServiceUrl.WithTrailingSlash() + context.Operation + "." + context.Format; } else { requestUri = context.ServiceUrl.WithTrailingSlash() + context.Format.WithTrailingSlash() + context.Operation; } var client = (HttpWebRequest)WebRequest.Create(requestUri); client.Accept = context.Accept; client.Method = DefaultHttpMethod; client.Headers.Add(Headers); if (!DisableConnectionLeaseTimeout) { client.ServicePoint.ConnectionLeaseTimeout = DefaultConnectionLeaseTimeout; } if (addHeaders != null && addHeaders.Count > 0) { client.Headers.Add(addHeaders); } if (Proxy != null) { client.Proxy = Proxy; } client.Timeout = (int)GetOperationTimeout(context.Operation, RequestTimeoutType.Timeout).TotalMilliseconds; client.ReadWriteTimeout = (int)GetOperationTimeout(context.Operation, RequestTimeoutType.ReadWriteTimeout).TotalMilliseconds; client.AutomaticDecompression = DisableAutoCompression ? DecompressionMethods.None : DefaultCompressionModes; client.AllowAutoRedirect = AllowAutoRedirect; ApplyWebRequestFilters(client); client.ContentType = context.ContentType; return(client); }
private Stream EndGetRequestStream(ClientExecutionContext context, HttpWebRequest httpRequest, IAsyncResult asyncResult) { try { return(httpRequest.EndGetRequestStream(asyncResult)); } catch (Exception) { throw; } }
private WebResponse EndGetResponse(ClientExecutionContext context, HttpWebRequest httpRequest, IAsyncResult asyncResult) { try { WebResponse response = httpRequest.EndGetResponse(asyncResult); return(response); } catch (Exception) { throw; } }
private static bool CheckProtocolWebException(ClientExecutionContext context, WebException webException) { var httpResponse = webException.Response as HttpWebResponse; if (httpResponse == null) { return(false); } int statusCode = (int)httpResponse.StatusCode; return(false); }
private WebResponse Invoke(ClientExecutionContext context, WebRequest request) { try { WebResponse response = request.GetResponse(); ServerAvailabilityChecker.CheckServerAvailability(context); return(response); } catch (Exception ex) { ServerAvailabilityChecker.CheckServerAvailability(context, ex); throw; } }
private void SemaphoreIsolationEndExecution(ClientExecutionContext context, object instance) { try { if (instance == null) { return; } CHystrixIntegration.UtilsSemaphoreIsolationEndExecution(instance); } catch (Exception ex) { Dictionary <string, string> addtionalInfo = GetClientInfo(context); addtionalInfo["ErrorCode"] = "FXD301018"; log.Warn("CHystrix IOCP Support EndExecution failed", ex, addtionalInfo); } }
private TResponse HandleResponse <TResponse>(ClientExecutionContext context, WebResponse webResponse) { if (DeserializeResponseUseMemoryStream) { return(HandleResponseUseMemoryStream <TResponse>(context, webResponse)); } ApplyWebResponseFilters(webResponse); TResponse response; using (var responseStream = webResponse.GetResponseStream()) { Stopwatch deserializationWatch = new Stopwatch(); try { deserializationWatch.Start(); response = (TResponse)context.CallFormat.StreamDeserializer(typeof(TResponse), responseStream); context.Response = response; } catch (WebException ex) { var webEx = ExceptionFactory.CreateWebException(ex); throw webEx; } catch (Exception) { throw; } finally { deserializationWatch.Stop(); context.Metrics.DeserializationTime = deserializationWatch.ElapsedMilliseconds; } } if (!HandleServiceErrorManually) { CheckResponseFailure(response as IHasResponseStatus); } return(response); }
private void LogGeneralException(ClientExecutionContext context, Exception ex) { string title = GetLogTitle("General Exception"); Dictionary <string, string> addtionalInfo = GetClientInfo(context); addtionalInfo["ErrorCode"] = "FXD301005"; if (!string.IsNullOrWhiteSpace(ex.HelpLink)) { addtionalInfo["HelpLink"] = ex.HelpLink; } if (IsWebException(ex) && !LogWebExceptionAsError) { log.Warn(title, ex, addtionalInfo); } else { log.Error(title, ex, addtionalInfo); } }
private void GetCHystrixCommandKeyForIOCPAsync(ClientExecutionContext context, out string chystrixCommandKey, out string chystrixInstanceKey) { string instanceKey = context.Host; chystrixCommandKey = CHystrixIOCPCommandKeys.GetOrAdd( CHystrixCommandKeyPrefixForIOCPAsync + context.Operation + "/" + instanceKey, key => { string commandKey = HystrixCommandKeyPrefixForIOCPAsync + "." + context.Operation.ToLower(); int count = GetCHystrixCommandMaxConcurrentCount(context.Operation); if (count > 0) { CHystrixIntegration.UtilsSemaphoreIsolationConfig(instanceKey, commandKey, HystrixCommandGroupKey, HystrixCommandDomain, count); } else { CHystrixIntegration.UtilsSemaphoreIsolationConfig(instanceKey, commandKey, HystrixCommandGroupKey, HystrixCommandDomain); } return(commandKey); }); chystrixInstanceKey = instanceKey; }
private object CreateCHystrixSemaphoreIsolationInstance(ClientExecutionContext context) { object chystrixSemaphoreIsolationInstance = null; try { if (EnableCHystrixSupportForIOCPAsync) { string chystrixCommandKey; string chystrixInstanceKey; GetCHystrixCommandKeyForIOCPAsync(context, out chystrixCommandKey, out chystrixInstanceKey); chystrixSemaphoreIsolationInstance = CHystrixIntegration.UtilsSemaphoreIsolationCreateInstance(chystrixInstanceKey, chystrixCommandKey); } } catch (Exception ex) { Dictionary <string, string> addtionalInfo = GetClientInfo(context); addtionalInfo["ErrorCode"] = "FXD301014"; log.Warn("CHystrix IOCP Support CreateInstance failed", ex, addtionalInfo); } return(chystrixSemaphoreIsolationInstance); }
public TResponse Invoke <TResponse>(string operationName, object requestObject, Func <TResponse> getFallback) { ClientExecutionContext context = CreateExecutionContext(operationName, requestObject, ExecutionModes.SynchronizationMode); Validate(context); try { if (!EnableCHystrixSupport) { return(InvokeInternal <TResponse>(context)); } string chystrixCommandKey; string chystrixInstanceKey; GetCHystrixCommandKey(context, out chystrixCommandKey, out chystrixInstanceKey); if (getFallback == null) { return(CHystrixIntegration.RunCommand <TResponse>(chystrixInstanceKey, chystrixCommandKey, () => InvokeInternal <TResponse>(context), null)); } return(CHystrixIntegration.RunCommand <TResponse>(chystrixInstanceKey, chystrixCommandKey, () => InvokeInternal <TResponse>(context), () => getFallback())); } catch (Exception ex) { context.IsSuccess = false; context.Error = ex; throw; } finally { ApplyRequestEndFilterSafe(context); } }
protected internal WebException HandleWebException(ClientExecutionContext context, WebException webEx) { using (webEx.Response) { HttpWebResponse errorResponse = webEx.Response as HttpWebResponse; if (errorResponse == null) { if (webEx is WebExceptionBase) { return(webEx); } return(ExceptionFactory.CreateWebException(webEx)); } if (webEx.Status == WebExceptionStatus.ProtocolError) { string title = string.IsNullOrWhiteSpace(errorResponse.StatusDescription) ? webEx.Message : errorResponse.StatusDescription; WebProtocolException serviceEx = null; if (webEx is WebProtocolException) { serviceEx = (WebProtocolException)webEx; } else { serviceEx = (WebProtocolException)ExceptionFactory.CreateWebException(webEx, title); } try { using (Stream stream = errorResponse.GetResponseStream()) { if (errorResponse.ContentType.MatchesContentType(context.ContentType)) { var bytes = stream.ReadFully(); using (var memoryStream = new MemoryStream(bytes)) { serviceEx.ResponseBody = bytes.FromUtf8Bytes(); serviceEx.ResponseObject = (GenericErrorResponseType)context.CallFormat.StreamDeserializer(typeof(GenericErrorResponseType), memoryStream); } } else { serviceEx.ResponseBody = stream.ToUtf8String(); } } } catch (Exception innerEx) { // Oh, well, we tried return(new WebProtocolException(title, innerEx) { StatusCode = (int)errorResponse.StatusCode, StatusDescription = errorResponse.StatusDescription, ResponseBody = serviceEx.ResponseBody }); } //Escape deserialize exception handling and throw here return(serviceEx); } return(webEx); } }
private static bool CheckGenericWebException(ClientExecutionContext context, WebException webException) { return(false); }
private void InitThreadLocalBaseUri(ClientExecutionContext context) { _threadLocalBaseUri.Value = context.ServiceUrl; }
private TResponse Invoke <TResponse>(ClientExecutionContext context) { Stopwatch stopwatch = null; Stopwatch remoteCallStopwatch = null; try { stopwatch = new Stopwatch(); stopwatch.Start(); ApplyRequestFilters(ServiceName, ServiceNamespace, context.Operation, context.Request); HttpWebRequest webRequest = PrepareWebRequest(context); remoteCallStopwatch = new Stopwatch(); remoteCallStopwatch.Start(); TResponse response; using (WebResponse webResponse = Invoke(context, webRequest)) { remoteCallStopwatch.Stop(); context.Metrics.ResponseSize = webResponse.ContentLength < 0 ? 0 : webResponse.ContentLength; response = HandleResponse <TResponse>(context, webResponse); } ApplyResponseFilters(ServiceName, ServiceNamespace, context.Operation, context.Response); context.IsSuccess = true; return(response); } catch (CServiceException cex) { Dictionary <string, string> additionalInfo = GetClientInfo(context); additionalInfo["ErrorCode"] = "FXD301004"; if (LogErrorWithRequestInfo) { additionalInfo["RequestObject"] = TypeSerializer.SerializeToString(context.Request); } LogCServiceException(GetLogTitle(InternalServiceUtils.ServiceErrorTitle), cex, additionalInfo); throw; } catch (WebException ex) { WebException subClassedException = HandleWebException(context, (WebException)ex); LogGeneralException(context, subClassedException); if (ex == subClassedException) { throw; } throw subClassedException; } catch (Exception ex) { LogGeneralException(context, ex); throw; } finally { if (remoteCallStopwatch != null) { if (remoteCallStopwatch.IsRunning) { remoteCallStopwatch.Stop(); } context.Metrics.ExecutionTime = remoteCallStopwatch.ElapsedMilliseconds; } stopwatch.Stop(); context.Metrics.TotalTime = stopwatch.ElapsedMilliseconds; ResetCurrentRequestTimeoutSetting(); } }
private TResponse HandleResponseUseMemoryStream <TResponse>(ClientExecutionContext context, WebResponse webResponse) { ApplyWebResponseFilters(webResponse); TResponse response; using (MemoryStream ms = new MemoryStream()) { string responseTypeName = typeof(TResponse).FullName; using (var responseStream = webResponse.GetResponseStream()) { var readStreamTransaction = new CatTransaction("SOA2Client.deserialization.readStream", responseTypeName); try { readStreamTransaction.Start(); responseStream.CopyTo(ms); ms.Flush(); ms.Seek(0, SeekOrigin.Begin); readStreamTransaction.MarkSuccess(); } catch (Exception ex) { readStreamTransaction.MarkFailure(ex); throw; } finally { readStreamTransaction.End(); } } var deserializeTransaction = new CatTransaction(CatSerializationTypes.ClientDeserializationCall, responseTypeName); Stopwatch deserializationWatch = new Stopwatch(); try { deserializationWatch.Start(); deserializeTransaction.Start(); response = (TResponse)context.CallFormat.StreamDeserializer(typeof(TResponse), ms); deserializeTransaction.MarkSuccess(); context.Response = response; } catch (WebException ex) { var webEx = ExceptionFactory.CreateWebException(ex); deserializeTransaction.MarkFailure(webEx); throw webEx; } catch (Exception ex) { deserializeTransaction.MarkFailure(ex); throw; } finally { deserializeTransaction.End(); deserializationWatch.Stop(); context.Metrics.DeserializationTime = deserializationWatch.ElapsedMilliseconds; } } if (!HandleServiceErrorManually) { CheckResponseFailure(response as IHasResponseStatus); } return(response); }
private TResponse InvokeInternal <TResponse>(ClientExecutionContext context) { return(Invoke <TResponse>(context)); }
/// <summary> /// 启动异步请求Task,IOCP实现 /// </summary> /// <typeparam name="TResponse">服务响应</typeparam> /// <param name="operationName">目标服务操作名</param> /// <param name="requestObject">服务请求对象</param> /// <returns>异步请求Task</returns> public Task <TResponse> StartIOCPTask <TResponse>(string operationName, object requestObject) { AsyncRequestState asyncRequestState = new AsyncRequestState(); TaskCompletionSource <TResponse> taskCompletionSource = new TaskCompletionSource <TResponse>(asyncRequestState); Stopwatch stopwatch = new Stopwatch(); Stopwatch requestWatch = new Stopwatch(); Stopwatch responseWatch = new Stopwatch(); ClientExecutionContext context = CreateExecutionContext(operationName, requestObject, ExecutionModes.IOCPMode); object semaphoreIsolationInstance = CreateCHystrixSemaphoreIsolationInstance(context); #region General Error Handler Action <Exception> handleGeneralError = ex => { try { if (asyncRequestState != null) { asyncRequestState.Complete(); } stopwatch.Stop(); context.Metrics.TotalTime = stopwatch.ElapsedMilliseconds; } catch { } try { SemaphoreIsolationMarkFailure(context, semaphoreIsolationInstance); } catch { } try { if (ex is WebException) { ex = HandleWebException(context, (WebException)ex); } if (semaphoreIsolationInstance == null || ex.GetType().FullName != CHystrixIntegration.CHystrixExceptionName) { LogGeneralException(context, ex); } context.IsSuccess = false; context.Error = ex; } catch { } taskCompletionSource.TrySetException(ex); }; #endregion try { SemaphoreIsolationStartExecution(semaphoreIsolationInstance); stopwatch.Start(); Validate(context); ApplyRequestFilters(ServiceName, ServiceNamespace, operationName, requestObject); HttpWebRequest webRequest = PrepareWebRequest(context, null); asyncRequestState.Initialize(webRequest, _enableTimeoutForIOCPAsync); #region Response CallBack AsyncCallback getResponseCallback = asyncGetResponseResult => { try { if (asyncGetResponseResult.CompletedSynchronously) { } else { InitThreadLocalBaseUri(context); } using (WebResponse webResponse = EndGetResponse(context, webRequest, asyncGetResponseResult)) { responseWatch.Stop(); context.Metrics.ResponseSize = webResponse.ContentLength < 0 ? 0 : webResponse.ContentLength; TResponse response = HandleResponse <TResponse>(context, webResponse); asyncRequestState.Complete(); ApplyResponseFilters(ServiceName, ServiceNamespace, operationName, response); taskCompletionSource.SetResult(response); try { context.IsSuccess = true; context.Metrics.TotalTime = stopwatch.ElapsedMilliseconds; } catch { } try { SemaphoreIsolationMarkSuccess(context, semaphoreIsolationInstance); } catch { } } } catch (CServiceException cex) { try { asyncRequestState.Complete(); Dictionary <string, string> addtionalInfo = GetClientInfo(context); addtionalInfo["ErrorCode"] = "FXD301004"; if (LogErrorWithRequestInfo) { addtionalInfo["RequestObject"] = TypeSerializer.SerializeToString(requestObject); } LogCServiceException(GetLogTitle(InternalServiceUtils.ServiceErrorTitle), cex, addtionalInfo); stopwatch.Stop(); context.IsSuccess = false; context.Error = cex; } catch { } try { if (IsCServiceExceptionValidationError(cex)) { SemaphoreIsolationMarkBadRequest(context, semaphoreIsolationInstance); } else { SemaphoreIsolationMarkFailure(context, semaphoreIsolationInstance); } } catch { } taskCompletionSource.TrySetException(cex); } catch (Exception ex1) { handleGeneralError(ex1); } finally { try { if (responseWatch.IsRunning) { responseWatch.Stop(); } context.Metrics.ExecutionTime = responseWatch.ElapsedMilliseconds; } catch { } ApplyRequestEndFilterSafe(context); } }; #endregion #region Request CallBack AsyncCallback getRequestCallback = asyncGetRequestResult => { bool success = true; try { if (asyncGetRequestResult.CompletedSynchronously) { } else { InitThreadLocalBaseUri(context); } using (Stream requestStream = EndGetRequestStream(context, webRequest, asyncGetRequestResult)) { try { context.CallFormat.StreamSerializer(requestObject, requestStream); } catch (Exception) { throw; } finally { } } context.Metrics.RequestSize = webRequest.ContentLength; responseWatch.Start(); BeginGetResponse(context, webRequest, getResponseCallback); } catch (Exception ex2) { success = false; handleGeneralError(ex2); } finally { try { requestWatch.Stop(); context.Metrics.SerializationTime = requestWatch.ElapsedMilliseconds; } catch { } if (!success) { ApplyRequestEndFilterSafe(context); } } }; #endregion requestWatch.Start(); BeginGetRequestStream(context, webRequest, getRequestCallback); } catch (Exception ex3) { handleGeneralError(ex3); ApplyRequestEndFilterSafe(context); } finally { ResetCurrentRequestTimeoutSetting(); } return(TryAddFaultHandler(taskCompletionSource.Task)); }