private static CosmosHttpClient CreateHelper( HttpClient httpClient, HttpMessageHandler httpMessageHandler, TimeSpan requestTimeout, UserAgentContainer userAgentContainer, ApiType apiType, ICommunicationEventSource eventSource) { if (httpClient == null) { throw new ArgumentNullException(nameof(httpClient)); } httpClient.Timeout = requestTimeout > CosmosHttpClientCore.GatewayRequestTimeout ? requestTimeout : CosmosHttpClientCore.GatewayRequestTimeout; httpClient.DefaultRequestHeaders.CacheControl = new CacheControlHeaderValue { NoCache = true }; httpClient.AddUserAgentHeader(userAgentContainer); httpClient.AddApiTypeHeader(apiType); // Set requested API version header that can be used for // version enforcement. httpClient.DefaultRequestHeaders.Add(HttpConstants.HttpHeaders.Version, HttpConstants.Versions.CurrentVersion); httpClient.DefaultRequestHeaders.Add(HttpConstants.HttpHeaders.Accept, RuntimeConstants.MediaTypes.Json); return(new CosmosHttpClientCore( httpClient, httpMessageHandler, eventSource)); }
public static CosmosHttpClient CreateWithConnectionPolicy( ApiType apiType, ICommunicationEventSource eventSource, ConnectionPolicy connectionPolicy, HttpMessageHandler httpMessageHandler, EventHandler <SendingRequestEventArgs> sendingRequestEventArgs, EventHandler <ReceivedResponseEventArgs> receivedResponseEventArgs) { if (connectionPolicy == null) { throw new ArgumentNullException(nameof(connectionPolicy)); } Func <HttpClient> httpClientFactory = connectionPolicy.HttpClientFactory; if (httpClientFactory != null) { if (sendingRequestEventArgs != null && receivedResponseEventArgs != null) { throw new InvalidOperationException($"{nameof(connectionPolicy.HttpClientFactory)} can not be set at the same time as {nameof(sendingRequestEventArgs)} or {nameof(ReceivedResponseEventArgs)}"); } HttpClient userHttpClient = httpClientFactory.Invoke() ?? throw new ArgumentNullException($"{nameof(httpClientFactory)} returned null. {nameof(httpClientFactory)} must return a HttpClient instance."); return(CosmosHttpClientCore.CreateHelper( httpClient: userHttpClient, httpMessageHandler: httpMessageHandler, requestTimeout: connectionPolicy.RequestTimeout, userAgentContainer: connectionPolicy.UserAgentContainer, apiType: apiType, eventSource: eventSource)); } if (httpMessageHandler == null) { httpMessageHandler = CosmosHttpClientCore.CreateHttpClientHandler( gatewayModeMaxConnectionLimit: connectionPolicy.MaxConnectionLimit, webProxy: null); } if (sendingRequestEventArgs != null || receivedResponseEventArgs != null) { httpMessageHandler = CosmosHttpClientCore.CreateHttpMessageHandler( httpMessageHandler, sendingRequestEventArgs, receivedResponseEventArgs); } HttpClient httpClient = new HttpClient(httpMessageHandler); return(CosmosHttpClientCore.CreateHelper( httpClient: httpClient, httpMessageHandler: httpMessageHandler, requestTimeout: connectionPolicy.RequestTimeout, userAgentContainer: connectionPolicy.UserAgentContainer, apiType: apiType, eventSource: eventSource)); }
private CosmosHttpClientCore( HttpClient httpClient, HttpMessageHandler httpMessageHandler, ICommunicationEventSource eventSource) { this.httpClient = httpClient ?? throw new ArgumentNullException(nameof(httpClient)); this.eventSource = eventSource ?? throw new ArgumentNullException(nameof(eventSource)); this.HttpMessageHandler = httpMessageHandler; }
public GatewayStoreClient( CosmosHttpClient httpClient, ICommunicationEventSource eventSource, JsonSerializerSettings serializerSettings = null) { this.httpClient = httpClient; this.SerializerSettings = serializerSettings; this.eventSource = eventSource; }
public StoreClientFactory( Protocol protocol, int requestTimeoutInSeconds, int maxConcurrentConnectionOpenRequests, UserAgentContainer userAgent = null, // optional for both HTTPS and RNTBD ICommunicationEventSource eventSource = null, // required for HTTPS, not used for RNTBD string overrideHostNameInCertificate = null, // optional for RNTBD, not used for HTTPS int openTimeoutInSeconds = 0, // optional for RNTBD, not used for HTTPS int idleTimeoutInSeconds = 1800, // optional for both HTTPS and RNTBD int timerPoolGranularityInSeconds = 0, // optional for RNTBD, not used for HTTPS int maxRntbdChannels = ushort.MaxValue, // RNTBD int rntbdPartitionCount = 1, // RNTBD int maxRequestsPerRntbdChannel = 30, // RNTBD int receiveHangDetectionTimeSeconds = 65, // RNTBD int sendHangDetectionTimeSeconds = 10, // RNTBD Func <TransportClient, TransportClient> transportClientHandlerFactory = null, // Interceptor factory bool enableCpuMonitor = true) { // <=0 means idle timeout is disabled. // valid value: >= 10 minutes if (idleTimeoutInSeconds > 0 && idleTimeoutInSeconds < 600) { throw new ArgumentOutOfRangeException(nameof(idleTimeoutInSeconds)); } if (protocol == Protocol.Https) { if (eventSource == null) { throw new ArgumentOutOfRangeException("eventSource"); } this.transportClient = new HttpTransportClient(requestTimeoutInSeconds, eventSource, userAgent, idleTimeoutInSeconds); } else if (protocol == Protocol.Tcp) { if (maxRntbdChannels <= 0) { throw new ArgumentOutOfRangeException(nameof(maxRntbdChannels)); } if ((rntbdPartitionCount < 1) || (rntbdPartitionCount > 8)) { throw new ArgumentOutOfRangeException(nameof(rntbdPartitionCount)); } if (maxRequestsPerRntbdChannel <= 0) { throw new ArgumentOutOfRangeException(nameof(maxRequestsPerRntbdChannel)); } if (maxRntbdChannels > ushort.MaxValue) { DefaultTrace.TraceWarning( "The value of {0} is unreasonably large. Received: {1}. " + "Use {2} to represent \"effectively infinite\".", nameof(maxRntbdChannels), maxRntbdChannels, ushort.MaxValue); } const int minRecommendedMaxRequestsPerChannel = 10; const int maxRecommendedMaxRequestsPerChannel = 10000; if (maxRequestsPerRntbdChannel < minRecommendedMaxRequestsPerChannel) { DefaultTrace.TraceWarning( "The value of {0} is unreasonably small. Received: {1}. " + "Small values of {0} can cause a large number of RNTBD " + "channels to be opened to the same back-end. Reasonable " + "values are between {2} and {3}", nameof(maxRequestsPerRntbdChannel), maxRequestsPerRntbdChannel, minRecommendedMaxRequestsPerChannel, maxRecommendedMaxRequestsPerChannel); } if (maxRequestsPerRntbdChannel > maxRecommendedMaxRequestsPerChannel) { DefaultTrace.TraceWarning( "The value of {0} is unreasonably large. Received: {1}. " + "Large values of {0} can cause significant head-of-line " + "blocking over RNTBD channels. Reasonable values are between {2} and {3}", nameof(maxRequestsPerRntbdChannel), maxRequestsPerRntbdChannel, minRecommendedMaxRequestsPerChannel, maxRecommendedMaxRequestsPerChannel); } // Not related to maxRecommendedMaxRequestsPerChannel. const int minRequiredSimultaneousRequests = 10000; if (checked (maxRntbdChannels * maxRequestsPerRntbdChannel) < minRequiredSimultaneousRequests) { DefaultTrace.TraceCritical( "The number of simultaneous requests allowed per backend " + "is unreasonably small. Received {0} = {1}, {2} = {3}. " + "Reasonable values are at least {4}", nameof(maxRntbdChannels), maxRntbdChannels, nameof(maxRequestsPerRntbdChannel), maxRequestsPerRntbdChannel, minRequiredSimultaneousRequests); } const int minReceiveHangDetectionTimeSeconds = 65; const int maxReceiveHangDetectionTimeSeconds = 180; if (receiveHangDetectionTimeSeconds < minReceiveHangDetectionTimeSeconds) { DefaultTrace.TraceWarning( "The value of {0} is too small. Received {1}. Adjusting to {2}", nameof(receiveHangDetectionTimeSeconds), receiveHangDetectionTimeSeconds, minReceiveHangDetectionTimeSeconds); receiveHangDetectionTimeSeconds = minReceiveHangDetectionTimeSeconds; } if (receiveHangDetectionTimeSeconds > maxReceiveHangDetectionTimeSeconds) { DefaultTrace.TraceWarning( "The value of {0} is too large. Received {1}. Adjusting to {2}", nameof(receiveHangDetectionTimeSeconds), receiveHangDetectionTimeSeconds, maxReceiveHangDetectionTimeSeconds); receiveHangDetectionTimeSeconds = maxReceiveHangDetectionTimeSeconds; } const int minSendHangDetectionTimeSeconds = 2; const int maxSendHangDetectionTimeSeconds = 60; if (sendHangDetectionTimeSeconds < minSendHangDetectionTimeSeconds) { DefaultTrace.TraceWarning( "The value of {0} is too small. Received {1}. Adjusting to {2}", nameof(sendHangDetectionTimeSeconds), sendHangDetectionTimeSeconds, minSendHangDetectionTimeSeconds); sendHangDetectionTimeSeconds = minSendHangDetectionTimeSeconds; } if (sendHangDetectionTimeSeconds > maxSendHangDetectionTimeSeconds) { DefaultTrace.TraceWarning( "The value of {0} is too large. Received {1}. Adjusting to {2}", nameof(sendHangDetectionTimeSeconds), sendHangDetectionTimeSeconds, maxSendHangDetectionTimeSeconds); sendHangDetectionTimeSeconds = maxSendHangDetectionTimeSeconds; } this.fallbackClient = new RntbdTransportClient( requestTimeoutInSeconds, maxConcurrentConnectionOpenRequests, userAgent, overrideHostNameInCertificate, openTimeoutInSeconds, idleTimeoutInSeconds, timerPoolGranularityInSeconds); this.transportClient = new Rntbd.TransportClient( new Rntbd.TransportClient.Options(TimeSpan.FromSeconds(requestTimeoutInSeconds)) { MaxChannels = maxRntbdChannels, PartitionCount = rntbdPartitionCount, MaxRequestsPerChannel = maxRequestsPerRntbdChannel, ReceiveHangDetectionTime = TimeSpan.FromSeconds(receiveHangDetectionTimeSeconds), SendHangDetectionTime = TimeSpan.FromSeconds(sendHangDetectionTimeSeconds), UserAgent = userAgent, CertificateHostNameOverride = overrideHostNameInCertificate, OpenTimeout = TimeSpan.FromSeconds(openTimeoutInSeconds), TimerPoolResolution = TimeSpan.FromSeconds(timerPoolGranularityInSeconds), IdleTimeout = TimeSpan.FromSeconds(idleTimeoutInSeconds), EnableCpuMonitor = enableCpuMonitor }); } else { throw new ArgumentOutOfRangeException("protocol", protocol, "Invalid protocol value"); } this.protocol = protocol; if (transportClientHandlerFactory != null) { this.fallbackClient = transportClientHandlerFactory(this.fallbackClient); this.transportClient = transportClientHandlerFactory(this.transportClient); } }