C# .NET Web Api应用程序在本地主机上调用其他Web Api应用程序时挂起

C# .NET Web Api应用程序在本地主机上调用其他Web Api应用程序时挂起,c#,.net,iis,localhost,webapi,C#,.net,Iis,Localhost,Webapi,在我的Web Api应用程序中,我尝试调用我的其他Api应用程序。应用程序托管在本地。呼叫是同步的,整个链如下所示: 客户端-[req]->EchoService-[req]->EchoService2-[resp]->EchoService-[resp]->Client 实际上,这些只是回显命令。问题是:当有3个或更多客户端并行调用第一个服务时,对第二个服务的调用将挂起 代码如下: EchoService2: public class Echo2Controller : ApiControll

在我的Web Api应用程序中,我尝试调用我的其他Api应用程序。应用程序托管在本地。呼叫是同步的,整个链如下所示:

客户端-[req]->EchoService-[req]->EchoService2-[resp]->EchoService-[resp]->Client

实际上,这些只是回显命令。问题是:当有3个或更多客户端并行调用第一个服务时,对第二个服务的调用将挂起

代码如下:

EchoService2:

public class Echo2Controller : ApiController
    {
        [Route("Echo/{Message}/{RequestID}/{SessionToken}")]
        public IHttpActionResult GetEcho(string Message, string RequestID, string SessionToken)
        {
            EchoResponse response = new EchoResponse();
            response.Payload.Message = "Echo 2: " + Message;
            response.Success = true;

            return Ok(response);
        }

    }
回声服务:

public class EchoController : ApiController
    {
        [Route("Echo/{Message}/{RequestID}/{SessionToken}")]
        public IHttpActionResult GetEcho(string Message, string RequestID, string SessionToken)
        {
            EchoResponse response = new EchoResponse();
            try
            {
                string echo2Resp = string.Empty;
                using (var client = new WebClient())
                {
                    **// STUCKS HERE WHEN 3 OR MORE CLIENTS**
                    string sResp = client.DownloadString("http://localhost/api/echoservice2/Echo/" + Message + "/2/3");  
                    EchoResponse echoResponse = JsonConvert.DeserializeObject<EchoResponse>(sResp);

                    echo2Resp = echoResponse.Payload.Message;
                }

                response.Payload.Message = "Echo: " + echo2Resp;
                response.Success = true;
            }
            catch(Exception ex)
            {
                response.Payload.Message = "Echo: Error!";
                response.Errors.Add(new Error() { Code = EErrorCodes.GeneralError, Type = EErrorType.Error, Message = ex.Message });
                response.Success = false;
            }           


            return Ok(response);
        }

    }
公共类EchoController:ApicController
{
[路由(“Echo/{Message}/{RequestID}/{SessionToken}”)]
公共IHttpActionResult GetEcho(字符串消息、字符串请求ID、字符串会话肯)
{
EchoResponse=新的EchoResponse();
尝试
{
字符串echo2Resp=string.Empty;
使用(var client=new WebClient())
{
**//当3个或更多客户**
string sResp=client.DownloadString(“http://localhost/api/echoservice2/Echo/“+消息+”/2/3“;
EchoResponse EchoResponse=JsonConvert.DeserializeObject(sResp);
echo2Resp=echoResponse.Payload.Message;
}
response.Payload.Message=“Echo:+echo2Resp;
回答:成功=正确;
}
捕获(例外情况除外)
{
response.Payload.Message=“Echo:Error!”;
添加(新错误(){Code=EErrorCodes.GeneralError,Type=EErrorType.Error,Message=ex.Message});
回答:成功=错误;
}           
返回Ok(响应);
}
}
客户端(控制台应用程序):

{
公共int超时{get;set;}
受保护的覆盖WebRequest GetWebRequest(Uri)
{
WebRequest lWebRequest=base.GetWebRequest(uri);
lWebRequest.Timeout=超时;
((HttpWebRequest)lWebRequest).ReadWriteTimeout=超时;
返回lWebRequest;
}
}
班级计划
{
静态void Main(字符串[]参数)
{
int taskscont=2;//当2-正常工作时,当3或更多-挂起时**
列表导入任务=新列表();
对于(int i=0;iThreadEcho());
导入任务。添加(导入任务);
importTask.Start();
}
Task.WaitAll(importTasks.ToArray());
}
私有静态void ThreadEcho()
{
整数计数=10;
var rnd=新随机(DateTime.Now.毫秒);
而(计数>0)
{
尝试
{
字符串消息=Guid.NewGuid().ToString();
string echoResp=string.Empty;
使用(var client=new MyWebClient())
{
client.Timeout=300000;
string sResp=client.DownloadString(“http://localhost/api/echoservice/Echo/“+消息+”/2/3“;
EchoResponse EchoResponse=JsonConvert.DeserializeObject(sResp);
echoResp=echoResponse.Payload.Message;
}
Console.WriteLine(string.Format(“[{0}][{1}]请求已完成:{2}”,
日期时间,现在,
System.Threading.Thread.CurrentThread.ManagedThreadId,
echoResp);
}
捕获(例外情况除外)
{
Console.WriteLine(string.Format(“[{0}][{1}]错误:{2}”,
日期时间,现在,
System.Threading.Thread.CurrentThread.ManagedThreadId,
(例如信息);
}
--计数;
系统线程线程睡眠(rnd.Next(100500));
}
}
}
尝试在VisualStudio中跟踪,但到目前为止,我发现EchoService2控制器(链中的最后一个)从未命中。甚至应用程序构造函数也不会被调用

在IIS日志文件中,除了几次看到代码“-500 0 64”外,没有任何错误。事件日志中也没有错误

我相信数字3只是巧合,问题的根本原因在于其他方面(IIS端有什么东西被阻止了?)


我被卡住了,没有想法了,任何关于如何追踪IIS内部发生的事情的帮助或提示都将受到高度赞赏

这可能是由于
WebRequest
中的默认连接限制为2。你可以试着提高这个限制。有关详细信息,请参阅使用wireshark或fiddler等嗅探器,并确认没有发生什么。我怀疑服务器有防止服务攻击的限制。“Visual Studio中的跟踪”远远不够。在.NET Framework上,应启用ASP.NET ETW,对于.NET Core,应启用其日志记录。只有当您完全看到所有的请求/响应时,您才有可能找到罪魁祸首。@devNull是的,看起来这是一个连接限制。你的链接指向了正确的方向-太好了!我已经设法增加了测试项目的限制。不幸的是,我仍然没有设法解决我的原始api服务的问题-它仍然坚持这2个连接的限制。我会在找到路的时候发布更新out@user1873711更改连接限制后是否重新启动iis?
{
        public int Timeout { get; set; }

        protected override WebRequest GetWebRequest(Uri uri)
        {
            WebRequest lWebRequest = base.GetWebRequest(uri);
            lWebRequest.Timeout = Timeout;
            ((HttpWebRequest)lWebRequest).ReadWriteTimeout = Timeout;
            return lWebRequest;
        }
    }


    class Program
    {
        static void Main(string[] args)
        {
            int tasksCount = 2; // WHEN 2 - works ok, WHEN 3 or more - hangs!**

            List<Task> importTasks = new List<Task>();

            for(int i = 0; i < tasksCount; ++i)
            {
                Task importTask = new Task(() => ThreadEcho());
                importTasks.Add(importTask);
                importTask.Start();
            }

            Task.WaitAll(importTasks.ToArray());

        }

        private static void ThreadEcho()
        {
            int count = 10;

            var rnd = new Random(DateTime.Now.Millisecond);

            while (count > 0)
            {
                try
                {
                    string message = Guid.NewGuid().ToString();
                    string echoResp = string.Empty;

                    using (var client = new MyWebClient())
                    {
                        client.Timeout = 300000;
                        string sResp = client.DownloadString("http://localhost/api/echoservice/Echo/" + message + "/2/3");
                        EchoResponse echoResponse = JsonConvert.DeserializeObject<EchoResponse>(sResp);

                        echoResp = echoResponse.Payload.Message;
                    }

                    Console.WriteLine(string.Format("[{0}] [{1}] Request completed: {2} ",
                        DateTime.Now,
                        System.Threading.Thread.CurrentThread.ManagedThreadId,
                        echoResp));
                }
                catch(Exception ex)
                {
                    Console.WriteLine(string.Format("[{0}] [{1}] Error: {2} ",
                        DateTime.Now,
                        System.Threading.Thread.CurrentThread.ManagedThreadId,
                        ex.Message));
                }

                --count;

                System.Threading.Thread.Sleep(rnd.Next(100, 500));
            }

        }
    }