sql server带端口连接串
1、问题现象
本人为了学习租用了一台国外(日本linode)机房的服务器(vps),不要问我为什么,就是喜欢折腾。
服务器作为WebServer,系统为CentOS(linux),为了跑.net网站,使用了Mono的.net环境,和jexus网站容器。系统为CentOS 7 + Mono 3.8.0 + jexus 5.6
AWS有个1年免费的ECS,本着无事找事,并且有便宜白占不白占的原则,也去弄了一年AWS,万般折腾下,配了windows 2008 + Sql Server Express 2005 Adv用做测试数据库服务器,数据库实例名为SQLEXPRESS2005
公司在武汉电信机房有托管服务器,系统为Windows 2008 + IIS + SqlServer 2008,数据库实例为默认实例MSSQLSERVER
上述简称 日本WebServer,新加坡SqlServer,武汉WebServer,武汉SqlServer
前几日,新做了个MVC4测试项目,FTP传到 日本WebServer,数据库附加到 新加坡SqlServer,登陆提交时出现异常信息“sqlserver server does not exist or connection refused.”,然后各种记录log,各种重传DLL重启jexus重启系统,故障信旧,查看微软的在线帮助也没有解答。
然后,把网站上传到公司武汉WebServer,登陆,居然正常,进入后各种与数据库相关的操作,均正常。
这可奇了怪了,怒把数据库附加到武汉SqlServer,修改web.config中的连接字符串,武汉WebServer访问依旧正常,日本Webserver居然也正常!
新加坡SqlServer连接字符串部分connectionString="Data Source=52.74.251.34\SqlExpress2005,14433;
武汉SqlServer连接字符串部分connectionString="Data Source=61.22.65.22,14433;
如下图:
当时的第一思路,新加坡SqlServer或日本WebServer是不是无法互通,或者是否各自把对方的IP加入了黑名单,但经过各种排查,发现网络和防火墙均正常。
然后怒用wireshark对武汉和新加坡的sqlServer进行抓包,发现新加坡SqlServer的数据库端口居然没有入站报文。
网络正常,但又没有数据库入站连接,这真是无计可施。
最后在日本WebServer使用tcpdump进行抓包,down下来一看,突然让人眼前一亮。如下图,服务器居然把Data source的主机部分,识别成了域名,调用了DNS进行解析,但这地址当然是不存在的,这样也就解释了为啥无法连接的问题。
问题果然如此么,此时,对日本WebServer的Web.config中的数据库连接进行测试,原武汉SqlServer的data source部分由"61.22.65.22,11433"修改为"61.22.65.22\MSSQLSERVER,11433",果然也不能成功访问。
2、问题解决
由于SqlClient程序集,被封装在System.Data.dll中,win和Mono的此dll文件内包含的内容不尽相同,所以用win版的System.Data.dll进行替换也无济于事。
从http://download.mono-project.com/sources/mono/mono-3.8.0.tar.bz2下载mono3.8.0源码,找到目录mcs/class/System.Data/System.Data.SqlClient/,打开其中SqlConnection.cs文件,经过一番定位,终于找到了其解析数据库连接的方法ParseDataSource(),代码如下
1 private bool ParseDataSource (string theDataSource, out int thePort, out string theServerName) 2 { 3 theServerName = string.Empty; 4 string theInstanceName = string.Empty; 5 6 if (theDataSource == null) 7 throw new ArgumentException("Format of initialization string does not conform to specifications"); 8 9 thePort = DEFAULT_PORT; // default TCP port for SQL Server 10 bool success = true; 11 12 int idx = 0; 13 if ((idx = theDataSource.IndexOf (',')) > -1) { 14 theServerName = theDataSource.Substring (0, idx); 15 string p = theDataSource.Substring (idx + 1); 16 thePort = Int32.Parse (p); 17 } else if ((idx = theDataSource.IndexOf ('\\')) > -1) { 18 theServerName = theDataSource.Substring (0, idx); 19 theInstanceName = theDataSource.Substring (idx + 1); 20 21 // do port discovery via UDP port 1434 22 port = DiscoverTcpPortViaSqlMonitor (theServerName, theInstanceName); 23 if (port == -1) 24 success = false; 25 } else 26 theServerName = theDataSource; 27 28 if (theServerName.Length == 0 || theServerName == "(local)" || theServerName == ".") 29 theServerName = "localhost"; 30 31 if ((idx = theServerName.IndexOf ("tcp:")) > -1) 32 theServerName = theServerName.Substring (idx + 4); 33 34 return success; 35 }代码中绿色背景部分,是否有问题呢,当然是有问题的,哈哈~~~
比如,上面的连接字符串,用这个方法解析出来,theServerName=52.74.251.34\SqlExpress2005,当然不会正常运行。
知道了问题,就知道解决方法啦
修改代码如下
private bool ParseDataSource(string theDataSource, out int thePort, out string theServerName) { theServerName = string.Empty; string theInstanceName = string.Empty; if (theDataSource == null) throw new ArgumentException("Format of initialization string does not conform to specifications"); thePort = DEFAULT_PORT; // default TCP port for SQL Server bool success = true; theServerName = theDataSource; int idx = 0; if ((idx = theServerName.IndexOf(',')) > -1) { string p = theServerName.Substring(idx + 1); thePort = Int32.Parse(p); theServerName = theServerName.Substring(0, idx); } if ((idx = theServerName.IndexOf('\\')) > -1) { theInstanceName = theDataSource.Substring(idx + 1); theServerName = theServerName.Substring(0, idx); if (thePort <= 0) { // do port discovery via UDP port 1434 port = DiscoverTcpPortViaSqlMonitor(theServerName, theInstanceName); if (port == -1) success = false; } } if (theServerName.Length == 0 || theServerName == "(local)" || theServerName == ".") theServerName = "localhost"; if ((idx = theServerName.IndexOf("tcp:")) > -1) theServerName = theServerName.Substring(idx + 4); return success; }到此,故障排查就到此了,这样就结束了么,当然没有
由于mono是在linux编译安装,所以这个改动,还得ssh进服务器进行修改并重新编译才能生效。
使用putty,登陆日本WebServer,找到mono编译的源码目录(辛亏当时编译好后没有删除),依次进入mcs->class->System.Data->System.Data.SqlClient,vi SqlConnection.cs,修改掉上述代码,保存退出。
随便到mono主目录,分别执行make和make install,漫长的等待后,mono即编译成功。
重启jexus服务,/usr/jexus/jws restart,重启成功后,再次访问,新加坡SqlServer成功访问。
据此,这个BUG被修复。
3、感悟
在使用了成熟团队开发的框架时,项目相关部分出现异常,第一时间一定要相信他人的代码,因为很多时候,项目跑不起来,排查到最后可能都是自己犯了某低级错误。
在确定排除掉自己的BUG后,就需要针对异常现象进行全方面的排查了,在这里如果有发现某框架的一些蛛丝马迹,就需要对框架代码进排查了,下源码,反编译,用各种手段看到框架的逻辑代码,有没有问题自然就一清二楚了。
SQL server SQL代理 insert mysql sql代理服务
SQL Server HA - Install SQL Server 2012 on a Windows Server 2012 Cluster
在Windows Server2012上安装SQLServer2012图文教程电脑安装sqlserver2012
Windows Server 2012单服务器安装SQL Server 2012 SP1sql server 2008 sp1
Windoesserver2012server 安装mysql windows server 2012 r2 安装mysql
windows server 2012 r2能够支持sql server的版本 windows server 2012 r2 sql 2008
Windows Server 2016上安装SQL SERVER 2012 server2012安装sql2005
Windows server 2012 安装sql server2005 server2012安装sql2000
在Windows Server 2012 R2中搭建SQL Server 2012故障转移集群sql server 2012 r2安装教程
windows server 2016 和sql server 2012 兼容 sql server2012与2016哪个好用