一、集群定义
集群技术(Cluster)可如下定义:一组相互独立的服务器在网络中表现为单一的系统,并以单一系统的模式加以管理。此单一系统为客户工作站提供高可靠性的服务。大多数模式下,集群中所有的计算机拥有一个共同的名称,集群内任一系统上运行的服务可被所有的网络客户所使用。Cluster必须可以协调管理各分离的组件的错误和失败,并可透明地向Cluster中加入组件。一个Cluster包含多台(至少二台)拥有共享数据存储空间的服务器。任何一台服务器运行一个应用时,应用数据被存储在共享的数据空间内。每台服务器的操作系统和应用程序文件存储在其各自的本地储存空间上。Cluster内各节点服务器通过一内部局域网相互通讯。当一台节点服务器发生故障时,这台服务器上所运行的应用程序将在另一节点服务器上被自动接管。当一个应用服务发生故障时,应用服务将被重新启动或被另一台服务器接管。当以上的任一故障发生时,客户都将能很快连接到新的应用服务上。
在数据库集群产品方面,其中主要包括基于数据库引擎的集群技术的Oracle RAC、Microsoft MSCS、IBM DB2 UDB、Sybase ASE,以及基于数据库网关(中间件)的集群技术的ICX-UDS等产品。
二、ArcSDE与集群
ArcSDE是ESRI服务器产品ArcGIS Server的一种空间数据库引擎技术,从数据管理的角度来看,ArcSDE可看成是一个连续的空间数据模型,借助这一模型,我们可用关系型数据库(RDBMS)管理空间数据。ArcSDE存储和组织数据库中的空间要素的方法,是将空间数据类型加到关系数据库中。ArcSDE并不改变和影响现有的数据库或应用。它只是在现有的数据表中加入图形数据项(Shape column),供软件管理和访问与其关联的空间数据。ArcSDE将地理数据和空间索引放在不同的数据表中,通过关键项将其相联。
ArcSDE的原理图:
集群技术(Cluster)可如下定义:一组相互独立的服务器在网络中表现为单一的系统,并以单一系统的模式加以管理。此单一系统为客户工作站提供高可靠性的服务。大多数模式下,集群中所有的计算机拥有一个共同的名称,集群内任一系统上运行的服务可被所有的网络客户所使用。Cluster必须可以协调管理各分离的组件的错误和失败,并可透明地向Cluster中加入组件。一个Cluster包含多台(至少二台)拥有共享数据存储空间的服务器。任何一台服务器运行一个应用时,应用数据被存储在共享的数据空间内。每台服务器的操作系统和应用程序文件存储在其各自的本地储存空间上。Cluster内各节点服务器通过一内部局域网相互通讯。当一台节点服务器发生故障时,这台服务器上所运行的应用程序将在另一节点服务器上被自动接管。当一个应用服务发生故障时,应用服务将被重新启动或被另一台服务器接管。当以上的任一故障发生时,客户都将能很快连接到新的应用服务上。
在数据库集群产品方面,其中主要包括基于数据库引擎的集群技术的Oracle RAC、Microsoft MSCS、IBM DB2 UDB、Sybase ASE,以及基于数据库网关(中间件)的集群技术的ICX-UDS等产品。
二、ArcSDE与集群
ArcSDE是ESRI服务器产品ArcGIS Server的一种空间数据库引擎技术,从数据管理的角度来看,ArcSDE可看成是一个连续的空间数据模型,借助这一模型,我们可用关系型数据库(RDBMS)管理空间数据。ArcSDE存储和组织数据库中的空间要素的方法,是将空间数据类型加到关系数据库中。ArcSDE并不改变和影响现有的数据库或应用。它只是在现有的数据表中加入图形数据项(Shape column),供软件管理和访问与其关联的空间数据。ArcSDE将地理数据和空间索引放在不同的数据表中,通过关键项将其相联。
ArcSDE的原理图:
从上述内容可以看出,ArcSDE实际上只是连接空间数据和数据库的一个“桥”,数据库角度理解,它只是数据库当中的一系列表。因此单从ArcSDE来讲,它并没有集群功能的。但在实际应用中经常会要求系统高可用性,需要实现空间数据的集群功能,通常是通过辅助手段解决的,本文就在这方面进行一些探索。
有两种方式实现ArcSDE的集群功能:
1.采用ArcSDE的直连方式,通过数据库的集群功能实现;
2.采用非直连方式,通过编码实现;
三、ArcSDE的直连方式实现集群功能
ArcSDE的直连方式是由客户端接口直接把空间请求转换成SQL命令发送到RDBMS上,并解释返回的数据,这种方式不需要通过ArcSDE的应用服务器,因此ArcSDE的服务不需要启动,这种方式下的集群功能实际上是通过数据库的集群功能实现的。这种方式下的客户端和服务器通讯都是通过SQL命令进行,因此需要在客户机上安装数据库的客户端。
如何使用:
这种方式下使用不需要任何额外的编码实现,但需要注意的是连接参数的设置上,如下所示设置(Oracle):
1.服务器名称(Server):不用填写。
2.服务端口(Service):SDE:数据库类型。比如:如果是oracle10g,则SDE:racle10g
3.数据库(Database):根据不同的DBMS决定是否要填。oracle系列不用填,而SQLServer需要填写。
4.用户名(UserName):需要填写的。
5.密码(password):密码@服务器名称。例如:pwd@222.115.2.6。
结构图:
局限性:
这种使用方式是把空间运算的压力部分转移到了客户端,因此每个客户端需要安装数据库的客户端,通过数据库的集群技术实现ArcSDE的集群,因此这种方式对客户端的配置要求较其它方式高,而且在Unix的客户端机器上有局限,如HP-Unix和IBM AIX的64位Unix系统下不能实现,因为使用这些ArcSDE数据的客户端如ArcIMS等不是一个真正的64位应用软件,而是32位应用。而在64位的操作系统下要求有32位的数据库客户端,而数据库厂商往往没有提供。
64 位处理器相对于32位处理器的优势在于解决了内存限制和数据访问的问题,因为64位处理器能超过32位处理器4GB内存限制,它们能存储更大数量的数据在主内存,提供对数据的直接访问和快速处理。另外,64位的处理器能处理的数据和执行的指令集是32位处理器的2倍,当处理要求高精度复杂的计算时,访问64位数据(相对于32位)的优势明显。
四、ArcSDE编码方式实现集群功能
ArcSDE编码实现集群功能的思路就是通过程序监听实现了集群的数据库状态,然后实现ArcSDE的自启动。
监听任务:数据库服务是否正常如宕机、断网;应用服务器是否正常如宕机、断网。
如何实现(以ArcIMS/Oracle/Weblogic 应用为例):
1、安装与配置好数据库集群;
2、在ArcIMS的服务器上安装ArcSDE,此时,ArcSDE与数据库是分开部署的,安装ArcSDE所需的数据库实例是虚拟实例如SF;
3、编写好监听程序,部署在ArcIMS的机器上;
结构图(以ArcIMS/Oracle/Weblogic 应用为例):
编码(Java):
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.sql.*;
public class LisOra
{
static String dbUrlsf1="jdbc:racle:thin:10.44.3.5:1521:sf1";
static String dbUrlsf2="jdbc:racle:thin:10.44.3.6:1521:sf2";
static String theUser="sde";
static String thePw="sde";
static Connection conn=null;
static Statement stmt;
static boolean sf1=true;
static boolean sf2=true;
static boolean sf3=true;
static boolean SID1=false;
static boolean SID2=false;
public static void main(String[] args)
{
System.out.println("###########################");
System.out.println("Do not exit this!It's lisening...");
System.out.println("If you want to exit,enter:ctrl+c");
System.out.println("###########################");
while(true){
SID1=testSID(true); //5
SID2=testSID(false); //5
if (SID1&&SID2){
sf3=true;
System.out.println("#### The network disconnected! ####");
}else{
if(!SID1 && !SID2){
if(sf3) doSDERestar(3); //30
}else{
if(SID1&& sf1)
doSDERestar(1);
if(SID2 && sf2)
doSDERestar(2);
}
}
}
}
private static boolean testSID(boolean isSF1)
{
try{
if(stmt!=null){
stmt=null;
}
if(conn!=null){
if(!conn.isClosed())
{
conn.close();
conn=null;
}
}
}catch(Exception e){
stmt=null;
conn=null;
}
try{
java.lang.Thread.sleep(5000);
DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver());
if (isSF1) conn=DriverManager.getConnection(dbUrlsf1,theUser,thePw);
else conn=DriverManager.getConnection(dbUrlsf2,theUser,thePw);
stmt=conn.createStatement();
if (isSF1) sf1=true;
else sf2=true;
}catch(Exception e1){
// e1.printStackTrace();
if (isSF1) System.out.println("Oracle is down on sf1");
else System.out.println("Oracle is down on sf2");
System.out.println("###########################");
System.out.println("Do not exit this!It's lisening...");
System.out.println("If you want to exit,enter:ctrl+c");
System.out.println("###########################");
return true;
}
return false;
}
private static void doSDERestar(int sf)
{
try
{
System.out.println("###########################");
System.out.println("Restart sde after 30s...");
System.out.println("###########################");
String cmdShutDown ="sdemon -o shutdown -p sde -N" ;
Process proc = Runtime.getRuntime().exec(cmdShutDown);
java.lang.Thread.sleep(10000);
BufferedReader in = new BufferedReader(new InputStreamReader(proc.getInputStream()));
String string_Temp = in.readLine();
while (string_Temp != null)
{
System.out.println(string_Temp);
string_Temp = in.readLine();
}
in=null;
proc=null;
String cmdStart ="sdemon -o start -p sde" ;
Process proc1 = Runtime.getRuntime().exec(cmdStart);
java.lang.Thread.sleep(20000);
BufferedReader in1 = new BufferedReader(new InputStreamReader(proc1.getInputStream()));
String string_Temp1 = in1.readLine();
while (string_Temp1 != null)
{
System.out.println(string_Temp1);
string_Temp1 = in1.readLine();
}
in1=null;
proc1=null;
if(sf==1) sf1=false;
if(sf==2) sf2=false;
sf3=false;
System.out.println("###########################");
System.out.println("sde started");
System.out.println("###########################");
System.out.println("Do not exit this!It's lisening...");
System.out.println("If you want to exit,enter:ctrl+c");
System.out.println("###########################");
}
catch (Exception e)
{
e.printStackTrace();
if(sf==1) sf1=true;
if(sf==2) sf2=true;
sf3=true;
}
}
private static void doSDERestarTest(int sf)
{
System.out.println("###########################");
System.out.println("Restart sde after 30s...");
System.out.println("###########################");
System.out.println("Test sde shutdown ...");
System.out.println("Test sde start ...");
if(sf==1) sf1=false;
if(sf==2) sf2=false;
sf3=false;
}
}
如何部署:
1、在应用服务器上分别编译上述代码;
2、编写sh文件如:run.sh,内容如下:
cd /usr/oracle/arcsde/sdeexe92/bin
/bin/nohup ./java LisOra >/usr/oracle/arcsde/sdeexe92/bin/run.log &
echo "arcsde listener complete"
3、将服务添加到系统的自启动脚本中,如:/sbin/init.d/ntappboot文件:
/bin/sleep 30
echo " `date` system application starting..." > /home/log/ntboot.log
#start sdelistener
/bin/su - oracle -c "sh /usr/oracle/arcsde/sdeexe92/bin/runsh.sh" > /home/log/startsdelistener_result.log
/bin/sleep 5
echo "SDELISTENER started"
4、经过测试,上述监听程序能够在机器启动后自动加载 ArcSDE,并且在宕机和断网的情况下调整ArcSDE的状态。
五、总结
第一种方式下的ArcSDE集群能够非常高效的运行,但有一定的局限性;第二种方式在一定程度上实现了ArcSDE的机器应用 。