コード例 #1
0
        /// <summary>
        /// Retrieves the next reachable <see cref="RemoteHost"/>.
        /// </summary>
        /// <param name="affinityToken">
        /// A string to generate a consistent affinity to a specific host within the set of available hosts.
        /// Identical strings will return the same host for a given pool of reachable hosts. A request ID is usually provided.
        /// </param>
        /// <returns>A reachable <see cref="RemoteHost"/>.</returns>
        /// <exception cref="EnvironmentException">Thrown when there is no reachable <see cref="RemoteHost"/> available.</exception>
        public IEndPointHandle GetNextHost(string affinityToken = null)
        {
            LastEndpointRequest = DateTime.UtcNow;

            var hostOverride = TracingContext.GetHostOverride(DeploymentIdentifier.ServiceName);

            if (hostOverride != null)
            {
                return(new OverriddenRemoteHost(DeploymentIdentifier.ServiceName, hostOverride.Hostname, hostOverride.Port ?? GetConfig().DefaultPort));
            }

            lock (_lock)
            {
                Health.Activate();

                if (ReachableHosts.Count == 0)
                {
                    var lastExceptionEndPoint = UnreachableHosts.FirstOrDefault();

                    // TODO: Exception throwing code should be in this class, not in another.
                    throw DiscoverySource.AllEndpointsUnreachable(EndPointsResult, lastExceptionEndPoint?.LastException, lastExceptionEndPoint == null ? null : $"{lastExceptionEndPoint.HostName}:{lastExceptionEndPoint.Port}", string.Join(", ", UnreachableHosts));
                }

                Counter++;

                ulong hostId = affinityToken == null ? Counter : (ulong)affinityToken.GetHashCode();

                return(ReachableHosts[(int)(hostId % (ulong)ReachableHosts.Count)]);
            }
        }
コード例 #2
0
        public async Task <IEndPointHandle> GetOrWaitForNextHost(CancellationToken cancellationToken)
        {
            var hostOverride = TracingContext.GetHostOverride(DeploymentIdentifier.ServiceName);

            if (hostOverride != null)
            {
                return(new OverriddenRemoteHost(DeploymentIdentifier.ServiceName, hostOverride.Hostname, hostOverride.Port ?? GetConfig().DefaultPort));
            }

            if (ReachableHosts.Count > 0)
            {
                return(GetNextHost());
            }

            lock (_lock)
            {
                if (FirstAvailableHostCompletionSource == null)
                {
                    FirstAvailableHostCompletionSource = new TaskCompletionSource <RemoteHost>();
                }

                cancellationToken.Register(() => FirstAvailableHostCompletionSource?.SetCanceled());
            }

            return(await FirstAvailableHostCompletionSource.Task.ConfigureAwait(false));
        }
コード例 #3
0
ファイル: RemoteHostPool.cs プロジェクト: ilanhu/microdot
        public async Task <RemoteHost> GetOrWaitForNextHost(CancellationToken cancellationToken)
        {
            var hostOverride = TracingContext.GetHostOverride(ServiceDeployment.ServiceName);

            if (hostOverride != null)
            {
                return(new OverriddenRemoteHost(ServiceDeployment.ServiceName, hostOverride, this));
            }

            if (ReachableHosts.Count > 0)
            {
                return(GetNextHost());
            }

            lock (_lock)
            {
                if (FirstAvailableHostCompletionSource == null)
                {
                    FirstAvailableHostCompletionSource = new TaskCompletionSource <RemoteHost>();
                }

                cancellationToken.Register(() => FirstAvailableHostCompletionSource?.SetCanceled());
            }

            return(await FirstAvailableHostCompletionSource.Task.ConfigureAwait(false));
        }
コード例 #4
0
        ///<inheritdoc />
        public async Task <NodeAndLoadBalancer> GetNode()
        {
            _lastUsageTime = DateTime.UtcNow;
            NodeAndLoadBalancer nodeAndLoadBalancer = null;
            string preferredEnvironment             = TracingContext.GetPreferredEnvironment();

            // 1. Use explicit host override if provided in request
            //    TBD: Theoretically if we only ever call a service through host overrides we might not have a health check for the service at all (though it is in use)
            var hostOverride = TracingContext.GetHostOverride(ServiceName);

            if (hostOverride != null)
            {
                return new NodeAndLoadBalancer {
                           Node                 = new Node(hostOverride.Host, hostOverride.Port),
                           LoadBalancer         = null,
                           PreferredEnvironment = preferredEnvironment ?? Environment.DeploymentEnvironment,
                }
            }
            ;

            // 2. Otherwise, use preferred environment if provided in request
            if (preferredEnvironment != null && (nodeAndLoadBalancer = await GetNodeAndLoadBalancer(preferredEnvironment, preferredEnvironment)) != null)
            {
                return(nodeAndLoadBalancer);
            }

            // 3. Otherwise, try use current environment
            if ((nodeAndLoadBalancer = await GetNodeAndLoadBalancer(Environment.DeploymentEnvironment, preferredEnvironment)) != null)
            {
                _healthStatus = new HealthMessage(Health.Healthy, message: null, suppressMessage: true); // No need for a health message since the load balancer we're returning already provides one
                return(nodeAndLoadBalancer);
            }

            // 4. We're in prod env and service is not deployed, no fallback possible
            if (Environment.DeploymentEnvironment == MASTER_ENVIRONMENT)
            {
                _healthStatus = new HealthMessage(Health.Unhealthy, "Service not deployed");
                throw ServiceNotDeployedException();
            }

            // 5. We're not in prod, but fallback to prod is disabled
            if (GetDiscoveryConfig().EnvironmentFallbackEnabled == false)
            {
                _healthStatus = new HealthMessage(Health.Unhealthy, "Service not deployed (and fallback to prod disabled)");
                throw ServiceNotDeployedException();
            }

            // 6. Otherwise, try fallback to prod
            if ((nodeAndLoadBalancer = await GetNodeAndLoadBalancer(MASTER_ENVIRONMENT, preferredEnvironment ?? Environment.DeploymentEnvironment)) != null)
            {
                _healthStatus = new HealthMessage(Health.Healthy, "Service not deployed, falling back to prod");
                return(nodeAndLoadBalancer);
            }

            _healthStatus = new HealthMessage(Health.Unhealthy, "Service not deployed, fallback to prod enabled but service not deployed in prod either");
            throw ServiceNotDeployedException();
        }
コード例 #5
0
        public async Task <object> Invoke(HttpServiceRequest request, Type resultReturnType, JsonSerializerSettings jsonSettings = null)
        {
            if (request == null)
            {
                throw new ArgumentNullException(nameof(request));
            }
            if (resultReturnType == null)
            {
                throw new ArgumentNullException(nameof(resultReturnType));
            }

            var hostOverride = TracingContext.GetHostOverride(ServiceName);

            if (hostOverride != null)
            {
                var httpRequest = CreateHttpRequest(request, jsonSettings, hostOverride);
            }
            else
            {
            }

            return(null);
        }