在客户端频繁并发的调用webservice时,高峰期导致访问webservice失败,重启IIS就可以了。
很简单的一个架构:C/S客户端--->webservice--->数据库
webservice程序: 一个提供数据库增删改的类--IDatabase
web服务类
public class Service : System.Web.Services.WebService
{
private IDbConnection dbcon;
private IDatabase dbbase;
/// 更新数据库
public void updata(string updataCommandText)
{
IDbConnection con;
//使用全局的IDbConnection
con = dbcon;
//新建一个IDbConnection
con = dbbase.GetDbConnection("ConnectionString");
dbbase.UpdataDb(updataCommandText, con);
}
}
几个疑问的地方 想请教下各位,先谢过!!!
1.在数据库查询时,是共用一个全局数据库连接,还是 每次新建一个IDbConnection?? 如果每次新建一个连接,在web访问比较频繁的话,连接过多的话会造成服务器资源耗尽, 可是会这样吗,网上有人多是推荐去新建一个连接,但这样并不会造成连接过多的情况,可是多没说出其缘由,,,,待解答
2,看论坛里有人的博客说:webservice是基于多线程的,那么在更新数据库函数updata中新建线程来执行访问操作是不是多余的?
3,在客户端调用webservice的,是每次调用新建一个webservice连接,还是公用一个全局的webservice连接??? --我现在使用的是每次新建一个webservice连接,因为对于客户端这种构造一个webservice的开销是微不足道(当然这不是最好的处理)
UpdataDb完后需要把 DbConnection 及时关掉。
不知道你的 UpdataDb的一般耗时是多少,请使用 BeginExecute 来让出请求线程,Service也请写成服务端异步的。
如果这样,数据库连接仍然不够用,请考虑使用MSMQ,将多条Update语句组合到一起,批量向数据库提交更新请求。
建议新建连接,共享一个连接的话,并发时会有问题.
如果新建连接的话,连接过多顶多也就是数据库连接池耗尽而已.
1)如果Connection不会用于多线程,建议每一个Request 一个新连接。当End_Request就关闭。
2)我觉得Server在任何情况下都不使用。如果需要异步的话,应该由客户端用多线程调用WebService就可以。
3)没有所谓。
1、数据库有最大连接数限制,并发量过大达到上限就会报错,而且频繁的创建关闭连接也要很大代价,还是使用数据库连接池吧,可以在连接字符串中设置,也可以自己写一个。不过你说的情况应该是高峰期时候webservice的并发访问请求超出IIS所能承受的最大并发连接数,导致请求阻塞引起的吧。
2.觉得没有必要
3.webservice生成的代理类不是线程安全的吧,如果使用一个全局实例,存在多线程或异步调用的话,返回值处理应该会有问题
谢谢大家的回复,问题还未解决,我还是加点分吧,希望大家再帮看下
IIS还是很站内存,后面给web服务设置独立应用程序池,设置CPU占用50%自动回收,服务端在高峰期不再很卡,但是web调用失败,
还是附上测试写的代码吧,
webservice代码
[WebMethod]
public DataSet Selectdata(string selectCommandText)
{
DataSet Set = new DataSet();
string sErr = "";
if (!SelectDs(selectCommandText, Set, ref sErr)) return null;
return Set;
}
[WebMethod]
public void updatedata(string updataCommandText)
{
string sErr = "";
UpDataDB(false, updataCommandText, "", ref sErr);
}
public IDbDataAdapter DbDat;
public IDbTransaction DbTran;
public Boolean SelectDs(string selectCommandText, DataSet dbSet, ref string sErr)
{
sErr = "";
try
{
using (IDbConnection conn = DbConsole.DbCon(ConnectionString))
{
DbDat.SelectCommand.CommandText = selectCommandText;
DbDat.SelectCommand.Connection = conn;
dbSet.Clear();
conn.Open();
DbDat.Fill(dbSet);
}
}
catch (SqlException sqlex)
{
sErr = sqlex.ToString();
return false;
}
return true;
}
public Boolean UpDataDB(Boolean IsStarTran, string updataCommandText, string splitStr, ref string sErr)
{
try
{
if (String.IsNullOrEmpty(splitStr)) splitStr = "DBSplitStr"; //默认分隔符
string[] sql = Regex.Split(updataCommandText, splitStr, RegexOptions.IgnoreCase);
using (IDbConnection conn = DbConsole.DbCon(ConnectionString))
{
//绑定数据库连接和事务对象
IDbCommand dbCom = DbDat.UpdateCommand;
dbCom.Connection = conn;
conn.Open();
if (IsStarTran)
{
DbTran = conn.BeginTransaction();
dbCom.Transaction = DbTran;
}
foreach (string sqlStr in sql)
{
dbCom.CommandText = sqlStr;
dbCom.ExecuteNonQuery();
}
if (IsStarTran) DbTran.Commit();
}
}
catch (SqlException sqlEx)
{
if (IsStarTran) DbTran.Rollback();
sErr = sqlEx.ToString();
return false;
}
catch (Exception Ex)
{
sErr += Ex.ToString();
return false;
}
return true;
}
客户端,用多个时钟new线程 不停调用web服务:
timer3.Interval = 1000;
timer3.Tick += new EventHandler((o, ev) => { new Thread(InsertAndUpdate).Start(); });
timer3.Enabled = true;
private void InsertAndUpdate()
{
try
{
localhost.Service server = new localhost.Service();
server.Url = sUrl;
server.updatedata("insert into Test(id,username,logintime,other,other1) values('00','22',getdate(),'" + Environment.MachineName + "','66')");
server.updatedata("update Test set id='01' where id='00'");
server.Selectdata("select * from Test ");
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
表Test(id,username,logintime,other,other1) 为测试用的一个表