
1IP+SID方式
[csharp] view plaincopyprint
DbHelperOracleconnectionString = stringFormat(@"Data Source=(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = {0})(PORT = 1521))
)
(CONNECT_DATA =
(SID = {1})
(SERVER = DEDICATED)
)
);User Id={2};Password={3};",
txtDBServerIPTextTrim(), txtOracleSIDTextTrim(), txtDBUserNameTextTrim(), txtDBPasswordTextTrim());
这种方式不需要在Oracle Net Manager管理中添加链接配置信息。
2 2配置链接方式,
在Oracle Net Manager管理中添加链接配置信息,然后链接字符串如下写法:
[csharp] view plaincopyprint
Data Source=TORCL;User Id=myUsername;Password=myPassword;
另外其他的连接方式,参考如下,从其他网站转来的:
Oracle连接字符串总结
Oracle XE
标准连接
Oracle XE(或者"Oracle Database 10g Express Edition")是一个简单免费发布的版本。
以下是语法格式:
Driver=(Oracle in XEClient);dbq=111213199:1521/XE;Uid=myUsername;Pwd=myPassword;
ODBC
新版本连接方式
以下是语法格式:
Driver={Microsoft ODBC for Oracle};Server=myServerAddress;Uid=myUsername;Pwd=myPassword;
老版本连接方式
以下是语法格式:
Driver={Microsoft ODBC Driver for Oracle};ConnectString=OracleServerworld;Uid=myUsername;Pwd=myPassword;
OLE DB, OleDbConnection (NET)
标准安全连接
此连接方式使用来自微软的Provider。
以下是语法格式:
Provider=msdaora;Data Source=MyOracleDB;User Id=myUsername;Password=myPassword;
信任连接
以下是语法格式:
Provider=msdaora;Data Source=MyOracleDB;Persist Security Info=False;Integrated Security=Yes;
标准安全连接
此连接方式使用来自Oracle的Provider。
以下是语法格式:
Provider=OraOLEDBOracle;Data Source=MyOracleDB;User Id=myUsername;Password=myPassword;
信任连接
以下是语法格式:
Provider=OraOLEDBOracle;Data Source=MyOracleDB;OSAuthent=1;
以下是语法格式:
Provider=OraOLEDBOracle;Data Source=(DESCRIPTION=(CID=GTU_APP)(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=myHost)(PORT=myPort)))(CONNECT_DATA=(SID=MyOracleSID)(SERVER=DEDICATED)));User Id=myUsername;Password=myPassword;
OracleDataAccessClientOracleConnection
标准连接
以下是语法格式:
Data Source=TORCL;User Id=myUsername;Password=myPassword;
带integrated security的连接
以下是语法格式:
Data Source=TORCL;Integrated Security=SSPI;
带 ODPNET 不带 tnsnamesora的连接
以下是语法格式:
Data Source=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=MyHost)(PORT=MyPort)))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=MyOracleSID)));User Id=myUsername;Password=myPassword;
OracleConnection, Oracle Data Provider, ODPNET, SystemDataOracleClientOracleConnection
标准连接
以下是语法格式:
Data Source=MyOracleDB;Integrated Security=yes
仅在Oracle8i release 3 或更高版本
指明用户密与密码的连接
以下是语法格式:
Data Source=MyOracleDB;User Id=myUsername;Password=myPassword;Integrated Security=no;
这是另一种连接方式不依赖你的DNSYou create a connection string based on the format used in the tnsnamesora file without the need to actually have one of these files on the client pc
以下是语法格式:
SERVER=(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=MyHost)(PORT=MyPort))(CONNECT_DATA=(SERVICE_NAME=MyOracleSID)));uid=myUsername;pwd=myPassword;
Some reported problems with the one above and Visual Studio Use the next one if you've encountered problems
以下是语法格式:
Data Source=(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=MyHost)(PORT=MyPort))(CONNECT_DATA=(SERVICE_NAME=MyOracleSID)));User Id=myUsername;Password=myPassword;
使用连接池
连接池服务如果找不到一个完全匹配连接字符串的连接,他将会创建一个。如果能找到该连接,将会重新使用。
以下是语法格式:
Data Source=myOracleDB;User Id=myUsername;Password=myPassword;Min Pool Size=10;Connection Lifetime=120;Connection Timeout=60;Incr Pool Size=5;Decr Pool Size=2;
Windows验证
以下是语法格式:
Data Source=myOracleDB;User Id=/;
特权连接
使用SYSOPER的特权
以下是语法格式:
Data Source=myOracleDB;User Id=SYS;Password=SYS;DBA Privilege=SYSOPER;
利用密码终止函数
当第一次打开连接时,当打开链接后,一个密码过期错误被抛出,捕获这个错误并执行OpenWithNewPassword命令行设置新密码。
以下是语法格式:
Data Source=myOracleDB;User Id=myUsername;Password=myPassword;
oConnOpenWithNewPassword(sTheNewPassword);
代理验证
以下是语法格式:
Data Source=myOracleDB;User Id=myUsername;Password=myPassword;Proxy User Id=pUserId;Proxy Password=pPassword;
Core Labs OraDirect (NET)
标准连接
以下是语法格式:
User ID=myUsername;Password=myPassword;Host=ora;Pooling=true;Min Pool Size=0;Max Pool Size=100;Connection Lifetime=0;
Data Shape
MS Data Shape
以下是语法格式:
Provider=MSDataShape1;Persist Security Info=False;Data Provider=MSDAORA;Data Source=orac;User Id=myUsername;Password=myPassword;
分布式:服务分散部署在不同服务器组成一个整体应用,分散压力,解决高并发。
假设访问量特别大,就可以做成分布式,将一个大项目拆分出来单独运行。跟cdn一样的机制。
Redis分布式:将redis中的数据分布到不同的服务器上,每台服务器存储不同内容。Mysql集群是每台服务器都存放相同数据。分布式部署:系统应用部署在2台或以上服务器或虚拟机上,服务间通过RPC、WCF(包含WebService)等交互,即可称作分布式部署。微服务也算作分布式的一种,反之则不然。分布式优点:1、将模块拆分,使用接口通信,降低模块之间的耦合度。2、将项目拆分成若干个子项目,不同团队负责不同子项目。3、增加功能时只需再加一个子项目,调用其它系统接口即可。4、可灵活进行分布式部署。5、提高代码的复用性,比如service层,如果不采用分布式rest服务方式架构,在手机Wap商城、微信商城、PC、Android、ios每个端都要写一个service层逻辑,开发量大,难以维护和一起升级,此时可采用分布式rest服务方式共用一个service层。缺点:系统之间交互要使用远程通信,接口开发增大工作量,但利大于弊。微服务:可单独部署运行的微小服务,一个服务只完成单一功能分散能力,服务之间通过RPC等交互,至少有一个数据库。用户量过大高并发时,建议将应用拆解为多个子系统,各自隔离,独立负责功能。缺点:服务数量大,后期运维较难。分布式、微服务区别:分布式依赖整体组合,是系统的部署方式;微服务是架构设计方式,粒度更小,服务之间耦合度更低。独立小团队负责,敏捷性更高。集群:多台服务器复制部署相同应用,由负载均衡共同对外提供服务,逻辑功能仍是单体应用。项目如果跑在一台机器上,这台机器如果出现故障,或者用户请求量比较高一台机器支撑不住,网站可能就访问不了。那怎么解决呢?就需要使用多台机器,复制部署一样的程序,让几个机器同时运行网站。那怎么分发请求到所有机器上?所以负载均衡的概念就出现了。负载均衡:将请求分发以分摊服务器压力。基于反向代理能将所有的请求根据指定的策略算法,分发到不同的服务器上。实现负载均衡常用Nginx、LVS。负载均衡服务器出现问题了怎么办?所有冗余的概念就出现了。冗余:两台或多台服务器,一个主服务器,一个从服务器。假设一个主服务器的负载均衡服务器出现问题,从服务器能替代主服务器来继续负载均衡。实现的方式就是使用Keepalive来抢占虚拟主机。双机双工模式:目前Cluster(集群)的一种形式,两台服务器均为活动状态,同时运行相同的应用,保证整体的性能,也实现了负载均衡和互为备份。WEB服务器或FTP服务器等用此种方式比较多。实现多台服务器代码(文件)同步方案:1、负载均衡中实现代码同步rsync。2、rsync+inotify逐一文件监听并实时同步。3、实现redis共享session。既然你用WCF,为什么还让客户端连接数据库呢?重新设计一下!
客户端只知道服务器的存在,数据库对客户端应该是透明的;
客户端只是想服务器发出请求,至于该请求的处理是对于数据库还是内存或者其他,客户端不需要知道,只要得到服务器的处理结果就可以。
另外,无论客户端还是服务器,用一个数据库连接是不应该的,遇上多线程就麻烦了:不做同步处理会产生错误,做同步处理效率又不行……
------------
你数据库连接使用不对,如果只用一个连接,别说事务,就是并发的普通处理都可能异常;应该每个请求都创建连接、打开、关闭、释放。从跨时区的角度对DateTime这个我们熟知的类型进行了深入探讨,它们都是为这篇文章作的准备工作。在接下来的两篇文章中,我们将完整的介绍如果在一个分布式系统中处理时区的问题。
一、场景以及需求
为了让大家本文介绍的主题有一个比较直观的认识,我们给出一个具体的应用场景。一个跨国公司开发一套统一的办公系统,供遍布全球的所有分公司使用。客户端的UI采用Smart Client (Windows Forms应用),而主要的业务逻辑均通过WCF服务的形式提供。我们将承载业务服务的服务器成为应用服务器,应用服务器部属于中国境内(东8区)。主要的客户端(分公司)分布于三个主要的国家和地区:北美、欧州和澳洲。
不论客户端和服务器之间,还是不同的客户端之间所处的时区均不相同,在进行时间处理的时候就会遇到一些麻烦:某个客户端通过服务调用获取的时间值应该基于哪个时区?对于这个问题,不同的场景可能有不同的要求。在大部分情况下,我们希望获取的时间值就是基于客户端的本地时区。不过也有些场景我们希望获取的时间值对应的时区是描述对象基于的那个时区。比如说,美国分公司于当地时间9月1号早8点举行开业典礼,欧洲分公司员工读取这条信息就没有必要将时间转换成基于本地时区的时间。
不过,本文不考虑这种情况,我们的最终要求是:客户端应用根本不用考虑时区问题,就像是一个单纯的本地应用一样。客户端调用服务传入的时间是DateTimeKindLocal时间或者DateTimeKindUnspecified时间,同理通过服务调用返回的时间也应该是基于客户端所在时区的时间。
二、解决方案实现原理
现在我们就来谈谈如何解决上面提出的问题。既然时区的处理不能在客户端做,换言之就必须在服务端实现。我们的一个前提是:在数据库中不存储时区的任何信息。在这样一个前提下实现上述的目标,需要解决两个问题:时间的保存和时间获取。
在时间的保存方面,既然数据库中能保存任何时区偏移之类的信息。在这种情况下,我们必须让所有保存在数据库中的时间都是基于同一个时区。我们可以选择应用服务器所在的时区,也可以直接采用UTC时间。我们的方案采用后者,即数据库所有时间保存为UTC时间 。
时间在数据库中的存储形式确定了,现在又出现一个问题:客户端传来的时间为客户端所在时区的当地时间,服务端接收到客户端发送的时间后,需要基于客户端相应时区转换成UTC时间才能保存到数据库。那么,服务端如何获取客户端所在的时区信息呢?将其作为服务 *** 作的参数肯定是不可取的。
如果你看过我之前的WCF系列文章,可能会记得我有一篇介绍如何通过WCF扩展实现在客户端和服务端之间传递上下文的文章:《通过WCF Extension实现Context信息的传递》。在这篇文章中我通过WCF扩展实现了将可户端的Culture和UICulture自动传向了服务端,从而确保两边保存一样的语言文化环境上下文。如果我们能够将基于客户端本地的TimeZoneInfo作为上下文进行传递,就能解决服务端对客户端的时区识别问题了。
关于保存时间的处理大体可以通过上面的序列图(点击看大图)来描述。客户端将基于本地时区的DateTimeKindLocal或者DateTimeKindUnspecified时间作为输入 *** 作调用某个服务,与此同时,本地的TimeZoneInfo序列化后作为上下文传递到服务端。服务端接将接收到的时间,根据接收到TimeZoneInfo上下文转换成DateTimeKindUtc时间,并保存到数据库中。
当客户端调用服务获取某个时间的时候,本地的同样作为上下文信息被传递到服务端。借助于这个TimeZoneInfo,服务端可以将数据库中以UTC形式保存的时间转换成基于客户端时区的DateTimeKindLocal时间。右图(点击看大图)所示的序列图反映了这个过程。
三、TimeZoneInfo的序列化问题
在《谈谈你最熟悉的SystemDateTime[上篇]》对TimeZoneInfo这个类进行介绍中,我说该类是可以被序列化的,序列化对于解决跨时区问题很重要。就是因为我们需要将TimeZoneInfo作为上下文在客户端和服务端进行传递,换言之,就是将TimeZoneInfo对象进行序列化,将序列化后的内容放入出栈消息(Outgoing Message)的消息报头(Message Header)中。
不过关于TimeZoneInfo对象序列化,我们一般并不会真正地将整个TimeZoneInfo对象交给序列化器去做序列化,而是利用定义在TimeZoneInfo中的两个特殊的方法来进行序列化和反序列化的工作。一个是实例方法ToSerializedString,将TimeZoneInfo转换成序列化后的一个字符串;另一个则静态方法FromSerializedString,对序列化后的字符转进行反序列化生成TimeZoneInfo对象。这两个方法的定义如下:
1: [Serializable]
2: public sealed class TimeZoneInfo
3: {
4: //Others
5: public static TimeZoneInfo FromSerializedString(string source);
6: public string ToSerializedString();
7: }
下面的代码演示了通过上述的这两个方法对TimeZoneInfo的序列化和反序列化的实现:
1: string serializedString = TimeZoneInfoLocalToSerializedString();
2: ConsoleWriteLine("SerializedString: {0}\n", serializedString);
3: TimeZoneInfo deserializedTimeZone = TimeZoneInfoFromSerializedString(serializedString);
4: ConsoleWriteLine("deserializedTimeZoneEquals(TimeZoneInfoLocal) {0}", deserializedTimeZoneEquals(TimeZoneInfoLocal));
5: ConsoleWriteLine("deserializedTimeZone == TimeZoneInfoLocal {0}", deserializedTimeZone == TimeZoneInfoLocal);
下面是输出结果,从中我们看出最终被序列化后的文本的内容。此外,输出结果也反映两个另一个信息:两个包含时区信息的TimeZoneInfo对象,调用Equals方法和使用== *** 作符得到不一样的结果。个人觉得这是微软作得不太到位的地方。
1: SerializedString: China Standard Time;480;(UTC+08:00) Beijing, Chongqing, Hong Kong, Urumqi;China Standard Time;China Daylight Time;;
2:
3: deserializedTimeZoneEquals(TimeZoneInfoLocal) True
4: deserializedTimeZone == TimeZoneInfoLocal False
关于这个分布式系统中跨时区问题的讨论暂时就到这里,在下篇中我将给出一个完整的例子,相信会使你对本文给出的解决方案有一个深刻的认识。转载,仅供参考。
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)