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