接下来,我们来就来实现Lars系统第一个暴露给业务开发者的API,get_host获取主机信息。

31.1 Lars-API:GetHost()方法客户端实现

  1. 我们首先先提供一个`C++`语言的API接口层,以后根据不同的业务的实现语言,可以多实现一些其他语言的API接口层。

/Lars下创建api/文件夹.

  1. /Lars/api/
  2. └── cpp/
  3. ├── example/
  4. ├── example.cpp
  5. └── Makefile
  6. ├── lars_api/
  7. ├── lars_api.cpp
  8. ├── lars_api.h
  9. └── Makefile
  10. └── lib/

lars_api/lars_api.h

  1. #pragma once
  2. #include "lars_reactor.h"
  3. #include <string>
  4. class lars_client
  5. {
  6. public:
  7. lars_client();
  8. ~lars_client();
  9. //lars 系统获取host信息 得到可用host的ip和port
  10. int get_host(int modid, int cmdid, std::string& ip, int &port);
  11. private:
  12. int _sockfd[3]; //3个udp socket fd 对应agent 3个udp server
  13. uint32_t _seqid; //消息的序列号
  14. };

lars_api/lars_api.cpp

  1. #include "lars_api.h"
  2. #include "lars.pb.h"
  3. #include <string.h>
  4. #include <sys/socket.h>
  5. #include <netinet/in.h>
  6. #include <arpa/inet.h>
  7. lars_client::lars_client():_seqid(0)
  8. {
  9. printf("lars_client()\n");
  10. //1 初始化服务器地址
  11. struct sockaddr_in servaddr;
  12. bzero(&servaddr, sizeof(servaddr));
  13. servaddr.sin_family = AF_INET;
  14. //默认的ip地址是本地,因为是API和agent应该部署于同一台主机上
  15. inet_aton("127.0.0.1", &servaddr.sin_addr);
  16. //2. 创建3个UDPsocket
  17. for (int i = 0; i < 3; i ++) {
  18. _sockfd[i] = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, IPPROTO_UDP);
  19. if (_sockfd[i] == -1) {
  20. perror("socket()");
  21. exit(1);
  22. }
  23. //agent的3个udp端口默认为8888,8889, 8890
  24. servaddr.sin_port = htons(8888 + i);
  25. int ret = connect(_sockfd[i], (const struct sockaddr *)&servaddr, sizeof(servaddr));
  26. if (ret == -1) {
  27. perror("connect()");
  28. exit(1);
  29. }
  30. printf("connection agent udp server succ!\n");
  31. }
  32. }
  33. lars_client::~lars_client()
  34. {
  35. printf("~lars_client()\n");
  36. for (int i = 0; i < 3; ++i) {
  37. close(_sockfd[i]);
  38. }
  39. }
  40. //lars 系统获取host信息 得到可用host的ip和port
  41. int lars_client::get_host(int modid, int cmdid, std::string &ip, int &port)
  42. {
  43. //从本地agent service获取 host信息
  44. uint32_t seq = _seqid++;
  45. //1. 封装请求信息
  46. lars::GetHostRequest req;
  47. req.set_seq(seq);//序列编号
  48. req.set_modid(modid);
  49. req.set_cmdid(cmdid);
  50. //2. send
  51. char write_buf[4096], read_buf[80*1024];
  52. //消息头
  53. msg_head head;
  54. head.msglen = req.ByteSizeLong();
  55. head.msgid = lars::ID_GetHostRequest;
  56. memcpy(write_buf, &head, MESSAGE_HEAD_LEN);
  57. //消息体
  58. req.SerializeToArray(write_buf+MESSAGE_HEAD_LEN, head.msglen);
  59. //简单的hash来发给对应的agent udp server
  60. int index = (modid + cmdid) %3;
  61. int ret = sendto(_sockfd[index], write_buf, head.msglen + MESSAGE_HEAD_LEN, 0, NULL, 0);
  62. if (ret == -1) {
  63. perror("sendto");
  64. return lars::RET_SYSTEM_ERROR;
  65. }
  66. //3. recv
  67. int message_len;
  68. lars::GetHostResponse rsp;
  69. do {
  70. message_len = recvfrom(_sockfd[index], read_buf, sizeof(read_buf), 0, NULL, NULL);
  71. if (message_len == -1) {
  72. perror("recvfrom");
  73. return lars::RET_SYSTEM_ERROR;
  74. }
  75. //消息头
  76. memcpy(&head, read_buf, MESSAGE_HEAD_LEN);
  77. if (head.msgid != lars::ID_GetHostResponse) {
  78. fprintf(stderr, "message ID error!\n");
  79. return lars::RET_SYSTEM_ERROR;
  80. }
  81. //消息体
  82. ret = rsp.ParseFromArray(read_buf + MESSAGE_HEAD_LEN, message_len - MESSAGE_HEAD_LEN);
  83. if (!ret) {
  84. fprintf(stderr, "message format error: head.msglen = %d, message_len = %d, message_len - MESSAGE_HEAD_LEN = %d, head msgid = %d, ID_GetHostResponse = %d\n", head.msglen, message_len, message_len-MESSAGE_HEAD_LEN, head.msgid, lars::ID_GetHostResponse);
  85. return lars::RET_SYSTEM_ERROR;
  86. }
  87. } while (rsp.seq() < seq);
  88. if (rsp.seq() != seq || rsp.modid() != modid || rsp.cmdid() != cmdid) {
  89. fprintf(stderr, "message format error\n");
  90. return lars::RET_SYSTEM_ERROR;
  91. }
  92. //4 处理消息
  93. if (rsp.retcode() == 0) {
  94. lars::HostInfo host = rsp.host();
  95. struct in_addr inaddr;
  96. inaddr.s_addr = host.ip();
  97. ip = inet_ntoa(inaddr);
  98. port = host.port();
  99. }
  100. return rsp.retcode();//lars::RET_SUCC
  101. }
  1. 模拟Lars的支持的传输协议,发送udp请求,其中messageID`ID_GetHostRequest`,返回的消息结构类型是`GetHostResponse`。每个消息有一个seq序列号,防止udp的丢包和消息不对称情况。

lars_api/Makefile

  1. TARGET= ../lib/liblarsclient.a
  2. CXX=g++
  3. CFLAGS=-g -O2 -Wall -Wno-deprecated
  4. BASE=../../../base
  5. BASE_H=$(BASE)/include
  6. PROTO = $(BASE)/proto
  7. PROTO_H = $(BASE)/proto
  8. LARS_REACTOR=../../../lars_reactor
  9. LARS_REACTOR_H =$(LARS_REACTOR)/include
  10. LARS_REACTOR_LIB=$(LARS_REACTOR)/lib -llreactor
  11. OTHER_LIB = -lpthread -ldl -lprotobuf
  12. SRC= ./
  13. INC= -I./include -I$(BASE_H) -I$(LARS_REACTOR_H) -I$(PROTO_H)
  14. LIB= -L$(LARS_REACTOR_LIB) $(OTHER_LIB)
  15. OBJS = $(addsuffix .o, $(basename $(wildcard $(SRC)/*.cpp)))
  16. OBJS += $(PROTO)/lars.pb.o
  17. $(TARGET): $(OBJS)
  18. mkdir -p ../lib
  19. ar cqs $@ $^
  20. %.o: %.cpp
  21. $(CXX) $(CFLAGS) -c -o $@ $< $(INC)
  22. .PHONY: clean
  23. clean:
  24. -rm -f ./*.o $(PROTO)/lars.pb.o $(TARGET)
  1. 最终生成一个liblarsclient.a静态库,供开发者使用。

接下来我们来实现一个模拟的业务端,example/

example/example.cpp

  1. #include "lars_api.h"
  2. #include <iostream>
  3. void usage()
  4. {
  5. printf("usage: ./example [modid] [cmdid]\n");
  6. }
  7. int main(int argc, char **argv)
  8. {
  9. if (argc != 3) {
  10. usage();
  11. return 1;
  12. }
  13. int modid = atoi(argv[1]);
  14. int cmdid = atoi(argv[2]);
  15. lars_client api;
  16. std::string ip;
  17. int port;
  18. int ret = api.get_host(modid, cmdid, ip, port);
  19. if (ret == 0) {
  20. std::cout << "host is " << ip << ":" << port << std::endl;
  21. //上报调用结果
  22. }
  23. return 0;
  24. }

example/Makefile

  1. CXX = g++
  2. CFLAGS = -g -O2 -Wall -Wno-deprecated
  3. LARS_REACTOR=../../../lars_reactor
  4. LARS_REACTOR_H =$(LARS_REACTOR)/include
  5. LARS_REACTOR_LIB=$(LARS_REACTOR)/lib -llreactor
  6. all:
  7. $(CXX) $(CFLAGS) -o example example.cpp -I$(LARS_REACTOR_H) -I../lars_api ../lib/liblarsclient.a -lprotobuf
  8. .PHONY: clean
  9. clean:
  10. -rm ./example

31.2 Agent UDP Server处理API-GetHost请求

  1. API:get_host()—>Agent UDP Server—>route_lb—>load_balance

如上所示,get_host的请求消息会依次经过agent udp server处理ID_GetHostRequest,然后交给某个route_lb

那么,API一旦发送get_host, Agent UDP Server需要添加一个对应的处理该消息的路由处理业务。

lars_loadbalance_agent/src/agent_udp_server.cpp

  1. void * agent_server_main(void * args)
  2. {
  3. long index = (long)args;
  4. short port = index + 8888;
  5. event_loop loop;
  6. udp_server server(&loop, "0.0.0.0", port);
  7. //给server注册消息分发路由业务, 每个udp拥有一个对应的route_lb
  8. server.add_msg_router(lars::ID_GetHostRequest, get_host_cb, r_lb[port-8888]);
  9. printf("agent UDP server :port %d is started...\n", port);
  10. loop.event_process();
  11. return NULL;
  12. }

其中get_host_cb()实现如下:

lars_loadbalance_agent/src/agent_udp_server.cpp

  1. static void get_host_cb(const char *data, uint32_t len, int msgid, net_connection *net_conn, void *user_data)
  2. {
  3. printf("get_host_cb is called ....\n");
  4. //解析api发送的请求包
  5. lars::GetHostRequest req;
  6. req.ParseFromArray(data, len);
  7. int modid = req.modid();
  8. int cmdid = req.cmdid();
  9. //设置回执消息
  10. lars::GetHostResponse rsp;
  11. rsp.set_seq(req.seq());
  12. rsp.set_modid(modid);
  13. rsp.set_cmdid(cmdid);
  14. route_lb *ptr_route_lb = (route_lb*)user_data;
  15. //调用route_lb的获取host方法,得到rsp返回结果
  16. ptr_route_lb->get_host(modid, cmdid, rsp);
  17. //打包回执给api消息
  18. std::string responseString;
  19. rsp.SerializeToString(&responseString);
  20. net_conn->send_message(responseString.c_str(), responseString.size(), lars::ID_GetHostResponse);
  21. printf("rspstring size = %d\n", responseString.size());
  22. }
  1. 这里面实际上的最终业务,交给了route_lb`get_host()`方法,而且其中`lars::GetHostResponse rsp;`做为函数的返回参数类型。
  2. `r_lb`是全局定义的3route_lb对象.定义实现如下.

lars_loadbalance_agent/src/main_server.cpp

  1. //每个Agent UDP server的 负载均衡器路由 route_lb
  2. route_lb * r_lb[3];
  3. static void create_route_lb()
  4. {
  5. for (int i = 0; i < 3; i++) {
  6. int id = i + 1; //route_lb的id从1 开始计数
  7. r_lb[i] = new route_lb(id);
  8. if (r_lb[i] == NULL) {
  9. fprintf(stderr, "no more space to new route_lb\n");
  10. exit(1);
  11. }
  12. }
  13. }
  14. static void init_lb_agent()
  15. {
  16. //1. 加载配置文件
  17. config_file::setPath("./conf/lars_lb_agent.conf");
  18. lb_config.probe_num = config_file::instance()->GetNumber("loadbalance", "probe_num", 10);
  19. lb_config.init_succ_cnt = config_file::instance()->GetNumber("loadbalance", "init_succ_cnt", 180);
  20. //2. 初始化3个route_lb模块
  21. create_route_lb();
  22. }
  23. int main(int argc, char **argv)
  24. {
  25. //1 初始化环境
  26. init_lb_agent();
  27. //1.5 初始化LoadBalance的负载均衡器
  28. //2 启动udp server服务,用来接收业务层(调用者/使用者)的消息
  29. start_UDP_servers();
  30. // ...
  31. return 0;
  32. }
  1. 接下来我们在看看`route_lb->get_host(modid, cmdid, rsp);`的实现。

lars_loadbalance_agent/src/route_lb.cpp

  1. #include "route_lb.h"
  2. #include "lars.pb.h"
  3. //构造初始化
  4. route_lb::route_lb(int id):_id(id)
  5. {
  6. pthread_mutex_init(&_mutex, NULL);
  7. }
  8. //agent获取一个host主机,将返回的主机结果存放在rsp中
  9. int route_lb::get_host(int modid, int cmdid, lars::GetHostResponse &rsp)
  10. {
  11. int ret = lars::RET_SUCC;
  12. //1. 得到key
  13. uint64_t key = ((uint64_t)modid << 32) + cmdid;
  14. pthread_mutex_lock(&_mutex);
  15. //2. 当前key已经存在_route_lb_map中
  16. if (_route_lb_map.find(key) != _route_lb_map.end()) {
  17. //2.1 取出对应的load_balance
  18. load_balance *lb = _route_lb_map[key];
  19. if (lb->empty() == true) {
  20. //存在lb 里面的host为空,说明正在pull()中,还没有从dns_service返回来,所以直接回复不存在
  21. assert(lb->status == load_balance::PULLING);
  22. rsp.set_retcode(lars::RET_NOEXIST);
  23. }
  24. else {
  25. ret = lb->choice_one_host(rsp);
  26. rsp.set_retcode(ret);
  27. //TODO 超时重拉路由
  28. }
  29. }
  30. //3. 当前key不存在_route_lb_map中
  31. else {
  32. //3.1 新建一个load_balance
  33. load_balance *lb = new load_balance(modid, cmdid);
  34. if (lb == NULL) {
  35. fprintf(stderr, "no more space to create loadbalance\n");
  36. exit(1);
  37. }
  38. //3.2 新建的load_balance加入到map中
  39. _route_lb_map[key] = lb;
  40. //3.3 从dns service服务拉取具体的host信息
  41. lb->pull();
  42. //3.4 设置rsp的回执retcode
  43. rsp.set_retcode(lars::RET_NOEXIST);
  44. ret = lars::RET_NOEXIST;
  45. }
  46. pthread_mutex_unlock(&_mutex);
  47. return ret;
  48. }

get_host在获取host的时候是一个动态的获取模式,如果根据当前的modid/cmdid请求的load_balance模块来获取,如果load_balance存在,则直接调用load_balancechoice_one_host()方法获取。 如果load_balance不存在,需要新建load_balance,并且当前的load_balance所携带的host信息,需要从远程dns service下载拉取下来,调用pull()方法来实现。

本端选择host信息(load_balance存在情况)

lars_loadbalance_agent/src/load_balance.cpp

  1. //从一个host_list中得到一个节点放到GetHostResponse 的HostInfo中
  2. static void get_host_from_list(lars::GetHostResponse &rsp, host_list &l)
  3. {
  4. //选择list中第一个节点
  5. host_info *host = l.front();
  6. //HostInfo自定义类型,proto3并没提供set方法,而是通过mutable_接口返回HostInfo的指针,可根据此指针进行赋值操作
  7. lars::HostInfo* hip = rsp.mutable_host();
  8. hip->set_ip(host->ip);
  9. hip->set_port(host->port);
  10. //将上面处理过的第一个节点放在队列的末尾
  11. l.pop_front();
  12. l.push_back(host);
  13. }
  14. //从两个队列中获取一个host给到上层
  15. int load_balance::choice_one_host(lars::GetHostResponse &rsp)
  16. {
  17. //1 判断_dile_list队列是否已经空,如果空表示没有空闲节点
  18. if (_idle_list.empty() == true) {
  19. // 1.1 判断是否已经超过了probe_num
  20. if (_access_cnt >= lb_config.probe_num) {
  21. _access_cnt = 0;
  22. //从 overload_list中选择一个已经过载的节点
  23. get_host_from_list(rsp, _overload_list);
  24. }
  25. else {
  26. //明确返回给API层,已经过载了
  27. ++_access_cnt;
  28. return lars::RET_OVERLOAD;
  29. }
  30. }
  31. else {
  32. // 2 判断过载列表是否为空
  33. if (_overload_list.empty() == true) {
  34. //2.1 当前modid/cmdid所有节点均为正常
  35. //选择一个idle节点
  36. get_host_from_list(rsp, _idle_list);
  37. }
  38. else {
  39. //2.2 有部分节点过载
  40. //判断访问次数是否超过probe_num阈值,超过则从overload_list取出一个
  41. if (_access_cnt >= lb_config.probe_num) {
  42. _access_cnt = 0;
  43. get_host_from_list(rsp, _overload_list);
  44. }
  45. else {
  46. //正常从idle_list中选出一个节点
  47. ++_access_cnt;
  48. get_host_from_list(rsp, _idle_list);
  49. }
  50. //选择一个idle节点
  51. get_host_from_list(rsp, _idle_list);
  52. }
  53. }
  54. return lars::RET_SUCC;
  55. }

idle_listover_list中的去取出适当的host阶段返回给上层。

远程拉取host信息(load_balance不存在情况)

load_balance首先向dns_client的thread_queue发送GetRouteRequest请求。load_balance更新为PULLING状态。

pull发送请求过程
  1. load_balance->pull() ----> dns client ----> dns server

lars_loadbalance_agent/src/load_balance.cpp

  1. //如果list中没有host信息,需要从远程的DNS Service发送GetRouteHost请求申请
  2. int load_balance::pull()
  3. {
  4. //请求dns service请求
  5. lars::GetRouteRequest route_req;
  6. route_req.set_modid(_modid);
  7. route_req.set_cmdid(_cmdid);
  8. //通过dns client的thread queue发送请求
  9. dns_queue->send(route_req);
  10. //由于远程会有一定延迟,所以应该给当前的load_balance模块标记一个正在拉取的状态
  11. status = PULLING;
  12. return 0;
  13. }

lars_loadbalance_agent/src/dns_client.cpp

  1. #include "lars_reactor.h"
  2. #include "main_server.h"
  3. #include <pthread.h>
  4. //typedef void io_callback(event_loop *loop, int fd, void *args);
  5. //只要thread_queue有数据,loop就会触发此回调函数来处理业务
  6. void new_dns_request(event_loop *loop, int fd, void *args)
  7. {
  8. tcp_client *client = (tcp_client*)args;
  9. //1. 将请求数据从thread_queue中取出,
  10. std::queue<lars::GetRouteRequest> msgs;
  11. //2. 将数据放在queue队列中
  12. dns_queue->recv(msgs);
  13. //3. 遍历队列,通过client依次将每个msg发送给reporter service
  14. while (!msgs.empty()) {
  15. lars::GetRouteRequest req = msgs.front();
  16. msgs.pop();
  17. std::string requestString;
  18. req.SerializeToString(&requestString);
  19. //client 发送数据
  20. client->send_message(requestString.c_str(), requestString.size(), lars::ID_GetRouteRequest);
  21. }
  22. }
  23. //...
  24. void *dns_client_thread(void* args)
  25. {
  26. printf("dns client thread start\n");
  27. event_loop loop;
  28. //1 加载配置文件得到dns service ip + port
  29. std::string ip = config_file::instance()->GetString("dnsserver", "ip", "");
  30. short port = config_file::instance()->GetNumber("dnsserver", "port", 0);
  31. //2 创建客户端
  32. tcp_client client(&loop, ip.c_str(), port, "dns client");
  33. //3 将thread_queue消息回调事件,绑定到loop中
  34. dns_queue->set_loop(&loop);
  35. dns_queue->set_callback(new_dns_request, &client);
  36. //4 设置当收到dns service回执的消息ID_GetRouteResponse处理函数
  37. client.add_msg_router(lars::ID_GetRouteResponse, deal_recv_route);
  38. //启动事件监听
  39. loop.event_process();
  40. return NULL;
  41. }
  42. void start_dns_client()
  43. {
  44. //开辟一个线程
  45. pthread_t tid;
  46. //启动线程业务函数
  47. int ret = pthread_create(&tid, NULL, dns_client_thread, NULL);
  48. if (ret == -1) {
  49. perror("pthread_create");
  50. exit(1);
  51. }
  52. //设置分离模式
  53. pthread_detach(tid);
  54. }

接收远程host信息回执过程
  1. dns service ----> dns client ----> route_lb::update_host() ----> load_balance::update()

lars_loadbalance_agent/src/dns_client.cpp

  1. /*
  2. * 处理远程dns service回复的modid/cmdid对应的路由信息
  3. * */
  4. void deal_recv_route(const char *data, uint32_t len, int msgid, net_connection *net_conn, void *user_data)
  5. {
  6. lars::GetRouteResponse rsp;
  7. //解析远程消息到proto结构体中
  8. rsp.ParseFromArray(data, len);
  9. int modid = rsp.modid();
  10. int cmdid = rsp.cmdid();
  11. int index = (modid+cmdid)%3;
  12. // 将该modid/cmdid交给一个route_lb处理 将rsp中的hostinfo集合加入到对应的route_lb中
  13. r_lb[index]->update_host(modid, cmdid, rsp);
  14. }

lars_loadbalance_agent/src/route_lb.cpp

  1. //根据Dns Service返回的结果更新自己的route_lb_map
  2. int route_lb::update_host(int modid, int cmdid, lars::GetRouteResponse &rsp)
  3. {
  4. //1. 得到key
  5. uint64_t key = ((uint64_t)modid << 32) + cmdid;
  6. pthread_mutex_lock(&_mutex);
  7. //2. 在_route_map中找到对应的key
  8. if (_route_lb_map.find(key) != _route_lb_map.end()) {
  9. load_balance *lb = _route_lb_map[key];
  10. if (rsp.host_size() == 0) {
  11. //2.1 如果返回的结果 lb下已经没有任何host信息,则删除该key
  12. delete lb;
  13. _route_lb_map.erase(key);
  14. }
  15. else {
  16. //2.2 更新新host信息
  17. lb->update(rsp);
  18. }
  19. }
  20. pthread_mutex_unlock(&_mutex);
  21. return 0;
  22. }

lars_loadbalance_agent/src/load_balance.cpp

  1. //根据dns service远程返回的结果,更新_host_map
  2. void load_balance::update(lars::GetRouteResponse &rsp)
  3. {
  4. //确保dns service返回的结果有host信息
  5. assert(rsp.host_size() != 0);
  6. std::set<uint64_t> remote_hosts;
  7. std::set<uint64_t> need_delete;
  8. //1. 插入新增的host信息 到_host_map中
  9. for (int i = 0; i < rsp.host_size(); i++) {
  10. //1.1 得到rsp中的一个host
  11. const lars::HostInfo & h = rsp.host(i);
  12. //1.2 得到ip+port的key值
  13. uint64_t key = ((uint64_t)h.ip() << 32) + h.port();
  14. remote_hosts.insert(key);
  15. //1.3 如果自身的_host_map找不到当下的key,说明是新增
  16. if (_host_map.find(key) == _host_map.end()) {
  17. //新增
  18. host_info *hi = new host_info(h.ip(), h.port(), lb_config.init_succ_cnt);
  19. if (hi == NULL) {
  20. fprintf(stderr, "new host_info error!\n");
  21. exit(1);
  22. }
  23. _host_map[key] = hi;
  24. //新增的host信息加入到 空闲列表中
  25. _idle_list.push_back(hi);
  26. }
  27. }
  28. //2. 删除减少的host信息 从_host_map中
  29. //2.1 得到哪些节点需要删除
  30. for (host_map_it it = _host_map.begin(); it != _host_map.end(); it++) {
  31. if (remote_hosts.find(it->first) == remote_hosts.end()) {
  32. //该key在host_map中存在,而在远端返回的结果集不存在,需要锁定被删除
  33. need_delete.insert(it->first);
  34. }
  35. }
  36. //2.2 删除
  37. for (std::set<uint64_t>::iterator it = need_delete.begin();
  38. it != need_delete.end(); it++) {
  39. uint64_t key = *it;
  40. host_info *hi = _host_map[key];
  41. if (hi->overload == true) {
  42. //从过载列表中删除
  43. _overload_list.remove(hi);
  44. }
  45. else {
  46. //从空闲列表删除
  47. _idle_list.remove(hi);
  48. }
  49. delete hi;
  50. }
  51. }

load balance agent V0.3—API get_host请求功能单元测试

为了方便我们编译Lars的全部模块,我们在/Lars/下提供一个Makefile来编译子目录模块

/Lars/Makefile

  1. SUBDIRS = lars_reactor lars_dns lars_reporter lars_loadbalance_agent
  2. .PHONY: all
  3. all:
  4. @list='$(SUBDIRS)'; for subdir in $$list; do \
  5. echo "Clean in $$subdir";\
  6. $(MAKE) -C $$subdir;\
  7. done
  8. .PHONY: clean
  9. clean:
  10. @echo Making clean
  11. @list='$(SUBDIRS)'; for subdir in $$list; do \
  12. echo "Clean in $$subdir";\
  13. $(MAKE) -C $$subdir clean;\
  14. done

现在我们编译,然后分别启动lars_dns,lars_reporter,lars_loadbalance_agent

lars_dns

  1. ~/Lars/lars_dns$ ./bin/lars_dns
  2. msg_router init...
  3. create 0 thread
  4. create 1 thread
  5. create 2 thread
  6. create 3 thread
  7. create 4 thread
  8. add msg cb msgid = 1
  9. lars dns service ....
  10. now route version is 1573034612
  11. modID = 1, cmdID = 1, ip = 3232235953, port = 7777
  12. modID = 1, cmdID = 2, ip = 3232235954, port = 7776
  13. modID = 2, cmdID = 1, ip = 3232235955, port = 7778
  14. modID = 2, cmdID = 2, ip = 3232235956, port = 7779
  15. load data to tmep succ! size is 4
  16. load data to tmep succ! size is 4
  17. ...

lars_reporter

  1. ~/Lars/lars_reporter$ ./bin/lars_reporter
  2. msg_router init...
  3. create 0 thread
  4. create 1 thread
  5. create 2 thread
  6. create 3 thread
  7. create 4 thread
  8. add msg cb msgid = 3

lars_lb_agent

  1. ~/Lars/lars_loadbalance_agent$ ./bin/lars_lb_agent
  2. msg_router init...
  3. UDP server on 0.0.0.0:8888 is running...
  4. add msg cb msgid = 4
  5. agent UDP server :port 8888 is started...
  6. msg_router init...
  7. msg_router init...
  8. UDP server on 0.0.0.0:8890 is running...
  9. add msg cb msgid = 4
  10. agent UDP server :port 8890 is started...
  11. [report] client thread start...
  12. done!
  13. msg_router init...
  14. UDP server on 0.0.0.0:8889 is running...
  15. add msg cb msgid = 4
  16. agent UDP server :port 8889 is started...
  17. dns client thread start
  18. do_connect EINPROGRESS
  19. connect 127.0.0.1:7779 succ!
  20. msg_router init...
  21. do_connect EINPROGRESS
  22. add msg cb msgid = 2
  23. connect 127.0.0.1:7778 succ!

启动API example/的单元测试程序

API:get_host example

  1. ~/Lars/api/cpp/example$ ./example 1 1
  2. lars_client()
  3. connection agent udp server succ!
  4. connection agent udp server succ!
  5. connection agent udp server succ!
  6. host is 177.1.168.192:7777
  7. ~lars_client()