目錄
功能實現:可以檢測 進程是否 live 或者 僵死,然後根據具體狀態,發signal 處理被檢測的進程
demo 有兩個進程 一個是 server 另一個是 client (可以有多個)(send && receive)
代碼結構如下:
├── bin
├── include
│ ├── heartbeat.h
│ ├── Log.h
│ └── udpnet.h
├── Makefile
├── make.sh
├── obj
└── src
├── heartbeat.cpp
├── Log.cpp
├── recv
│ └── heartbeatMonitor.cpp
├── send
│ └── heartbeatMonitor_send.cpp
└── udpnet.cpp
代碼解析:
兩個進程,主要有3個線程來實現:send tread receive tread check thread
check tread:
void* HeartbeatMonitor::checkThread( void* param )
{
const int LOST_LIMIT = 5;
static int call_cnt = 0;
HeartbeatMonitor* monitor = (HeartbeatMonitor*)param;
HeartbeartStatistic &statistic = monitor->statistic; //使用 引用調用 HeartbeatMonitor
int pkg_cnt = 0;
bool err_found = false;
Heartbeat new_heartbeat;
HeartbeatChecker checker;
hb_usleep(HEARTBEAT_CYCLE_MS * 1000); // 3000 ms
while(1)
{
int &pkg_lost_cnt = checker.pkg_lost_cnt;
if (monitor->pkg_cnt == pkg_cnt) //丟包判斷
{
pkg_lost_cnt++;
statistic.pkg_lost_cnt++;
hbprintf(DEBUG_LOG, DBG_HEAD " YL Pkg lost for %d times.", pkg_lost_cnt);
if (LOST_LIMIT < pkg_lost_cnt)
{
checker.recover();
statistic.pkg_lost_kill_cnt++;
}
goto LOOP_DELAY;
}
else
{
pkg_cnt = monitor->pkg_cnt;
pkg_lost_cnt = 0;
}
new_heartbeat = monitor->getHeartbeat();
err_found = false;
for (int i = 0; i < HEARTBEAT_COUNTER_NUM; ++i) //檢測不同模塊的進程的 狀態counter
{
if (new_heartbeat.counter[i] == checker.heartbeat.counter[i])
{
err_found = true;
break;
}
}
if (err_found)
{
//new_heartbeat.showContent(DBG_HEAD);
}
for (int i = 0; i < HEARTBEAT_COUNTER_NUM; ++i)
{
int &lost_cnt = checker.lost_cnt[i];
if (new_heartbeat.counter[i] != checker.heartbeat.counter[i])
{
lost_cnt++;
statistic.lost_cnt.counter[i]++;
hbprintf(DEBUG_LOG, DBG_HEAD "\"%s\" lost for %d times.", Heartbeat::counter_name[i], lost_cnt);
if (LOST_LIMIT < lost_cnt)
{
checker.recover(); //丟包 超過次數後執行 操作
statistic.kill_cnt.counter[i]++;
goto LOOP_DELAY;
}
}
else
{
lost_cnt = 0;
}
}
checker.heartbeat = new_heartbeat;
statistic.last_heart = new_heartbeat;
LOOP_DELAY:
++call_cnt;
if (call_cnt % HEARTBEAT_PRINT_CYCLE == 0)
{
statistic.showContent("HeartbeatMonitor");
}
hb_usleep(HEARTBEAT_CYCLE_MS * 1000); // 3000 ms
}
return (void *)0;
}
receive tread:
/* static */ void* HeartbeatMonitor::recvThread( void* param )
{
#define DBG_HEAD "[Recv] "
bool ret = true;
UINT32 peer_ip; //lo: 127.0.0.1 Loopback address
int peer_port;
double heartbeat_cycle_sec = 1.0 * HEARTBEAT_CYCLE_MS / 1000;
HeartbeatMonitor* monitor = (HeartbeatMonitor*)param;
HeartbeartStatistic &statistic = monitor->statistic;
while(1)
{
ret = monitor->netAdp.NetRecv(monitor->recv_buff, monitor->recv_size, heartbeat_cycle_sec, &peer_ip, &peer_port);
if (ret == false)
{
if (monitor->recv_size == 0)
{
hbprintf(DEBUG_LOG, DBG_HEAD "Time out at NetRecv.");
statistic.timeout_cnt++;
}
else
{
hbprintf(DEBUG_LOG, DBG_HEAD "ERROR at NetRecv.");
statistic.err_cnt++;
}
continue;
}
//hbprintf(DEBUG_LOG, DBG_HEAD "Hearbeat recv ok.");
monitor->pkg_cnt++;
statistic.ok_cnt++;
monitor->parseHeartbeatPkg();
}
return (void *)0;
#undef DBG_HEAD
}
send tread:
/* static */ void* HeartbeatSender::sendThread( void* param )
{
#define DBG_HEAD "[ YL -- Send] "
static int call_cnt = 0;
int iRet = true;
bool ret = true;
HeartbeatSender* sender = (HeartbeatSender*)param;
HeartbeartStatistic &statistic = sender->statistic;
while(1)
{
if (HeartbeatPkgUT_ON())
{
goto CYCLE_DELEY;
}
sender->generateHeartbeatPkg();
hbprintf(DEBUG_LOG," YL -- dest_ip = %d ,dest_port = %d,sender->send_size =%d , sender->send_buff =%s",sender->dest_ip,sender->dest_port,sender->send_size,sender->send_buff);
ret = sender->netAdp.NetSend(sender->dest_ip,
sender->dest_port,
sender->send_buff,
sender->send_size,
&iRet);
if (ret == false)
{
if (iRet == 0)
{
hbprintf(DEBUG_LOG, DBG_HEAD "Time out at NetSend.");
statistic.timeout_cnt++;
}
else
{
hbprintf(DEBUG_LOG, DBG_HEAD "ERROR at NetSend.");
statistic.err_cnt++;
}
goto CYCLE_DELEY;
}
// hbprintf(DEBUG_LOG, DBG_HEAD "Hearbeat send ok.");
statistic.last_heart = sender->getHeartbeat();
statistic.ok_cnt++;
CYCLE_DELEY:
++call_cnt;
if (call_cnt % HEARTBEAT_PRINT_CYCLE == 0)
{
statistic.showContent("HeartbeatSender");
}
hb_usleep(HEARTBEAT_CYCLE_MS * 1000); // 3000 ms
}
return (void *)0;
#undef DBG_HEAD
}
完整代碼工程下載:
To click on:core download
編譯代碼方式:
make all 即可以編譯出搜有模塊
有興趣的可以修改 Makefile和代碼 編譯多個 receive 端