www.pudn.com > 2003090514065121890.zip > spServerEB.h


#ifndef __SP_SERVER_EB_H_ 
#define __SP_SERVER_EB_H_ 
/* 
实现负载均衡和故障检测: 
首先实现了故障信息收集功能,然后添加负载均衡信息收集功能 
所以在CErrorInfoCollect中,部分成员命名为添加Error或是Balance前缀, 
未添加前缀的成员按照故障信息收集处理 
 
关于所以已经建立的连接的处理: 
所有建立的连接会存放到一个链表中, 
对新创建的处理线程来讲,线程通过调用AddConnectionAndWait,AddBalanceConnectionAndWait,将自己添加到链表中 
并且一直等待退出事件变为有信号。 
 
线程分类: 
1、Ping包添加线程 AddPingInfoThread,定期在待发送的数据链表内添加Ping包 
2、故障信息发送线程 ErrorInfoSendThread 定期发送故障信息到所有已经连接的客户端 
3、负载信息发送线程 BalanceInfoSendThread 定期发送负载信息到所有已经连接的客户端 
 
关于Ping包,故障信息和负载信息数据发送的处理: 
所有待发送的数据存放在链表中 
发送线程定期从链表中读取数据,并通过连接链表读出已经建立的套接口信息并逐个发送 
如果向已经建立连接的套接口发送失败,发送线程会将相应的线程的退出事件设置为有信号 
 
关于数据同步的处理: 
利用读写锁同步所有可能会别多线程同时访问的数据 
*/ 
 
namespace spBase 
{//定义名字空间 
class CErrorInfoCollect; 
class CConnectContainer; 
class CEBSimpleDisplay; 
 
//初始化服务器名称, exported 
//该名称在系统内必须唯一,长度不能超过6字节 
//此函数在系统启动时必须第一时间被调用,而且不能被第二次调用 
void glo_spInitEBName(LPCSTR pszName); 
 
//得到故障信息收集对象 exported 
CErrorInfoCollect* glo_spGetErrorInfoObject(void); 
 
//故障检查,服务器端回调函数 
void ErrorMonitorCallback(CServerStatus* pS,CSocketChildThread* pC); 
//回调函数,将故障数据发送给对方 
void BalanceDataCallback(CServerStatus* pS,CSocketChildThread* pC); 
 
//故障信息发送线程 
DWORD ErrorInfoSendThread(LPVOID pD); 
//Ping包发送线程 
DWORD AddPingInfoThread(LPVOID pD); 
//负载均衡数据发送线程 
DWORD BalanceInfoSendThread(LPVOID pD); 
} 
 
namespace spBase 
{ 
////////////////////////// 
//基本的信息显示类 
////////////////////////// 
class CEBSimpleDisplay : public COutputDisplay 
{//显示类 
public: 
	CEBSimpleDisplay() 
	{}; 
	~CEBSimpleDisplay(){}; 
public: 
	BOOL PutLine(ErrorLevel eLevel,LPCSTR pszOutput) 
	{ 
		//char szDesc[20]; 
		//GetErrorLevelString(eLevel,szDesc); 
		//printf("%d %s %s\n",(int)eLevel,szDesc,pszOutput); 
		return TRUE; 
	}; 
}; 
 
//////////////////////////////////////// 
//保存已经建立的连接的信息 
//////////////////////////////////////// 
struct ConnectElement 
{ 
	int iID; 
	CSocketChildThread* pConnection; 
	HANDLE hEvent; 
}; 
 
///////////////////////////////////////// 
//用来保存所有连接 
///////////////////////////////////////// 
class CConnectContainer 
{ 
public: 
	CConnectContainer(){}; 
	~CConnectContainer() 
	{ 
		while(m_arrElement.GetUpperBound()+1) 
		{ 
			struct ConnectElement* pE = m_arrElement.ElementAt(0); 
			m_arrElement.RemoveAt(0); 
			CloseHandle(pE->hEvent); 
			delete pE; 
		} 
	}; 
public: 
	//将连接添加到数组中,并一直等待到被释放 
	void AddConnection(CSocketChildThread* pConnection,HANDLE hEvent,int iID) 
	{ 
		struct ConnectElement* pE= new struct ConnectElement; 
		pE->iID = iID; 
		pE->hEvent = hEvent; 
		pE->pConnection=pConnection; 
		m_arrElement.Add(pE); 
	}; 
	void DelConnection(int iID) 
	{ 
		int iTotal = (int)m_arrElement.GetUpperBound()+1; 
		for(int i=0;iiID == iID) 
			{ 
				m_arrElement.RemoveAt(i); 
				delete pE; 
				break; 
			} 
		} 
	}; 
public: 
	CArray m_arrElement; 
}; 
 
//故障信息收集类 
class CErrorInfoCollect 
{ 
	friend DWORD spBase::ErrorInfoSendThread(LPVOID pD); 
	friend DWORD spBase::AddPingInfoThread(LPVOID pD); 
	friend DWORD spBase::BalanceInfoSendThread(LPVOID pD); 
public: 
	CErrorInfoCollect(); 
	~CErrorInfoCollect(); 
public: 
	//启动服务,iPort为故障信息监听端口,iPort+1为负载信息监听端口 
	BOOL Start(LPCSTR pszLocalAddr,int iPort,BOOL fAutoPing=TRUE); 
	BOOL Stop(void); 
public://关于故障信息收集的相关函数 
	BOOL AddPing(void); 
/* 	 
添加故障信息 
故障类型: 
	0:不可恢复,服务器现为不可用状态。 
	1:无法接受请求,等待恢复。 
	5:普通故障,尚可以继续处理请求。 
	9:正常。 
故障位置:故障类型为5时需要指明,否则此参数为Z 
	Z:正常情况 
 	P:进程。 
 	T:子线程。 
 	O:外部服务。 
 	N:网络。 
 	F:存储系统。 
 	D:数据库。 
 	M:内存。 
fSendNow:是否立即发送,如果为TRUE,则当前数据队列中待发送数据会被全部删除,本次数据会被放到第一位 
*/ 
	BOOL AddErrorInfo(int iCata=9,char cPos='Z',int iErrorCode=0,LPCSTR pszDesc="",BOOL fSendNow=FALSE); 
	//得到需要发送的信息 
	//如果当前无需要发送的信息,返回FALSE 
	BOOL PopErrorInfo(CString& szPop,CString *pszLastError=NULL); 
	//添加连接,添加连接后等待退出 
	void AddConnectionAndWait(CSocketChildThread* pConn); 
protected: 
	//对待发送的故障信息数据的操作 
	void DeleteAllInfo(void); 
	void PushErrorInfo(LPCSTR pszPush,BOOL fIsPing=FALSE); 
public://对于负载信息处理的函数 
	//添加CPU负荷 
	BOOL AddCPUBalance(int iPercent); 
	//添加当前等待的队列长 
	BOOL AddWaitingBalance(int iWaiting); 
	//添加已经处理的队列长 
	BOOL AddHandledBalance(int iHandled); 
	//添加正在处理的队列长 
	BOOL AddHandlingBalance(int iHandling); 
	//将数据添加到待发送的信息数据链表中 
	BOOL PopBalance(CString& szPop); 
	//添加连接,添加连接后等待退出 
	void AddBalanceConnectionAndWait(CSocketChildThread* pConn); 
protected: 
	BOOL AddBanlanceInfo(LPCSTR pszType,LPCSTR pszPara); 
	void DeleteAllBalanceInfo(void); 
	void PushBalance(LPCSTR pszPush); 
protected://Helper 
	//设置所有内部成员变量为空 
	void ResetMember(void); 
	//删除所有内部成员 
	void DeleteMember(void); 
 
protected: 
	//是否自动发送Ping信息 
	BOOL m_fAutoPing; 
	//服务器是否在运行 
	BOOL m_fRunning; 
	//序号 
	CSequenceGenerator *m_pseqID; 
	//显示 
	CEBSimpleDisplay *m_pDisplay; 
 
	//保存所有待发送的故障数据 
	CStringList m_listErrorInfo; 
	//保存最后一次错误信息 
	CString m_szLastErrorInfo; 
	//发送线程与Ping线程的句柄 
	HANDLE m_hSendThread,m_hPingThread; 
	//保证故障数据读写安全 
	CRWAccessLock *m_pInfoLock; 
	//所有已经连接上的故障检测服务器的信息 
	CConnectContainer *m_pconnContainer; 
	//保证故障检测连接数据读写安全 
	CRWAccessLock *m_pConnLock; 
	//故障检测服务器线程 
	CSocketParentThread *m_pErrorServerThread; 
	//数据收集服务端存储 
	CSocketGlobalDataStorage *m_pstoreSvr; 
 
	//保存所有待发送的负载数据 
	CStringList m_listBalanceInfo; 
	//负载信息发送线程句柄 
	HANDLE m_hBalanceThread; 
	//保证负载数据读写安全 
	CRWAccessLock *m_pBalanceInfoLock; 
	//所有已经连接上的负载服务器的信息 
	CConnectContainer *m_pconnBalanceContainer; 
	//保证负载收集连接数据读写安全 
	CRWAccessLock *m_pBalanceConnLock; 
	//故障检测服务器线程 
	CSocketParentThread *m_pBalanceServerThread; 
	//数据收集服务端存储 
	CSocketGlobalDataStorage *m_pstoreBalanceSvr; 
 
}; 
 
}//end namespace 
#endif