详细功能:客户端是WPF,服务端是Web Service(C#),客户端请求查询服务器端是否有更新的版本,若有则下载更新。
开发工具:VS2013,在管理员权限下运行。
开发及测试环境:IIS6.0,电脑内核数量为4,逻辑处理器数量为8。
相关参数设置:IIS管理器下设置-应用程序池-网站的最大工作进程数为默认值1.客户端与Web Service的超时时间都是120秒。测试用的更新包大小为3101KB。采用log4net在服务器端记录日志。
问题描述:由于最终将发布在远程服务器上,带宽有限制,120秒的时间内,最多只能保证大约23个请求成功下载,其他的请求不可能成功。【计算方法:带宽*120秒/3101KB=25个。并且经测试,几乎都是保持在23个请求可以成功下载更新。(附:远程服务器环境为核心数2,线程数2,IIS6.0)】 于是想用Application["CountOnline"]来统计正在请求下载的客户端数量,假设这个数量已经超过了23,如果再有新的下载请求,那么就立刻返回“服务器忙”异常消息;否则就下载更新。每有一次连接请求,那么Application["CountOnline"]值加1;请求结束之后,Application["CountOnline"]值减1。采用多线程同时请求下载来模拟多客户端进行测试。
1、把web service发布到本地的开发机器的虚拟目录下,发现Application["CountOnline"]的值最大为3,根本不能突破3。注:本地环境下测试,无带宽限制。把Web Service发布到远程服务器上,Application["CountOnline"]最大为1。
2、若不发布web service,直接在WPF项目下,添加服务引用——发现“解决方案下的服务”,然后运行测试代码,发现Application["CountOnline"]的值最大可以达到8.
3、修改IIS管理器下设置-应用程序池-网站的最大工作进程数为10,此时若再引用本地的虚拟目录下的服务,Application["CountOnline"]的最大值依然是3,并且由于是最大工作进程数的限制变为10,导致记录的日志信息不完全。同样的,服务器端Application["CountOnline"]最大值依然是1.
Web Service主要代码如下:
[WebMethod(Description = "", EnableSession = true)]
public byte[] LoadFile(string software)
{
string filePath = Server.MapPath("Software/") + software;
FileStream fs = null;
if (File.Exists(filePath))
{
try
{
log.Info(String.Format("线程{0}进入请求时候,Application[\"count\"]:{1}", System.Threading.Thread.CurrentThread.ManagedThreadId, Application["CountOnline"]));
if (!(Application["CountOnline"] == null || (int)Application["CountOnline"] <= 23))
{
throw new SoapException("服务器正忙,请稍后再试!", SoapException.ServerFaultCode);
}
fs = new FileStream(filePath, FileMode.Open, FileAccess.Read);
return ConvertStreamToByteBuffer(fs);
}
catch (SoapException ex)
{
log.Error(String.Format("---------请求已经达到最大限度。"));
throw new SoapException("服务器正忙,请稍后再试!", SoapException.ServerFaultCode);
}
catch (Exception ex)
{
log.Error(String.Format("异常消息:{0}{1}堆栈:{2}{0}相关内容:{3}", ex.Message, Environment.NewLine, ex.StackTrace, ex.ToString()));
throw new SoapException(ex.ToString(), SoapException.ServerFaultCode);
}
finally
{
if(fs!=null)
{
fs.Flush();
fs.Close();
}
log.Info(String.Format("线程{0}执行完毕离开时候,Application[\"count\"]:{1}", System.Threading.Thread.CurrentThread.ManagedThreadId, Application["CountOnline"]));
Session.Abandon();
}
}
else
{
log.Error(filePath + "文件不存在");
throw new SoapException(filePath + "文件不存在", SoapException.ServerFaultCode);
}
}
public class Global : System.Web.HttpApplication
{
protected void Application_Start(object sender, EventArgs e)
{
if (Application["CountOnline"] == null)
{
Application["CountOnline"] = 0;
}
log4net.Config.XmlConfigurator.Configure(new FileInfo("Log4net.config"));
}
protected void Session_Start(object sender, EventArgs e)
{
Application.Lock();
int countOnline = (int)Application["CountOnline"];
countOnline++;
Application["CountOnline"] = countOnline;
Application.UnLock();
}
protected void Session_End(object sender, EventArgs e)
{
Application.Lock();
int countOnline = (int)Application["CountOnline"];
countOnline--;
Application["CountOnline"] = countOnline;
Application.UnLock();
}
}
客户端测试代码主要如下:
try
{
for (int i = 0; i <100; i++)
{
ThreadWithState tws = new ThreadWithState(i);
Thread t = new Thread(new ThreadStart(tws.ThreadProc));
t.Start();
}
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
public class ThreadWithState
{
private int i;
public ThreadWithState( int number)
{
i = number;
}
public void ThreadProc()
{
try
{
BasicHttpBinding binding = new BasicHttpBinding();
ServiceReference1.WebService1SoapClient ws;
binding.MaxReceivedMessageSize = 2147483647;
binding.MaxBufferPoolSize = 2147483647;
binding.CloseTimeout = new TimeSpan(0,0,120);
binding.SendTimeout = new TimeSpan(0, 0, 120);
ws = new ServiceReference1.WebService1SoapClient(binding, new EndpointAddress(new Uri("http://192.168.1.91:81/WebService1.asmx")));
System.Diagnostics.Stopwatch spw = new System.Diagnostics.Stopwatch();
spw.Start();
ws.Open();
byte[] file = ws.LoadFile("*****文件名****");
spw.Restart();
string time = System.DateTime.Now.ToString("_yyyy-MM-dd HH-mm-ss_ffff");
string downPath = @"c:\download\" + i + "" + time + ".zip";
FileStream fs = new FileStream(downPath, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite);
fs.Write(file, 0, file.Length);
fs.Flush();
fs.Dispose();
ws.Abort();
ws.Close();
Console.WriteLine(i + ",写入磁盘完成耗时:" + spw.ElapsedMilliseconds + ",线程id:" + System.Threading.Thread.CurrentThread.ManagedThreadId);
}
catch(Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
每一个新的请求,那么服务端应该都会新开一个线程,为什么我的服务器端的Application["CountOnline"]始终没有什么变化呢。我猜想是不是IIS或者还有哪个地方没有设置呢?还是我的代码有问题?已经在百度上面查询了好久,没有找到答案。请大家帮忙看看。
web service访问数量控制
- 写回答
- 好问题 0 提建议
- 追加酬金
- 关注问题
- 邀请回答
-
1条回答 默认 最新
- lhl_lqc 2015-07-20 03:37关注
建议你不要用sessionStart和sessionEnd对Application变量进行增减,而是通过对Application变量加锁的方式进行增减,这样能够保证多线程时Application变量的增减同步。举个例子,定义一个static object obj=new object();
lock(obj){
Application["count"]++;//or --;
}解决 无用评论 打赏 举报
悬赏问题
- ¥15 drone 推送镜像时候 purge: true 推送完毕后没有删除对应的镜像,手动拷贝到服务器执行结果正确在样才能让指令自动执行成功删除对应镜像,如何解决?
- ¥15 求daily translation(DT)偏差订正方法的代码
- ¥15 js调用html页面需要隐藏某个按钮
- ¥15 ads仿真结果在圆图上是怎么读数的
- ¥20 Cotex M3的调试和程序执行方式是什么样的?
- ¥20 java项目连接sqlserver时报ssl相关错误
- ¥15 一道python难题3
- ¥15 牛顿斯科特系数表表示
- ¥15 arduino 步进电机
- ¥20 程序进入HardFault_Handler