예제 #1
0
 /// <summary>
 /// <para>Sets up a module that enriches all requests with two auxiliary headers:</para>
 /// <list type="bullet">
 ///     <item><description><paramref name="priorityHeader"/> with the value of request's <see cref="RequestParameters.Priority"/></description></item>
 ///     <item><description><paramref name="identityHeader"/> with the value of configuration's <see cref="IClusterClientConfiguration.ClientApplicationName"/></description></item>
 /// </list>
 /// </summary>
 public static void SetupAuxiliaryHeaders(
     this IClusterClientConfiguration configuration,
     string priorityHeader = HeaderNames.RequestPriority,
     string identityHeader = HeaderNames.ApplicationIdentity)
 {
     configuration.AddRequestModule(new AuxiliaryHeadersModule(priorityHeader, identityHeader));
 }
예제 #2
0
 /// <summary>
 /// Inject latency to the every request retry with default latency performer
 /// </summary>
 /// <example>
 /// <code>
 ///   ------► + injected latency ---► replica(1..n)
 ///     ↑__________retry (1..n)__________________|
 /// </code>
 /// </example>
 /// <param name="configuration">IClusterClientConfiguration instance</param>
 /// <param name="latencyProvider">Func returning latency to inject</param>
 /// <param name="rateProvider">Func returning injection probability (rate)</param>
 public static void InjectLatencyOnEveryRetry(
     this IClusterClientConfiguration configuration,
     Func <TimeSpan> latencyProvider,
     Func <double> rateProvider)
 {
     configuration.AddRequestModule(new LatencyModule(new LatencyPerformer(), new RateManager(), latencyProvider, rateProvider), RequestModule.RequestRetry, ModulePosition.After);
 }
예제 #3
0
 /// <summary>
 /// <para>Adds given <paramref name="module"/> to configuration's <see cref="IClusterClientConfiguration.Modules"/> collection.</para>
 /// <para><paramref name="module"/> will be inserted into request module chain once near <paramref name="relatedModule"/>.</para>
 /// </summary>
 /// <param name="relatedModule">A module near which <paramref name="module"/> will be inserted.</param>
 /// <param name="module">A module to insert into request pipeline.</param>
 /// <param name="configuration">A configuration instance.</param>
 /// <param name="position">A relative position of <paramref name="module"/> from <paramref name="relatedModule"/>. This parameter is optional and has default value <see cref="ModulePosition.Before"/>.</param>
 public static void AddRequestModule(
     this IClusterClientConfiguration configuration,
     IRequestModule module,
     RequestModule relatedModule = RequestModule.Logging,
     ModulePosition position     = ModulePosition.Before)
 {
     configuration.AddRequestModule(module, RequestModulesMapping.GetModuleType(relatedModule), position);
 }
예제 #4
0
        /// <summary>
        /// Adds a <see cref="DistributedContextModule"/> to request modules pipeline and wraps transport with <see cref="DistributedContextTransport"/>.
        /// </summary>
        public static void SetupDistributedContext([NotNull] this IClusterClientConfiguration configuration)
        {
            configuration.AddRequestModule(new DistributedContextModule(), RequestModule.AuxiliaryHeaders);

            if (!(configuration.Transport is DistributedContextTransport))
            {
                configuration.Transport = new DistributedContextTransport(configuration.Transport);
            }
        }
        /// <summary>
        /// Sets up a replica budgeting mechanism with given parameters.
        /// </summary>
        /// <param name="configuration">A configuration to be modified.</param>
        /// <param name="storageKey">See <see cref="ReplicaBudgetingOptions.StorageKey"/>.</param>
        /// <param name="minutesToTrack">See <see cref="ReplicaBudgetingOptions.MinutesToTrack"/>.</param>
        /// <param name="minimumRequests">See <see cref="ReplicaBudgetingOptions.MinimumRequests"/>.</param>
        /// <param name="criticalRatio">See <see cref="ReplicaBudgetingOptions.CriticalRatio"/>.</param>
        public static void SetupReplicaBudgeting(
            this IClusterClientConfiguration configuration,
            string storageKey,
            int minutesToTrack   = ClusterClientDefaults.ReplicaBudgetingMinutesToTrack,
            int minimumRequests  = ClusterClientDefaults.ReplicaBudgetingMinimumRequests,
            double criticalRatio = ClusterClientDefaults.ReplicaBudgetingCriticalRatio)
        {
            var options = new ReplicaBudgetingOptions(storageKey, minutesToTrack, minimumRequests, criticalRatio);

            configuration.AddRequestModule(new ReplicaBudgetingModule(options), RequestModule.RequestExecution);
        }
        public static void SetupSingular(this IClusterClientConfiguration configuration, SingularClientSettings settings)
        {
            if (configuration == null)
            {
                throw new ArgumentNullException(nameof(configuration));
            }

            if (settings == null)
            {
                throw new ArgumentNullException(nameof(settings));
            }

            configuration.RequestTransforms.Add(
                new AdHocRequestTransform(
                    request => request
                    .WithHeader(SingularHeaders.Environment, settings.TargetEnvironment)
                    .WithHeader(SingularHeaders.Service, settings.TargetService)));

            configuration.TargetEnvironment = settings.TargetEnvironment;
            configuration.TargetServiceName = ServiceMeshEnvironmentInfo.UseLocalSingular
                ? $"{settings.TargetService} via ServiceMesh"
                : $"{settings.TargetService} via {SingularConstants.ServiceName}";

            var clusterConfigClient = ClusterConfigClient.Default;

            configuration.ClusterProvider = settings.AlternativeClusterProvider ??
                                            new ClusterConfigClusterProvider(clusterConfigClient, SingularConstants.CCTopologyName, configuration.Log);

            configuration.SetupWeighedReplicaOrdering(
                builder =>
            {
                var datacenters = DatacentersProvider.Get();
                builder.AddRelativeWeightModifier(new RelativeWeightSettings());
                builder.SetupAvoidInactiveDatacentersWeightModifier(datacenters);
                builder.SetupBoostLocalDatacentersWeightModifier(datacenters);
            });

            var forkingStrategy       = Strategy.Forking(SingularClientConstants.ForkingStrategyParallelismLevel);
            var idempotencyIdentifier = IdempotencyIdentifierCache.Get(clusterConfigClient, settings.TargetEnvironment, settings.TargetService);

            configuration.DefaultRequestStrategy = new IdempotencySignBasedRequestStrategy(idempotencyIdentifier, Strategy.Sequential1, forkingStrategy);

            configuration.MaxReplicasUsedPerRequest = SingularClientConstants.ForkingStrategyParallelismLevel;

            if (ServiceMeshEnvironmentInfo.UseLocalSingular)
            {
                var serviceMeshRequestModule = new ServiceMeshRequestModule(configuration.Log, idempotencyIdentifier);
                configuration.AddRequestModule(serviceMeshRequestModule, RequestModule.RequestExecution);
            }

            InitializeMetricsProviderIfNeeded(configuration, settings.MetricContext, clusterConfigClient);
        }
        private static void InitializeMetricsProviderIfNeeded(IClusterClientConfiguration configuration, IMetricContext?metricContext, IClusterConfigClient clusterConfigClient)
        {
            if (metricContext == null && MetricContextProvider.IsConfigured)
            {
                metricContext = MetricContextProvider.Get();
            }

            if (metricContext != null)
            {
                var environment = clusterConfigClient.Get(SingularConstants.EnvironmentNamePath)?.Value;
                if (environment == SingularConstants.ProdEnvironment || environment == SingularConstants.CloudEnvironment)
                {
                    var metricsProvider = MetricsProviderCache.Get(metricContext, environment, SloMetricsClientName);
                    configuration.AddRequestModule(new MetricsModule(metricsProvider));
                }
            }
        }
예제 #8
0
        /// <summary>
        /// Sets up an adaptive client throttling mechanism with given parameters.
        /// </summary>
        /// <param name="configuration">A configuration to be modified.</param>
        /// <param name="storageKey">See <see cref="AdaptiveThrottlingOptions.StorageKey"/>.</param>
        /// <param name="minutesToTrack">See <see cref="AdaptiveThrottlingOptions.MinutesToTrack"/>.</param>
        /// <param name="minimumRequests">See <see cref="AdaptiveThrottlingOptions.MinimumRequests"/>.</param>
        /// <param name="criticalRatio">See <see cref="AdaptiveThrottlingOptions.CriticalRatio"/>.</param>
        /// <param name="maximumRejectProbability">See <see cref="AdaptiveThrottlingOptions.MaximumRejectProbability"/>.</param>
        public static void SetupAdaptiveThrottling(
            this IClusterClientConfiguration configuration,
            string storageKey,
            int minutesToTrack              = ClusterClientDefaults.AdaptiveThrottlingMinutesToTrack,
            int minimumRequests             = ClusterClientDefaults.AdaptiveThrottlingMinimumRequests,
            double criticalRatio            = ClusterClientDefaults.AdaptiveThrottlingCriticalRatio,
            double maximumRejectProbability = ClusterClientDefaults.AdaptiveThrottlingRejectProbabilityCap)
        {
            var options = new AdaptiveThrottlingOptions(
                storageKey,
                minutesToTrack,
                minimumRequests,
                criticalRatio,
                maximumRejectProbability);

            configuration.AddRequestModule(new AdaptiveThrottlingModule(options), typeof(AbsoluteUrlSenderModule));
        }
        /// <summary>
        /// Sets up distributed tracing of HTTP requests using given <paramref name="configuration"/>.
        /// </summary>
        public static void SetupDistributedTracing([NotNull] this IClusterClientConfiguration config, [NotNull] TracingConfiguration configuration)
        {
            config.SetupDistributedContext();

            var tracingTransport = new TracingTransport(config.Transport, configuration)
            {
                TargetServiceProvider     = () => config.TargetServiceName,
                TargetEnvironmentProvider = () => config.TargetEnvironment
            };

            var tracingModule = new TracingModule(configuration)
            {
                TargetServiceProvider     = () => config.TargetServiceName,
                TargetEnvironmentProvider = () => config.TargetEnvironment
            };

            config.Transport = tracingTransport;
            config.AddRequestModule(tracingModule, typeof(DistributedContextModule));
        }
예제 #10
0
 /// <summary>
 /// Enables fixing of undertuned <see cref="System.Threading.ThreadPool"/> limits upon encountering request timeouts.
 /// </summary>
 public static void SetupThreadPoolLimitsTuning(this IClusterClientConfiguration configuration)
 {
     configuration.AddRequestModule(ThreadPoolTuningModule.Instance, typeof(LoggingModule));
 }
예제 #11
0
 /// <summary>
 /// Enables HTTP request method validation. Valid HTTP methods listed in <see cref="RequestMethods" /> class.
 /// </summary>
 public static void SetupHttpMethodValidation(this IClusterClientConfiguration configuration)
 {
     configuration.AddRequestModule(new HttpMethodValidationModule(), typeof(RequestValidationModule), ModulePosition.After);
 }