├── AUTHORS ├── NEWS ├── README ├── ChangeLog ├── autoscan.log ├── sample ├── NEWS ├── README ├── AUTHORS ├── ChangeLog ├── autoscan.log ├── rpc_server.ini ├── proto │ ├── rpc_msg.proto │ ├── gen.sh │ └── rpc_sample.proto ├── rpc_client.ini ├── bootstrap.sh ├── libevrpc.sh ├── configure.ac ├── Makefile.am ├── build_sample.sh └── src │ ├── libev_server.cc │ └── libev_client.cc ├── share ├── rpc_conf │ ├── rpc_server.ini │ └── rpc_client.ini ├── rep_third.sh └── configure_sample.ac ├── src ├── unit_test │ ├── test_conf │ │ └── test.ini │ ├── test_def.h │ ├── test_compile.sh │ ├── bootstrap.sh │ ├── client_test.cpp │ ├── test_cp.cc │ ├── test_rpc_util.cpp │ ├── server_test.cpp │ ├── center_test │ │ ├── client_test.cc │ │ ├── cluster_test.cc │ │ └── center_test.cc │ ├── test_udp_server.cc │ ├── configure.ac │ ├── test_udp_client.cc │ ├── test_hb_client.cc │ ├── build_ut.sh │ ├── test_libev_tp.cc │ ├── test_hb_server.cc │ └── Makefile.am ├── center_proto │ ├── center_type.proto │ ├── gen.sh │ ├── center_client.proto │ ├── center_cluster.proto │ ├── centers.proto │ ├── center_type.pb.h │ └── center_type.pb.cc ├── util │ ├── rpc_util.h │ ├── disallow_copy_and_assign.h │ ├── rpc_controller.cpp │ ├── rpc_controller.h │ ├── rpc_util.cpp │ ├── rpc_communication.h │ ├── thread.h │ ├── pthread_mutex.h │ └── pthread_rwlock.h ├── rpc_center │ ├── reporter_thread.h │ ├── load_balancer │ │ ├── load_balancer.h │ │ ├── consistent_hash_load_balancer.h │ │ └── consistent_hash_load_balancer.cpp │ ├── leader_thread.h │ ├── election_thread.h │ ├── rpc_center_server.cc │ ├── center_server_thread.h │ ├── leader_thread.cpp │ ├── reporter_thread.cpp │ ├── election_thread.cpp │ ├── center_server_thread.cpp │ └── rpc_center.h ├── rpc_server │ ├── center_cluster_heartbeat.h │ ├── server_rpc_controller.cpp │ ├── rpc_heartbeat_server.h │ ├── server_rpc_controller.h │ ├── dispatch_thread.h │ ├── rpc_heartbeat_server.cpp │ ├── libev_thread_pool.h │ ├── rpc_server.h │ ├── connection_timer_manager.h │ ├── dispatch_thread.cpp │ ├── center_cluster_heartbeat.cpp │ └── libev_thread_pool.cpp ├── rpc_client │ ├── rpc_heartbeat_client.h │ ├── client_rpc_controller.cpp │ ├── client_rpc_controller.h │ ├── center_client_heartbeat.h │ ├── rpc_client.h │ ├── rpc_heartbeat_client.cpp │ ├── rpc_channel.h │ ├── rpc_client.cpp │ ├── rpc_channel.cpp │ └── center_client_heartbeat.cpp ├── config_parser │ ├── config_parser.h │ ├── config_parser.cpp │ └── dictionary.h └── Makefile.am ├── bootstrap.sh ├── Makefile.am ├── libevrpc.sh ├── configure.ac ├── deps_build.sh └── README.md /AUTHORS: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /NEWS: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /ChangeLog: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /autoscan.log: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /sample/NEWS: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /sample/README: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /sample/AUTHORS: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /sample/ChangeLog: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /sample/autoscan.log: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /sample/rpc_server.ini: -------------------------------------------------------------------------------- 1 | [rpc_server] 2 | port = 9998 3 | thread_num = 10 4 | 5 | [heartbeat] 6 | port = 9999 7 | 8 | -------------------------------------------------------------------------------- /share/rpc_conf/rpc_server.ini: -------------------------------------------------------------------------------- 1 | [rpc_server] 2 | port = 9998 3 | thread_num = 10 4 | 5 | [heartbeat] 6 | port = 9999 7 | 8 | -------------------------------------------------------------------------------- /src/unit_test/test_conf/test.ini: -------------------------------------------------------------------------------- 1 | [rpc_server] 2 | port = 9998 3 | thread_num = 10 4 | 5 | [heartbeat] 6 | port = 9999 7 | 8 | -------------------------------------------------------------------------------- /share/rep_third.sh: -------------------------------------------------------------------------------- 1 | 2 | 3 | #sed -i "s/third-64/third-64/g" `grep 'third-64' -rl .` 4 | 5 | sed "s/third-64/third-64/g" `grep 'third-64' -rl .` 6 | -------------------------------------------------------------------------------- /sample/proto/rpc_msg.proto: -------------------------------------------------------------------------------- 1 | 2 | message RpcMessage { 3 | optional uint32 head_code = 1 [default = 0]; 4 | optional string body_msg = 2 [default = ""]; 5 | } 6 | -------------------------------------------------------------------------------- /sample/rpc_client.ini: -------------------------------------------------------------------------------- 1 | [rpc_server] 2 | addr = 127.0.0.1 3 | port = 9998 4 | 5 | [heartbeat] 6 | open = true 7 | port = 9999 8 | 9 | [connection] 10 | timeout = 10 11 | -------------------------------------------------------------------------------- /share/rpc_conf/rpc_client.ini: -------------------------------------------------------------------------------- 1 | [rpc_server] 2 | addr = 127.0.0.1 3 | port = 9998 4 | 5 | [heartbeat:port] 6 | open = true 7 | port = 9999 8 | 9 | [connection] 10 | timeout = 10 11 | -------------------------------------------------------------------------------- /src/center_proto/center_type.proto: -------------------------------------------------------------------------------- 1 | package libevrpc; 2 | 3 | // 中心,RPC客户端,RPC集群通信标示 4 | enum CenterType { 5 | CENTER2CENTER = 100; 6 | CENTER2CLIENT = 101; 7 | CENTER2CLUSTER = 102; 8 | } 9 | -------------------------------------------------------------------------------- /sample/proto/gen.sh: -------------------------------------------------------------------------------- 1 | 2 | ../../../third-64/protobuf/bin/protoc --proto_path=./ --cpp_out=./ ./rpc_sample.proto 3 | #../../../third-64/protobuf/bin/protoc --proto_path=./ --cpp_out=./ ./rpc_msg.proto && \ 4 | #mv rpc_msg.pb.* ../common 5 | -------------------------------------------------------------------------------- /src/center_proto/gen.sh: -------------------------------------------------------------------------------- 1 | 2 | if [ "$1" == "clean" ]; then 3 | rm -rf *.pb.cc 4 | rm -rf *.pb.h 5 | exit 6 | fi 7 | 8 | ../../../third-64/protobuf/bin/protoc --proto_path=./ --cpp_out=./ ./*.proto 9 | #../../../third-64/protobuf/bin/protoc --proto_path=./ --cpp_out=./ ./rpc_msg.proto && \ 10 | #mv rpc_msg.pb.* ../common 11 | -------------------------------------------------------------------------------- /src/unit_test/test_def.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define ADDR "127.0.0.1" 5 | #define PORT "8899" 6 | 7 | #define MAX_BUFFER 1024 8 | #define BODY_SIZE 512 9 | 10 | typedef struct MetaDataStruct { 11 | int32_t code; 12 | char text[BODY_SIZE]; 13 | } MetaData; 14 | 15 | int32_t meta_size = sizeof(MetaData); 16 | -------------------------------------------------------------------------------- /sample/proto/rpc_sample.proto: -------------------------------------------------------------------------------- 1 | package echo; 2 | 3 | option cc_generic_services = true; 4 | 5 | 6 | message EchoRequest { 7 | optional string request = 1 [default = ""]; 8 | } 9 | 10 | message EchoResponse { 11 | optional string response = 1 [default = ""]; 12 | } 13 | 14 | service EchoService { 15 | rpc Echo(EchoRequest) returns (EchoResponse); 16 | }; 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /src/unit_test/test_compile.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | #g++ -o client client_test.cpp test_def.h ../util/rpc_communication.* ../util/rpc_util.* 4 | #g++ -o server server_test.cpp test_def.h ../util/rpc_communication.* ../util/rpc_util.* 5 | 6 | 7 | g++ -o udp_client test_udp_client.cc test_def.h ../util/rpc_communication.* ../util/rpc_util.* 8 | g++ -o udp_server test_udp_server.cc test_def.h ../util/rpc_communication.* ../util/rpc_util.* 9 | -------------------------------------------------------------------------------- /src/center_proto/center_client.proto: -------------------------------------------------------------------------------- 1 | package libevrpc; 2 | 3 | import "center_type.proto"; 4 | 5 | // 中心与RPC客户端信息协议 6 | enum ClientClusterAction { 7 | CLIENT_INIT_REQ = 1; 8 | UPDATE_SERVER_INFO = 2; 9 | CENTER_RESP_OK = 3; 10 | CENTER_RESP_ERR = 4; 11 | } 12 | 13 | message ClientWithCenter { 14 | optional string from_addr = 1; 15 | optional ClientClusterAction client_center_action = 2; 16 | repeated string should_communicate_center = 3; 17 | repeated string cluster_server_list = 4; 18 | } 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /bootstrap.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ "$1" == "clean" ]; then 4 | make distclean &>/dev/null 5 | rm -rf m4 aclocal.m4 autom4te.cache config.guess config.sub configure depcomp INSTALL install-sh ltmain.sh missing config.log config.status libtool 6 | rm -f *.rpm *.gz 7 | find . -name 'Makefile' -exec rm -f {} \; 8 | find . -name '.deps' -exec rm -rf {} \; 9 | find . -name 'Makefile.in' -exec rm -f {} \; 10 | exit; 11 | fi 12 | 13 | aclocal 14 | libtoolize --force 15 | autoconf 16 | automake --add-missing --force --warnings=no-portability 17 | autoheader 18 | make clean 19 | -------------------------------------------------------------------------------- /src/unit_test/bootstrap.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ "$1" == "clean" ]; then 4 | make distclean &>/dev/null 5 | rm -rf aclocal.m4 autom4te.cache config.guess config.sub configure depcomp INSTALL install-sh ltmain.sh missing config.log config.status libtool 6 | rm -f *.rpm *.gz 7 | rm -rf compile 8 | find . -name 'Makefile' -exec rm -f {} \; 9 | find . -name '.deps' -exec rm -rf {} \; 10 | find . -name 'Makefile.in' -exec rm -f {} \; 11 | exit; 12 | fi 13 | 14 | libtoolize --force 15 | aclocal 16 | autoconf 17 | automake --add-missing --force --warnings=no-portability 18 | -------------------------------------------------------------------------------- /sample/bootstrap.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ "$1" == "clean" ]; then 4 | make distclean &>/dev/null 5 | rm -rf m4 aclocal.m4 autom4te.cache config.guess config.sub configure depcomp INSTALL install-sh ltmain.sh missing config.log config.status libtool 6 | rm -f *.rpm *.gz 7 | find . -name 'Makefile' -exec rm -f {} \; 8 | find . -name '.deps' -exec rm -rf {} \; 9 | find . -name 'Makefile.in' -exec rm -f {} \; 10 | exit; 11 | fi 12 | 13 | aclocal 14 | libtoolize --force 15 | autoconf 16 | automake --add-missing --force --warnings=no-portability 17 | autoheader 18 | make clean 19 | -------------------------------------------------------------------------------- /src/unit_test/client_test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include "test_def.h" 9 | #include "../util/rpc_communication.h" 10 | 11 | using namespace libevrpc; 12 | using namespace std; 13 | 14 | int main() { 15 | int32_t conn_fd = TcpConnect(ADDR, PORT, 10000); 16 | 17 | if (conn_fd < 0) { 18 | printf("Tcp conncect error!\n"); 19 | return 0; 20 | } 21 | 22 | std::string test_str = "123start12345678901234567890end123"; 23 | 24 | int32_t ret = RpcSend(conn_fd, 0, test_str, true); 25 | printf("ret id is %d, errno is %s\n", ret, strerror(errno)); 26 | 27 | return 0; 28 | } 29 | -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | #if TEST_OPT 2 | #TEST = test 3 | #endif 4 | 5 | ACLOCAL_AMFLAGS = -I m4 6 | 7 | AUTOMAKE_OPTIONS = foreign 8 | 9 | SUBDIRS = . src 10 | 11 | 12 | MAINTAINERCLEANFILES = \ 13 | aclocal.m4 \ 14 | config.guess \ 15 | config.sub \ 16 | configure \ 17 | depcomp \ 18 | install-sh \ 19 | ltmain.sh \ 20 | Makefile.in \ 21 | missing \ 22 | mkinstalldirs \ 23 | config.h.in \ 24 | stamp.h.in \ 25 | m4/ltsugar.m4 \ 26 | m4/libtool.m4 \ 27 | m4/ltversion.m4 \ 28 | m4/lt~obsolete.m4 \ 29 | m4/ltoptions.m4 30 | 31 | -------------------------------------------------------------------------------- /src/center_proto/center_cluster.proto: -------------------------------------------------------------------------------- 1 | package libevrpc; 2 | 3 | import "center_type.proto"; 4 | 5 | enum ClusteAction { 6 | REGISTER = 1; 7 | CLUSTER_PING = 2; 8 | } 9 | 10 | enum ResponseClusterAction { 11 | CLUSTER_RESP = 1; 12 | CENTER_NOT_READY = 2; 13 | } 14 | 15 | 16 | // 中心与RPC集群之间的信息协议 17 | message RpcClusterServer { 18 | optional ClusteAction cluster_action = 1; 19 | optional string cluster_server_addr = 2; 20 | optional uint32 load = 3; 21 | optional float cpu_used = 4; 22 | optional int32 connection_num = 5; 23 | } 24 | 25 | message CenterResponseCluster { 26 | optional ResponseClusterAction center_response_action = 1; 27 | repeated string should_reporter_center = 2; 28 | } 29 | 30 | 31 | -------------------------------------------------------------------------------- /src/unit_test/test_cp.cc: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * 3 | * Copyright (c) 2016 aishuyu, Inc. All Rights Reserved 4 | * 5 | **************************************************************************/ 6 | 7 | 8 | 9 | /** 10 | * @file test_cp.cc 11 | * @author aishuyu(asy5178@163.com) 12 | * @date 2016/07/12 00:06:36 13 | * @brief 14 | * 15 | **/ 16 | 17 | 18 | 19 | 20 | #include "../config_parser/config_parser.h" 21 | 22 | 23 | using namespace libevrpc; 24 | 25 | int main() { 26 | ConfigParser& cp = ConfigParser::GetInstance("test.ini"); 27 | 28 | const char* test1 = cp.IniGetString("test1", "test-1-test"); 29 | 30 | printf("The having default is %s\n", test1); 31 | 32 | return 0; 33 | } 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | /* vim: set expandtab ts=4 sw=4 sts=4 tw=100: */ 43 | -------------------------------------------------------------------------------- /src/util/rpc_util.h: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * 3 | * Copyright (c) 2014 Aishuyu. All Rights Reserved 4 | * 5 | **************************************************************************/ 6 | 7 | 8 | 9 | /** 10 | * @file rpc_util.h 11 | * @author aishuyu(asy5178@163.com) 12 | * @date 2014/11/30 17:47:28 13 | * @brief 14 | * 15 | **/ 16 | 17 | 18 | 19 | 20 | #ifndef __RPC_UTIL_H_ 21 | #define __RPC_UTIL_H_ 22 | 23 | #include 24 | 25 | namespace libevrpc { 26 | 27 | uint32_t BKDRHash(const char *orig_str); 28 | 29 | void PrintErrorInfo(const char* error_info); 30 | 31 | const char* GetLocalAddress(); 32 | 33 | uint32_t MurMurHash2(const char* key_str, int32_t len); 34 | 35 | } // end of namespace libevrpc 36 | 37 | 38 | 39 | #endif //__RPC_UTIL_H_ 40 | 41 | /* vim: set expandtab ts=4 sw=4 sts=4 tw=100: */ 42 | -------------------------------------------------------------------------------- /src/unit_test/test_rpc_util.cpp: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * 3 | * Copyright (c) 2016 aishuyu, Inc. All Rights Reserved 4 | * 5 | **************************************************************************/ 6 | 7 | 8 | 9 | /** 10 | * @file test_rpc_util.cpp 11 | * @author aishuyu(asy5178@163.com) 12 | * @date 2016/04/12 20:18:24 13 | * @brief 14 | * 15 | **/ 16 | 17 | #include 18 | 19 | #include 20 | 21 | #include "../util/rpc_util.h" 22 | 23 | using namespace libevrpc; 24 | 25 | 26 | int main() { 27 | 28 | PrintErrorInfo("Test"); 29 | 30 | std::string ip_addr = "10.189.192.213"; 31 | printf("out test\n"); 32 | 33 | uint32_t hash_id = MurMurHash2(ip_addr.c_str(), ip_addr.size()); 34 | 35 | printf("the hash id is %u", hash_id); 36 | 37 | return 0; 38 | } 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | /* vim: set expandtab ts=4 sw=4 sts=4 tw=100: */ 48 | -------------------------------------------------------------------------------- /src/util/disallow_copy_and_assign.h: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * 3 | * Copyright (c) 2014 aishuyu.com, Inc. All Rights Reserved 4 | * 5 | **************************************************************************/ 6 | 7 | 8 | 9 | /** 10 | * @file disallow_copy_and_assign.h 11 | * @author aishuyu(asy5178@163.com) 12 | * @date 2014/11/01 22:19:56 13 | * @brief 14 | * 15 | **/ 16 | 17 | 18 | 19 | 20 | #ifndef __DISALLOW_COPY_AND_ASSIGN_H_ 21 | #define __DISALLOW_COPY_AND_ASSIGN_H_ 22 | 23 | 24 | 25 | 26 | // A macro to disallow the copy constructor and operator= functions 27 | // This should be used in the private: declarations for a class 28 | #define DISALLOW_COPY_AND_ASSIGN(TypeName) \ 29 | TypeName(const TypeName&); \ 30 | TypeName& operator=(const TypeName&); 31 | 32 | 33 | 34 | 35 | #endif //__DISALLOW_COPY_AND_ASSIGN_H_ 36 | 37 | /* vim: set expandtab ts=4 sw=4 sts=4 tw=100: */ 38 | -------------------------------------------------------------------------------- /src/unit_test/server_test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | #include "test_def.h" 9 | #include "../util/rpc_communication.h" 10 | 11 | using namespace libevrpc; 12 | 13 | int main() { 14 | int32_t listen_fd = TcpListen(ADDR, PORT, false); 15 | 16 | struct sockaddr_in client_addr; 17 | socklen_t len = sizeof(struct sockaddr_in); 18 | printf("Test the listen_fd is : %d\n", listen_fd); 19 | int32_t cfd = Accept(listen_fd, client_addr, len, false); 20 | if (cfd < 0) { 21 | printf("accpet eror!\n"); 22 | return 0; 23 | } 24 | 25 | std::string guest_addr; 26 | GetPeerAddr(cfd, guest_addr); 27 | 28 | std::string recv_msg; 29 | int id = RpcRecv(cfd, recv_msg, true); 30 | 31 | printf("Test string is :%s\n", recv_msg.c_str()); 32 | printf("Test guest_addr string is :%s\n", guest_addr.c_str()); 33 | 34 | return 0; 35 | } 36 | 37 | -------------------------------------------------------------------------------- /src/unit_test/center_test/client_test.cc: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * 3 | * Copyright (c) 2016 aishuyu, Inc. All Rights Reserved 4 | * 5 | **************************************************************************/ 6 | 7 | 8 | 9 | /** 10 | * @file client_test.cc 11 | * @author aishuyu(asy5178@163.com) 12 | * @date 2016/12/22 21:36:33 13 | * @brief 14 | * 15 | **/ 16 | 17 | 18 | #include "../rpc_client/center_client_heartbeat.h" 19 | 20 | using namespace libevrpc; 21 | 22 | 23 | int main() { 24 | 25 | CenterClientHeartbeat center_client_heartbeat("test_conf/test.ini"); 26 | center_client_heartbeat.Start(); 27 | 28 | sleep(30); 29 | 30 | center_client_heartbeat.Stop(); 31 | center_client_heartbeat.Wait(); 32 | 33 | // delete center_client_heartbeat_ptr 34 | return 0; 35 | } 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | /* vim: set expandtab ts=4 sw=4 sts=4 tw=100: */ 49 | -------------------------------------------------------------------------------- /src/unit_test/center_test/cluster_test.cc: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * 3 | * Copyright (c) 2017 aishuyu, Inc. All Rights Reserved 4 | * 5 | **************************************************************************/ 6 | 7 | 8 | 9 | /** 10 | * @file cluster_test.cc 11 | * @author aishuyu(asy5178@163.com) 12 | * @date 2017/03/10 20:47:59 13 | * @brief 14 | * 15 | **/ 16 | 17 | 18 | 19 | #include 20 | #include 21 | 22 | #include "../rpc_server/center_cluster_heartbeat.h" 23 | 24 | using namespace libevrpc; 25 | 26 | 27 | int main() { 28 | 29 | CenterClusterHeartbeat center_cluster_heartbeat("test_conf/test.ini"); 30 | center_cluster_heartbeat.Start(); 31 | 32 | sleep(30); 33 | 34 | center_cluster_heartbeat.Stop(); 35 | center_cluster_heartbeat.Wait(); 36 | 37 | return 0; 38 | } 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | /* vim: set expandtab ts=4 sw=4 sts=4 tw=100: */ 54 | -------------------------------------------------------------------------------- /src/unit_test/center_test/center_test.cc: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * 3 | * Copyright (c) 2016 aishuyu, Inc. All Rights Reserved 4 | * 5 | **************************************************************************/ 6 | 7 | 8 | 9 | /** 10 | * @file center_test.cc 11 | * @author aishuyu(asy5178@163.com) 12 | * @date 2016/12/22 21:57:08 13 | * @brief 14 | * 15 | **/ 16 | 17 | #include "../rpc_center/rpc_center.h" 18 | 19 | using namespace libevrpc; 20 | 21 | int main() { 22 | RpcCenter& rc = RpcCenter::GetInstance("test_conf/rpc_center.ini"); 23 | printf("Start Center........\n"); 24 | if (!rc.StartCenter()) { 25 | printf("Start Center Failed\n"); 26 | return 0; 27 | } 28 | printf("Wait Center........\n"); 29 | rc.WaitCenter(); 30 | printf("Stop Center........\n"); 31 | rc.StopCenter(); 32 | return 0; 33 | } 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | /* vim: set expandtab ts=4 sw=4 sts=4 tw=100: */ 46 | -------------------------------------------------------------------------------- /src/unit_test/test_udp_server.cc: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * 3 | * Copyright (c) 2016 aishuyu, Inc. All Rights Reserved 4 | * 5 | **************************************************************************/ 6 | 7 | 8 | 9 | /** 10 | * @file test_udp_server.cc 11 | * @author aishuyu(asy5178@163.com) 12 | * @date 2016/05/25 19:52:16 13 | * @brief 14 | * 15 | **/ 16 | 17 | #include 18 | #include 19 | #include 20 | 21 | #include 22 | #include 23 | 24 | #include "test_def.h" 25 | #include "../util/rpc_communication.h" 26 | 27 | using namespace libevrpc; 28 | 29 | int main() { 30 | 31 | int32_t server_fd = UdpServerInit(ADDR, PORT); 32 | 33 | std::string recv_info; 34 | while (true) { 35 | if (RpcRecvFrom(server_fd, recv_info, false) < 0) { 36 | break; 37 | } 38 | sleep(2); 39 | } 40 | 41 | // printf("Test recv_info is :%s\n", recv_info.c_str()); 42 | 43 | return 0; 44 | } 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | /* vim: set expandtab ts=4 sw=4 sts=4 tw=100: */ 58 | -------------------------------------------------------------------------------- /src/util/rpc_controller.cpp: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * 3 | * Copyright (c) 2015 aishuyu, Inc. All Rights Reserved 4 | * 5 | **************************************************************************/ 6 | 7 | 8 | 9 | /** 10 | * @file rpc_controller.cpp 11 | * @author aishuyu(asy5178@163.com) 12 | * @date 2016/03/31 20:47:09 13 | * @brief 14 | * 15 | **/ 16 | 17 | #include "rpc_controller.h" 18 | 19 | namespace libevrpc { 20 | 21 | RpcController::RpcController() { 22 | } 23 | 24 | RpcController::~RpcController() { 25 | } 26 | 27 | void RpcController::Reset() { 28 | } 29 | 30 | bool RpcController::Failed() const { 31 | return true; 32 | } 33 | 34 | string RpcController::ErrorText() const { 35 | } 36 | 37 | void RpcController::StartCancel() { 38 | } 39 | 40 | void RpcController::SetFailed(const string& reason) { 41 | } 42 | 43 | bool RpcController::IsCanceled() const { 44 | } 45 | 46 | void RpcController::NotifyOnCancel(Closure* callback) { 47 | } 48 | 49 | 50 | 51 | } // end of namespace libevrpc 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | /* vim: set expandtab ts=4 sw=4 sts=4 tw=100: */ 62 | -------------------------------------------------------------------------------- /src/center_proto/centers.proto: -------------------------------------------------------------------------------- 1 | package libevrpc; 2 | 3 | import "center_type.proto"; 4 | import "center_client.proto"; 5 | import "center_cluster.proto"; 6 | 7 | // 选举算法使用,决定哪一台机器为Leader,便于同步全局RpcServer列表 8 | enum CenterStatus { 9 | LOOKING = 0; 10 | FOLLOWING = 1; 11 | OBSERVING = 2; 12 | LEADING = 3; 13 | UNKONW = 4; 14 | DEAD = 5; 15 | } 16 | 17 | enum CenterAction { 18 | INQUIRY = 0; 19 | PROPOSAL = 1; 20 | LEADER_CONFIRM = 2; 21 | ACCEPT = 3; 22 | REFUSED = 4; 23 | FOLLOWER_PING = 5; 24 | LEADER_PING_RESPONSE = 6; 25 | CENTER_REPORTER = 7; 26 | } 27 | 28 | message LoadBalancerMetaData { 29 | optional uint32 vid = 1; 30 | optional string server_addr = 2; 31 | } 32 | 33 | message CentersProto { 34 | optional string from_center_addr = 1; 35 | optional CenterStatus center_status = 2; 36 | optional CenterAction center_action = 3; 37 | optional uint64 start_time = 4; 38 | optional uint64 lc_start_time = 5; 39 | optional uint64 logical_clock = 6; 40 | optional string leader_center = 7; 41 | repeated RpcClusterServer server_infos_list = 8; 42 | repeated LoadBalancerMetaData lb_result = 9; 43 | } 44 | 45 | 46 | -------------------------------------------------------------------------------- /src/util/rpc_controller.h: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * 3 | * Copyright (c) 2015 aishuyu, Inc. All Rights Reserved 4 | * 5 | **************************************************************************/ 6 | 7 | 8 | 9 | /** 10 | * @file rpc_controller.h 11 | * @author aishuyu(asy5178@163.com) 12 | * @date 2016/03/31 20:41:10 13 | * @brief 14 | * 15 | **/ 16 | 17 | 18 | 19 | 20 | #ifndef __RPC_CONTROLLER_H 21 | #define __RPC_CONTROLLER_H 22 | 23 | #include 24 | 25 | 26 | namespace libevrpc { 27 | 28 | class RpcController : public google::protobuf::RpcController { 29 | public: 30 | RpcController(); 31 | ~RpcController(); 32 | 33 | void Reset(); 34 | bool Failed() const; 35 | string ErrorText() const; 36 | void StartCancel(); 37 | void SetFailed(const string& reason); 38 | bool IsCanceled() const; 39 | void NotifyOnCancel(Closure* callback); 40 | 41 | }; 42 | 43 | 44 | } // end of namespace libevrpc 45 | 46 | 47 | 48 | 49 | 50 | #endif // __RPC_CONTROLLER_H 51 | 52 | 53 | 54 | /* vim: set expandtab ts=4 sw=4 sts=4 tw=100: */ 55 | -------------------------------------------------------------------------------- /src/rpc_center/reporter_thread.h: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * 3 | * Copyright (c) 2016 aishuyu, Inc. All Rights Reserved 4 | * 5 | **************************************************************************/ 6 | 7 | 8 | 9 | /** 10 | * @file reporter_thread.h 11 | * @author aishuyu(asy5178@163.com) 12 | * @date 2016/07/16 22:42:27 13 | * @brief 14 | * 15 | **/ 16 | 17 | 18 | 19 | 20 | #ifndef __REPORTER_THREAD_H 21 | #define __REPORTER_THREAD_H 22 | 23 | #include "util/thread.h" 24 | 25 | namespace libevrpc { 26 | 27 | /* 28 | * 与Leader机器通信, 交换信息 29 | */ 30 | class ReporterThread : public Thread { 31 | public: 32 | ReporterThread(); 33 | ~ReporterThread(); 34 | 35 | bool StartReporter( 36 | const char* leader_addr, 37 | const char* leader_port); 38 | 39 | virtual void Run(); 40 | 41 | private: 42 | char* leader_addr_; 43 | char* leader_port_; 44 | 45 | bool reporter_running_; 46 | int32_t conn_fd_; 47 | 48 | }; 49 | 50 | } // end of namespace libevrpc 51 | 52 | 53 | 54 | 55 | #endif // __REPORTER_THREAD_H 56 | 57 | 58 | 59 | /* vim: set expandtab ts=4 sw=4 sts=4 tw=100: */ 60 | -------------------------------------------------------------------------------- /libevrpc.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # chkconfig: 2345 80 50 4 | # description: data_server is for testing how to write service in Linux 5 | # 6 | # processname: data_server 7 | # 8 | # Source function library. 9 | . /etc/rc.d/init.d/functions 10 | 11 | ret=0 12 | 13 | start() { 14 | # check fdb status 15 | echo "start data_server" 16 | ./data_server & 17 | ret=$? 18 | } 19 | 20 | stop() { 21 | echo "stop data_server" 22 | kill -9 $(ps -ef | grep data_server | grep -v grep | awk '{print $2}') 23 | ret=$? 24 | } 25 | 26 | status() { 27 | local result 28 | echo "check status of data_server..." 29 | result=$( ps -ef | grep -v data_server | grep -v grep | wc -l ) 30 | if [ $result -gt 0 ] ; then 31 | echo "data_server is up" 32 | ret=0 33 | else 34 | echo "data_server is down" 35 | ret=1 36 | fi 37 | echo "check status of data_server...done." 38 | } 39 | 40 | # See how we were called. 41 | case "$1" in 42 | start) 43 | start 44 | ;; 45 | stop) 46 | stop 47 | ;; 48 | status) 49 | status 50 | ;; 51 | restart) 52 | stop 53 | start 54 | ;; 55 | *) 56 | echo $"Usage: $0 {start|stop|status}" 57 | exit 1 58 | esac 59 | 60 | exit $ret 61 | -------------------------------------------------------------------------------- /sample/libevrpc.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # chkconfig: 2345 80 50 4 | # description: data_server is for testing how to write service in Linux 5 | # 6 | # processname: data_server 7 | # 8 | # Source function library. 9 | . /etc/rc.d/init.d/functions 10 | 11 | ret=0 12 | 13 | start() { 14 | # check fdb status 15 | echo "start data_server" 16 | ./data_server & 17 | ret=$? 18 | } 19 | 20 | stop() { 21 | echo "stop data_server" 22 | kill -9 $(ps -ef | grep data_server | grep -v grep | awk '{print $2}') 23 | ret=$? 24 | } 25 | 26 | status() { 27 | local result 28 | echo "check status of data_server..." 29 | result=$( ps -ef | grep -v data_server | grep -v grep | wc -l ) 30 | if [ $result -gt 0 ] ; then 31 | echo "data_server is up" 32 | ret=0 33 | else 34 | echo "data_server is down" 35 | ret=1 36 | fi 37 | echo "check status of data_server...done." 38 | } 39 | 40 | # See how we were called. 41 | case "$1" in 42 | start) 43 | start 44 | ;; 45 | stop) 46 | stop 47 | ;; 48 | status) 49 | status 50 | ;; 51 | restart) 52 | stop 53 | start 54 | ;; 55 | *) 56 | echo $"Usage: $0 {start|stop|status}" 57 | exit 1 58 | esac 59 | 60 | exit $ret 61 | -------------------------------------------------------------------------------- /src/unit_test/configure.ac: -------------------------------------------------------------------------------- 1 | # -*- Autoconf -*- 2 | # Process this file with autoconf to produce a configure script. 3 | 4 | AC_PREREQ([2.60]) 5 | AC_INIT([libevrpc], [0.0.2], [asy5178@163.com]) 6 | 7 | # Checks for programs. 8 | AC_PROG_INSTALL 9 | AC_PROG_MAKE_SET 10 | AM_INIT_AUTOMAKE 11 | AC_PROG_RANLIB 12 | 13 | AC_PROG_CXX 14 | AC_PROG_CC 15 | AC_PROG_INSTALL 16 | AC_PROG_MAKE_SET 17 | 18 | # Checks for libraries. 19 | # FIXME: Replace `main' with a function in `-lm': 20 | AC_CHECK_LIB([m], [main]) 21 | # FIXME: Replace `main' with a function in `-lpthread': 22 | AC_CHECK_LIB([pthread], [main]) 23 | # FIXME: Replace `main' with a function in `-lrt': 24 | AC_CHECK_LIB([rt], [main]) 25 | # FIXME: Replace `main' with a function in `-lz': 26 | AC_CHECK_LIB([z], [main]) 27 | 28 | # Checks for header files. 29 | AC_CHECK_HEADERS([arpa/inet.h fcntl.h netdb.h netinet/in.h stdint.h stdlib.h sys/socket.h unistd.h]) 30 | 31 | # Checks for typedefs, structures, and compiler characteristics. 32 | AC_CHECK_HEADER_STDBOOL 33 | AC_C_INLINE 34 | AC_TYPE_INT32_T 35 | AC_TYPE_SIZE_T 36 | AC_TYPE_UINT32_T 37 | 38 | # Checks for library functions. 39 | AC_FUNC_MALLOC 40 | AC_CHECK_FUNCS([bzero memset socket strerror]) 41 | 42 | CXXFLAGS=-std=c++11 43 | 44 | AC_CONFIG_FILES([Makefile]) 45 | AC_OUTPUT 46 | -------------------------------------------------------------------------------- /sample/configure.ac: -------------------------------------------------------------------------------- 1 | # -*- Autoconf -*- 2 | # Process this file with autoconf to produce a configure script. 3 | 4 | AC_PREREQ([2.60]) 5 | AC_INIT([libevrpc], [0.0.2], [asy5178@163.com]) 6 | 7 | # Checks for programs. 8 | AC_PROG_INSTALL 9 | AC_PROG_MAKE_SET 10 | AM_INIT_AUTOMAKE 11 | AC_PROG_RANLIB 12 | AC_PROG_LIBTOOL 13 | 14 | AC_PROG_CXX 15 | AC_PROG_CC 16 | AC_PROG_INSTALL 17 | AC_PROG_MAKE_SET 18 | 19 | # Checks for libraries. 20 | # FIXME: Replace `main' with a function in `-lm': 21 | AC_CHECK_LIB([m], [main]) 22 | # FIXME: Replace `main' with a function in `-lpthread': 23 | AC_CHECK_LIB([pthread], [main]) 24 | # FIXME: Replace `main' with a function in `-lrt': 25 | AC_CHECK_LIB([rt], [main]) 26 | # FIXME: Replace `main' with a function in `-lz': 27 | AC_CHECK_LIB([z], [main]) 28 | 29 | # Checks for header files. 30 | #AC_CHECK_HEADERS([arpa/inet.h fcntl.h netdb.h netinet/in.h stdint.h stdlib.h sys/socket.h unistd.h]) 31 | AC_CONFIG_HEADERS 32 | 33 | # Checks for typedefs, structures, and compiler characteristics. 34 | AC_C_INLINE 35 | AC_TYPE_INT32_T 36 | AC_TYPE_SIZE_T 37 | AC_TYPE_UINT32_T 38 | 39 | # Checks for library functions. 40 | AC_FUNC_MALLOC 41 | AC_CHECK_FUNCS([bzero memset socket strerror]) 42 | 43 | CXXFLAGS=-std=c++11 44 | 45 | AC_CONFIG_FILES([Makefile]) 46 | AC_OUTPUT 47 | -------------------------------------------------------------------------------- /src/unit_test/test_udp_client.cc: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * 3 | * Copyright (c) 2016 aishuyu, Inc. All Rights Reserved 4 | * 5 | **************************************************************************/ 6 | 7 | 8 | 9 | /** 10 | * @file test_udp_client.cc 11 | * @author aishuyu(asy5178@163.com) 12 | * @date 2016/05/25 20:08:24 13 | * @brief 14 | * 15 | **/ 16 | 17 | #include 18 | #include 19 | 20 | #include 21 | #include 22 | #include 23 | 24 | #include "test_def.h" 25 | #include "../util/rpc_communication.h" 26 | 27 | using namespace libevrpc; 28 | 29 | int main() { 30 | 31 | struct sockaddr_in to; 32 | int32_t conn_fd = UdpClientInit(ADDR, PORT, to); 33 | 34 | printf("Test UdpClientInit done! conn_fd is %d error no is %s\n", conn_fd, strerror(errno)); 35 | 36 | std::string send_info = "udp Test123456789"; 37 | int32_t ret = RpcSendTo(conn_fd, to, send_info, true); 38 | if (ret < 0) { 39 | printf("RpcSendTo error\n"); 40 | } else { 41 | printf("RpcSendTo sucessful ret is %d\n", ret); 42 | } 43 | 44 | sleep(200); 45 | 46 | return 0; 47 | } 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | /* vim: set expandtab ts=4 sw=4 sts=4 tw=100: */ 61 | -------------------------------------------------------------------------------- /configure.ac: -------------------------------------------------------------------------------- 1 | # -*- Autoconf -*- 2 | # Process this file with autoconf to produce a configure script. 3 | 4 | AC_PREREQ([2.60]) 5 | AC_INIT([libevrpc], [0.0.2], [asy5178@163.com]) 6 | 7 | # Checks for programs. 8 | AC_PROG_INSTALL 9 | AC_PROG_MAKE_SET 10 | AM_INIT_AUTOMAKE 11 | AC_PROG_RANLIB 12 | AC_PROG_LIBTOOL 13 | 14 | AC_PROG_CXX 15 | AC_PROG_CC 16 | AC_PROG_INSTALL 17 | AC_PROG_MAKE_SET 18 | 19 | # Checks for libraries. 20 | # FIXME: Replace `main' with a function in `-lm': 21 | AC_CHECK_LIB([m], [main]) 22 | # FIXME: Replace `main' with a function in `-lpthread': 23 | AC_CHECK_LIB([pthread], [main]) 24 | # FIXME: Replace `main' with a function in `-lrt': 25 | AC_CHECK_LIB([rt], [main]) 26 | # FIXME: Replace `main' with a function in `-lz': 27 | AC_CHECK_LIB([z], [main]) 28 | 29 | # Checks for header files. 30 | #AC_CHECK_HEADERS([arpa/inet.h fcntl.h netdb.h netinet/in.h stdint.h stdlib.h sys/socket.h unistd.h]) 31 | AC_CONFIG_HEADERS 32 | 33 | # Checks for typedefs, structures, and compiler characteristics. 34 | AC_C_INLINE 35 | AC_TYPE_INT32_T 36 | AC_TYPE_SIZE_T 37 | AC_TYPE_UINT32_T 38 | 39 | # Checks for library functions. 40 | AC_FUNC_MALLOC 41 | AC_CHECK_FUNCS([bzero memset socket strerror]) 42 | 43 | CXXFLAGS=-std=c++11 44 | 45 | AC_CONFIG_FILES([Makefile 46 | src/Makefile]) 47 | AC_OUTPUT 48 | -------------------------------------------------------------------------------- /src/rpc_server/center_cluster_heartbeat.h: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * 3 | * Copyright (c) 2016 aishuyu, Inc. All Rights Reserved 4 | * 5 | **************************************************************************/ 6 | 7 | 8 | 9 | /** 10 | * @file center_cluster_heartbeat.h 11 | * @author aishuyu(asy5178@163.com) 12 | * @date 2016/09/07 20:43:13 13 | * @brief 14 | * 15 | **/ 16 | 17 | 18 | 19 | 20 | #ifndef __CENTER_CLUSTER_HEARTBEAT_H 21 | #define __CENTER_CLUSTER_HEARTBEAT_H 22 | 23 | #include 24 | #include 25 | 26 | #include "util/thread.h" 27 | 28 | namespace libevrpc { 29 | 30 | typedef std::vector ADDRS_LIST_TYPE; 31 | 32 | class CenterClusterHeartbeat : public Thread { 33 | public: 34 | CenterClusterHeartbeat(const std::string& config_file); 35 | ~CenterClusterHeartbeat(); 36 | 37 | bool InitCenterClusterHB(); 38 | 39 | virtual void Run(); 40 | 41 | private: 42 | std::string config_file_; 43 | ADDRS_LIST_TYPE* center_addrs_ptr_; 44 | ADDRS_LIST_TYPE* reporter_center_addrs_ptr_; 45 | 46 | bool running_; 47 | char* center_port_; 48 | }; 49 | 50 | } // end of namespace libevrpc 51 | 52 | 53 | 54 | 55 | 56 | 57 | #endif // __CENTER_CLUSTER_HEARTBEAT_H 58 | 59 | 60 | 61 | /* vim: set expandtab ts=4 sw=4 sts=4 tw=100: */ 62 | -------------------------------------------------------------------------------- /src/rpc_client/rpc_heartbeat_client.h: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * 3 | * Copyright (c) 2016 aishuyu, Inc. All Rights Reserved 4 | * 5 | **************************************************************************/ 6 | 7 | 8 | 9 | /** 10 | * @file rpc_heartbeat_client.h 11 | * @author aishuyu(asy5178@163.com) 12 | * @date 2016/04/04 21:04:43 13 | * @brief 14 | * 15 | **/ 16 | 17 | 18 | 19 | 20 | #ifndef __RPC_HEARTBEAT_CLIENT_H 21 | #define __RPC_HEARTBEAT_CLIENT_H 22 | 23 | #include 24 | #include 25 | 26 | #include "util/thread.h" 27 | 28 | namespace libevrpc { 29 | 30 | class RpcHeartbeatClient : public Thread { 31 | public: 32 | RpcHeartbeatClient(const char* hb_server_addr, 33 | const char* hb_server_port, 34 | int32_t timeout); 35 | ~RpcHeartbeatClient(); 36 | 37 | bool CreateRpcConnection(); 38 | virtual void Run(); 39 | 40 | private: 41 | char* hb_server_addr_; 42 | char* hb_server_port_; 43 | int32_t timeout_; 44 | int32_t connect_fd_; 45 | struct sockaddr_in to_; 46 | 47 | volatile bool running_; 48 | }; 49 | 50 | } // end of namespace libevrpc 51 | 52 | 53 | 54 | 55 | 56 | 57 | #endif // __RPC_HEARTBEAT_CLIENT_H 58 | 59 | 60 | 61 | /* vim: set expandtab ts=4 sw=4 sts=4 tw=100: */ 62 | -------------------------------------------------------------------------------- /sample/Makefile.am: -------------------------------------------------------------------------------- 1 | AUTOMAKE_OPTIONS=foreign subdir-objects 2 | 3 | top_dir = ${top_srcdir}/../.. 4 | cs_rootdir = ${top_srcdir} 5 | third_dir = ${top_dir}/third-64 6 | 7 | #SUBDIRS = proto 8 | 9 | INCLUDES = -I${third_dir}/protobuf/include/ \ 10 | -I${third_dir}/libevrpc/include/ \ 11 | -I${third_dir}/libev/include/ \ 12 | -I${cs_rootdir}/ 13 | 14 | 15 | #AM_LDFLAGS = -rdynamic -lpthread -lz -lm -lrt 16 | rpc_client_LDFLAGS = -lpthread -lz -lm 17 | 18 | #$(top_builddir)/src/rpc_server/librpc_server.a 19 | 20 | 21 | LDADD = ${third_dir}/libevrpc/lib/*.a \ 22 | ${third_dir}/protobuf/lib/*.a \ 23 | ${third_dir}/libev/lib/*.a 24 | 25 | bin_PROGRAMS = rpc_server rpc_client 26 | 27 | SERVER_SRC = ${cs_rootdir}/src/libev_server.cc \ 28 | ${cs_rootdir}/proto/rpc_sample.pb.h \ 29 | ${cs_rootdir}/proto/rpc_sample.pb.cc 30 | rpc_server_SOURCES = ${SERVER_SRC} 31 | 32 | CLIENT_SRC = ${cs_rootdir}/src/libev_client.cc \ 33 | ${cs_rootdir}/proto/rpc_sample.pb.h \ 34 | ${cs_rootdir}/proto/rpc_sample.pb.cc 35 | rpc_client_SOURCES = ${CLIENT_SRC} 36 | 37 | # rpc_client_LDADD = $(top_builddir)/src/rpc_client/librpc_client.a \ 38 | # $(top_builddir)/src/cs_sample/proto/libproto.a \ 39 | # ${third_dir}/protobuf/lib/*.a \ 40 | # ${third_dir}/libev/lib/*.a 41 | # 42 | # bin_PROGRAMS = rpc_client 43 | # 44 | # CLIENT_SRC = ${cs_rootdir}/libev_client.cc 45 | # rpc_client_SOURCES = ${CLIENT_SRC} 46 | -------------------------------------------------------------------------------- /share/configure_sample.ac: -------------------------------------------------------------------------------- 1 | # -*- Autoconf -*- 2 | # Process this file with autoconf to produce a configure script. 3 | 4 | AC_PREREQ([2.69]) 5 | AC_INIT([libevrpc], [0.0.2], [asy5178@163.com]) 6 | 7 | # Checks for programs. 8 | AC_PROG_INSTALL 9 | AC_PROG_MAKE_SET 10 | AM_INIT_AUTOMAKE 11 | AC_PROG_RANLIB 12 | 13 | AC_PROG_CXX 14 | AC_PROG_CC 15 | AC_PROG_INSTALL 16 | AC_PROG_MAKE_SET 17 | 18 | # Checks for libraries. 19 | # FIXME: Replace `main' with a function in `-lm': 20 | AC_CHECK_LIB([m], [main]) 21 | # FIXME: Replace `main' with a function in `-lpthread': 22 | AC_CHECK_LIB([pthread], [main]) 23 | # FIXME: Replace `main' with a function in `-lrt': 24 | AC_CHECK_LIB([rt], [main]) 25 | # FIXME: Replace `main' with a function in `-lz': 26 | AC_CHECK_LIB([z], [main]) 27 | 28 | # Checks for header files. 29 | AC_CHECK_HEADERS([arpa/inet.h fcntl.h netdb.h netinet/in.h stdint.h stdlib.h sys/socket.h unistd.h]) 30 | 31 | # Checks for typedefs, structures, and compiler characteristics. 32 | AC_CHECK_HEADER_STDBOOL 33 | AC_C_INLINE 34 | AC_TYPE_INT32_T 35 | AC_TYPE_SIZE_T 36 | AC_TYPE_UINT32_T 37 | 38 | # Checks for library functions. 39 | AC_FUNC_MALLOC 40 | AC_CHECK_FUNCS([bzero memset socket strerror]) 41 | 42 | AC_CONFIG_FILES([Makefile 43 | src/Makefile 44 | src/cs_sample/Makefile 45 | src/cs_sample/proto/Makefile 46 | src/rpc/Makefile]) 47 | AC_OUTPUT 48 | -------------------------------------------------------------------------------- /sample/build_sample.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | BUILD_ROOT=$PWD 4 | CLIENT_SRC_PATH=$BUILD_ROOT 5 | SERVER_SRC_PATH=$BUILD_ROOT 6 | 7 | START_FILE=$BUILD_ROOT/libevrpc.sh 8 | SAMPLE_PATH=$BUILD_ROOT/rpc_sample 9 | CONF_PATH=$BUILD_ROOT 10 | CONF_FILE=$CONF_PATH/*.ini 11 | 12 | # check the bootstrap exist. 13 | if [ ! -f $BUILD_ROOT/bootstrap.sh ] 14 | then 15 | echo "the bootstrap.sh does not exist!" 16 | exit -1 17 | fi 18 | 19 | make distclean 20 | ./bootstrap.sh clean 21 | ./bootstrap.sh 22 | 23 | # check the configure file 24 | if [ ! -f $BUILD_ROOT/configure ] 25 | then 26 | echo "the configure does not exist!" 27 | exit -1 28 | fi 29 | 30 | # make the project 31 | ./configure --disable-dependency-tracking && make 32 | if [ $? -ne 0 ] 33 | then 34 | echo "make the project failed!" 35 | exit -1 36 | fi 37 | 38 | ## make sure the config file exist 39 | #if [ ! -f $CONF_FILE ] 40 | #then 41 | # echo "the config file $CONF_FILE does not exist" 42 | # exit -1 43 | #fi 44 | 45 | if [ ! -f $START_FILE ] 46 | then 47 | echo "the $START_FILE file does not exist" 48 | exit -1 49 | fi 50 | 51 | 52 | if [ -d $SAMPLE_PATH ] 53 | then 54 | rm -rf $SAMPLE_PATH 55 | fi 56 | mkdir -p $SAMPLE_PATH 57 | 58 | 59 | mv $CLIENT_SRC_PATH/rpc_client $SERVER_SRC_PATH/rpc_server $SAMPLE_PATH && \ 60 | cp $START_FILE $SAMPLE_PATH 61 | cp -r $CONF_FILE $SAMPLE_PATH && \ 62 | 63 | if [ $? -ne 0 ] 64 | then 65 | echo "build the clint bin failed" 66 | exit -1 67 | fi 68 | 69 | 70 | make distclean 71 | ./bootstrap.sh clean 72 | -------------------------------------------------------------------------------- /src/unit_test/test_hb_client.cc: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * 3 | * Copyright (c) 2016 aishuyu, Inc. All Rights Reserved 4 | * 5 | **************************************************************************/ 6 | 7 | 8 | 9 | /** 10 | * @file test_hb_client.cc 11 | * @author aishuyu(asy5178@163.com) 12 | * @date 2016/05/08 21:33:56 13 | * @brief 14 | * 15 | **/ 16 | 17 | #include 18 | 19 | #include "util/rpc_util.h" 20 | #include "util/rpc_communication.h" 21 | #include "rpc_client/rpc_heartbeat_client.h" 22 | 23 | using namespace libevrpc; 24 | 25 | int main() { 26 | int32_t conn_fd = TcpConnect(GetLocalAddress(), "7777", 10000); 27 | //int32_t conn_fd = TcpConnect("127.0.0.1", "7777", 10000); 28 | 29 | if (conn_fd < 0) { 30 | printf("Tcp conncect error!\n"); 31 | return 0; 32 | } 33 | RpcHeartbeatClient rhc(GetLocalAddress() ,"9999", 1000); 34 | // RpcHeartbeatClient rhc("127.0.0.1", "9999", 1000); 35 | printf("RpcHeartbeatClient start\n"); 36 | rhc.Start(); 37 | 38 | std::string test_str = "123start12345678901234567890end123"; 39 | 40 | // int32_t ret = RpcSend(conn_fd, 0, test_str, true); 41 | printf("RpcHeartbeatClient start\n"); 42 | // printf("ret id is %d\n", ret); 43 | 44 | printf("RpcHeartbeatClient sleep\n"); 45 | sleep(50); 46 | rhc.Stop(); 47 | rhc.Wait(); 48 | return 0; 49 | } 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | /* vim: set expandtab ts=4 sw=4 sts=4 tw=100: */ 62 | -------------------------------------------------------------------------------- /src/rpc_server/server_rpc_controller.cpp: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * 3 | * Copyright (c) 2016 aishuyu, Inc. All Rights Reserved 4 | * 5 | **************************************************************************/ 6 | 7 | 8 | 9 | /** 10 | * @file server_rpc_controller.cpp 11 | * @author aishuyu(asy5178@163.com) 12 | * @date 2016/04/04 00:12:42 13 | * @brief 14 | * 15 | **/ 16 | 17 | 18 | #include "server_rpc_controller.h" 19 | 20 | 21 | namespace libevrpc { 22 | 23 | using std::string; 24 | using google::protobuf::Closure; 25 | 26 | ServerRpcController::ServerRpcController() : error_info_("") { 27 | } 28 | 29 | ServerRpcController::~ServerRpcController() { 30 | } 31 | 32 | void ServerRpcController::Reset() { 33 | error_info_.clear(); 34 | } 35 | 36 | bool ServerRpcController::Failed() const { 37 | return !error_info_.empty(); 38 | } 39 | 40 | string ServerRpcController::ErrorText() const { 41 | return error_info_; 42 | } 43 | 44 | void ServerRpcController::StartCancel() { 45 | /* 46 | * TODO 47 | */ 48 | } 49 | 50 | void ServerRpcController::SetFailed(const string& reason) { 51 | error_info_ = reason; 52 | } 53 | 54 | bool ServerRpcController::IsCanceled() const { 55 | /* 56 | * TODO 57 | */ 58 | } 59 | 60 | void ServerRpcController::NotifyOnCancel(Closure* callback) { 61 | /* 62 | * TODO 63 | */ 64 | } 65 | 66 | } // namespace of libevrpc 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | /* vim: set expandtab ts=4 sw=4 sts=4 tw=100: */ 76 | -------------------------------------------------------------------------------- /src/rpc_center/load_balancer/load_balancer.h: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * 3 | * Copyright (c) 2016 aishuyu, Inc. All Rights Reserved 4 | * 5 | **************************************************************************/ 6 | 7 | 8 | 9 | /** 10 | * @file load_balancer.h 11 | * @author aishuyu(asy5178@163.com) 12 | * @date 2016/07/12 20:40:20 13 | * @brief 14 | * 15 | **/ 16 | 17 | 18 | 19 | 20 | #ifndef __LOAD_BALANCER_H 21 | #define __LOAD_BALANCER_H 22 | 23 | #include 24 | #include 25 | 26 | #include "center_proto/centers.pb.h" 27 | #include "center_proto/center_cluster.pb.h" 28 | 29 | namespace libevrpc { 30 | 31 | class LoadBalancer { 32 | public: 33 | virtual ~LoadBalancer() {} 34 | 35 | virtual bool InitBalancer() = 0; 36 | virtual void SetConfigFile(const std::string& file_name) = 0; 37 | virtual bool AddRpcServer(const RpcClusterServer& rpc_cluster_server) = 0; 38 | virtual bool GetRpcServer(const std::string& rpc_client, std::vector& rpc_server_list) = 0; 39 | virtual bool GetCurrentLBResult(::google::protobuf::RepeatedPtrField& lb_result_list) = 0; 40 | virtual bool UpdateLBResult(const ::google::protobuf::RepeatedPtrField& lb_result_list) = 0; 41 | 42 | 43 | }; // end of namespace libevrpc 44 | 45 | 46 | } // end of namespace libevrpc 47 | 48 | 49 | 50 | 51 | 52 | #endif // __LOAD_BALANCER_H 53 | 54 | 55 | 56 | /* vim: set expandtab ts=4 sw=4 sts=4 tw=100: */ 57 | -------------------------------------------------------------------------------- /src/rpc_server/rpc_heartbeat_server.h: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * 3 | * Copyright (c) 2016 aishuyu, Inc. All Rights Reserved 4 | * 5 | **************************************************************************/ 6 | 7 | 8 | 9 | /** 10 | * @file rpc_heartbeat_server.h 11 | * @author aishuyu(asy5178@163.com) 12 | * @date 2016/04/04 22:08:26 13 | * @brief 14 | * 15 | **/ 16 | 17 | 18 | 19 | 20 | #ifndef __RPC_HEARTBEAT_SERVER_H 21 | #define __RPC_HEARTBEAT_SERVER_H 22 | 23 | // #include 24 | #include 25 | 26 | #include "util/thread.h" 27 | 28 | namespace libevrpc { 29 | 30 | class RpcHeartbeatServer : public Thread { 31 | public: 32 | RpcHeartbeatServer( 33 | const char* hb_host, 34 | const char* hb_port, 35 | const char* config_file); 36 | ~RpcHeartbeatServer(); 37 | 38 | bool InitHeartbeatServer(); 39 | 40 | virtual void Run(); 41 | 42 | /* 43 | * recv the hearbeat in libev and put the hb info 44 | * into connection timer manager 45 | */ 46 | static void HeartBeatProcessor(struct ev_loop *loop, struct ev_io *watcher, int revents); 47 | 48 | private: 49 | char* hb_host_; 50 | char* hb_port_; 51 | char* config_file_; 52 | 53 | bool hb_running_; 54 | 55 | struct ev_loop *epoller_; 56 | struct ev_io socket_watcher_; 57 | 58 | }; 59 | 60 | } // end of namespace libevrpc 61 | 62 | 63 | 64 | 65 | #endif // __RPC_HEARTBEAT_SERVER_H 66 | 67 | 68 | 69 | /* vim: set expandtab ts=4 sw=4 sts=4 tw=100: */ 70 | -------------------------------------------------------------------------------- /src/rpc_client/client_rpc_controller.cpp: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * 3 | * Copyright (c) 2016 aishuyu, Inc. All Rights Reserved 4 | * 5 | **************************************************************************/ 6 | 7 | 8 | 9 | /** 10 | * @file client_rpc_controller.cpp 11 | * @author aishuyu(asy5178@163.com) 12 | * @date 2016/04/04 00:04:09 13 | * @brief 14 | * 15 | **/ 16 | 17 | 18 | 19 | 20 | #include "client_rpc_controller.h" 21 | 22 | namespace libevrpc { 23 | 24 | using std::string; 25 | using google::protobuf::Closure; 26 | 27 | ClientRpcController::ClientRpcController() : error_info_("") { 28 | } 29 | 30 | ClientRpcController::~ClientRpcController() { 31 | } 32 | 33 | void ClientRpcController::Reset() { 34 | error_info_.clear(); 35 | } 36 | 37 | bool ClientRpcController::Failed() const { 38 | return !error_info_.empty(); 39 | } 40 | 41 | string ClientRpcController::ErrorText() const { 42 | ReadLockGuard rguard(error_info_rwlock_); 43 | return error_info_; 44 | } 45 | 46 | void ClientRpcController::StartCancel() { 47 | /* 48 | * TODO 49 | */ 50 | } 51 | 52 | void ClientRpcController::SetFailed(const string& reason) { 53 | WriteLockGuard wguard(error_info_rwlock_); 54 | error_info_.append(reason + "\n"); 55 | } 56 | 57 | bool ClientRpcController::IsCanceled() const { 58 | /* 59 | * TODO 60 | */ 61 | } 62 | 63 | void ClientRpcController::NotifyOnCancel(Closure* callback) { 64 | /* 65 | * TODO 66 | */ 67 | } 68 | 69 | } // namespace of libevrpc 70 | 71 | 72 | 73 | 74 | 75 | /* vim: set expandtab ts=4 sw=4 sts=4 tw=100: */ 76 | -------------------------------------------------------------------------------- /src/unit_test/build_ut.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | #!/bin/bash 3 | 4 | #build the data_server 5 | #must have the bootstrap.sh file or be failed for sure 6 | #must install automake 7 | 8 | BUILD_ROOT=$PWD 9 | 10 | SRC_ROOT=$BUILD_ROOT/src 11 | 12 | SERVER_PATH=$BUILD_ROOT/libevrpc 13 | 14 | echo $BUILD_ROOT 15 | 16 | 17 | if [ "$1" == "clean" ]; then 18 | make distclean 19 | ./bootstrap.sh clean 20 | exit 21 | fi 22 | 23 | 24 | # check the bootstrap exist. 25 | if [ ! -f $BUILD_ROOT/bootstrap.sh ] 26 | then 27 | echo "the bootstrap.sh does not exist!" 28 | exit -1 29 | fi 30 | 31 | # clean the .o file in order to make the proj 32 | if [ -d $SERVER_PATH ] 33 | then 34 | rm -rf $SERVER_PATH 35 | fi 36 | make distclean && ./bootstrap.sh clean 37 | ./bootstrap.sh 38 | 39 | # check the configure file 40 | if [ ! -f $BUILD_ROOT/configure ] 41 | then 42 | echo "the configure does not exist!" 43 | exit -1 44 | fi 45 | 46 | # make the project 47 | ./configure --disable-dependency-tracking && make 48 | if [ $? -ne 0 ] 49 | then 50 | echo "make the project failed!" 51 | exit -1 52 | fi 53 | 54 | 55 | 56 | #start to collect the project file 57 | 58 | ## make sure the config file exist 59 | #if [ ! -f $CONF_FILE ] 60 | #then 61 | # echo "the config file $CONF_FILE does not exist" 62 | # exit -1 63 | #fi 64 | 65 | echo "" 66 | echo "*******************************************" 67 | echo "build the ut successfully!!" 68 | echo "*******************************************" 69 | echo "" 70 | 71 | 72 | #make distclean 1>/dev/null 2>&1 73 | #./bootstrap.sh clean 1>/dev/null 2>&1 74 | 75 | #make distclean && ./bootstrap.sh clean 76 | 77 | 78 | -------------------------------------------------------------------------------- /src/unit_test/test_libev_tp.cc: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * 3 | * Copyright (c) 2015 aishuyu, Inc. All Rights Reserved 4 | * 5 | **************************************************************************/ 6 | 7 | 8 | 9 | /** 10 | * @file test_libev_tp.cpp 11 | * @author aishuyu(asy5178@163.com) 12 | * @date 2015/12/13 22:51:29 13 | * @brief 14 | * 15 | **/ 16 | 17 | #include 18 | 19 | #include "rpc_server/libev_thread_pool.h" 20 | 21 | using namespace libevrpc; 22 | using std::string; 23 | 24 | typedef struct { 25 | string cc; 26 | } TS; 27 | 28 | void* RpcCallTest(void *arg) { 29 | TS* ts = (TS*)arg; 30 | if (NULL != ts) { 31 | printf("Test ts %s\n", ts->cc.c_str()); 32 | } 33 | for (int i = 0; i < 100; ++i) { 34 | printf("Test ts %s\n", ts->cc.c_str()); 35 | sleep(1); 36 | } 37 | } 38 | 39 | int main() { 40 | LibevThreadPool ltp; 41 | ltp.Start(1); 42 | TS ts; 43 | ts.cc = "call 1"; 44 | ltp.DispatchRpcCall(RpcCallTest, &ts); 45 | sleep(3); 46 | 47 | LIBEV_THREAD* lt_ptr = ltp.GetTestThreadInfo(); 48 | printf("Test tid is %ld", lt_ptr->thread_id); 49 | ltp.RestartThread(lt_ptr->thread_id, lt_ptr->running_version); 50 | 51 | 52 | TS ts2; 53 | ts2.cc = "call ****2"; 54 | ltp.DispatchRpcCall(RpcCallTest, &ts2); 55 | 56 | TS ts3; 57 | ts3.cc = "call ****3"; 58 | ltp.DispatchRpcCall(RpcCallTest, &ts3); 59 | 60 | TS ts4; 61 | ts4.cc = "call ****4"; 62 | ltp.DispatchRpcCall(RpcCallTest, &ts4); 63 | 64 | return 0; 65 | } 66 | 67 | 68 | 69 | 70 | 71 | /* vim: set expandtab ts=4 sw=4 sts=4 tw=100: */ 72 | -------------------------------------------------------------------------------- /src/rpc_server/server_rpc_controller.h: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * 3 | * Copyright (c) 2016 aishuyu, Inc. All Rights Reserved 4 | * 5 | **************************************************************************/ 6 | 7 | 8 | 9 | /** 10 | * @file server_rpc_controller.h 11 | * @author aishuyu(asy5178@163.com) 12 | * @date 2016/04/04 00:11:53 13 | * @brief 14 | * 15 | **/ 16 | 17 | 18 | 19 | 20 | #ifndef __SERVER_RPC_CONTROLLER_H 21 | #define __SERVER_RPC_CONTROLLER_H 22 | 23 | 24 | #include 25 | 26 | namespace libevrpc { 27 | 28 | class ServerRpcController : public google::protobuf::RpcController { 29 | public: 30 | ServerRpcController(); 31 | ~ServerRpcController(); 32 | 33 | /* 34 | * 35 | */ 36 | virtual void Reset(); 37 | /* 38 | * 39 | */ 40 | virtual bool Failed() const; 41 | /* 42 | * 43 | */ 44 | virtual std::string ErrorText() const; 45 | /* 46 | * 47 | */ 48 | virtual void StartCancel(); 49 | /* 50 | * 51 | */ 52 | virtual void SetFailed(const std::string& reason); 53 | /* 54 | * 55 | */ 56 | virtual bool IsCanceled() const; 57 | /* 58 | * 59 | */ 60 | virtual void NotifyOnCancel(google::protobuf::Closure* callback); 61 | 62 | private: 63 | std::string error_info_; 64 | 65 | }; 66 | 67 | } // end of namespace libevrpc 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | #endif // __SERVER_RPC_CONTROLLER_H 76 | 77 | 78 | 79 | /* vim: set expandtab ts=4 sw=4 sts=4 tw=100: */ 80 | -------------------------------------------------------------------------------- /src/rpc_center/leader_thread.h: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * 3 | * Copyright (c) 2016 aishuyu, Inc. All Rights Reserved 4 | * 5 | **************************************************************************/ 6 | 7 | 8 | 9 | /** 10 | * @file leader_thread.h 11 | * @author aishuyu(asy5178@163.com) 12 | * @date 2016/08/25 20:45:56 13 | * @brief 14 | * 15 | **/ 16 | 17 | 18 | 19 | 20 | #ifndef __LEADER_THREAD_H 21 | #define __LEADER_THREAD_H 22 | 23 | 24 | #include "center_proto/centers.pb.h" 25 | #include "util/thread.h" 26 | #include "util/pthread_mutex.h" 27 | 28 | namespace libevrpc { 29 | 30 | typedef struct FollowerItem FW_ITEM; 31 | struct FollowerItem { 32 | int32_t conn_fd; 33 | CentersProto centers_proto; 34 | FW_ITEM* prev; 35 | FW_ITEM* next; 36 | }; 37 | 38 | typedef struct FollowerQueue FQ; 39 | struct FollowerQueue { 40 | FW_ITEM* head; 41 | FW_ITEM* tail; 42 | }; 43 | 44 | /* 45 | * Center进入Leading状态下启动 leader 线程异步处理 Follower发送来的请求 46 | */ 47 | class LeaderThread : public Thread { 48 | public: 49 | LeaderThread(); 50 | ~LeaderThread(); 51 | 52 | virtual void Run(); 53 | void StopThread(); 54 | 55 | bool PushFollowerMessage(int32_t fd, const CentersProto& centers_proto); 56 | FollowerItem* PopFollowerMessage(); 57 | 58 | private: 59 | void Destory(); 60 | 61 | private: 62 | volatile std::atomic running_; 63 | FQ* follower_q_; 64 | 65 | Mutex fq_mutex_; 66 | }; 67 | 68 | 69 | } // end of namespace libevrpc 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | #endif // __LEADER_THREAD_H 78 | 79 | 80 | 81 | /* vim: set expandtab ts=4 sw=4 sts=4 tw=100: */ 82 | -------------------------------------------------------------------------------- /sample/src/libev_server.cc: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * 3 | * Copyright (c) 2014 Aishuyu. All Rights Reserved 4 | * 5 | **************************************************************************/ 6 | 7 | 8 | 9 | /** 10 | * @file rpc_server.cc 11 | * @author aishuyu(asy5178@163.com) 12 | * @date 2014/12/02 17:01:36 13 | * @brief 14 | * 15 | **/ 16 | 17 | 18 | 19 | #include "proto/rpc_sample.pb.h" 20 | #include "rpc_server/rpc_server.h" 21 | 22 | using namespace libevrpc; 23 | using namespace echo; 24 | 25 | class EchoServiceImpl : public EchoService { 26 | public: 27 | EchoServiceImpl() { 28 | } 29 | 30 | ~EchoServiceImpl() { 31 | } 32 | 33 | virtual void Echo(RpcController* controller, 34 | const EchoRequest* request, 35 | EchoResponse* response, 36 | Closure* done) { 37 | printf("service recv msg is %s\n", request->request().c_str()); 38 | string send_str = "sevice echo is : " + request->request(); 39 | response->set_response(send_str); 40 | printf("current tid is %u\n", pthread_self()); 41 | if (done) { 42 | done->Run(); 43 | } 44 | } 45 | }; 46 | 47 | 48 | int main() { 49 | 50 | RpcServer& rpc_server = RpcServer::GetInstance(); 51 | EchoServiceImpl service; 52 | rpc_server.RegisteService(&service); 53 | printf("Start the rpc sevice....\n"); 54 | rpc_server.Start(); 55 | 56 | printf("Start wait.........\n"); 57 | rpc_server.Wait(); 58 | 59 | return 0; 60 | } 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | /* vim: set expandtab ts=4 sw=4 sts=4 tw=100: */ 69 | -------------------------------------------------------------------------------- /src/rpc_center/election_thread.h: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * 3 | * Copyright (c) 2016 aishuyu, Inc. All Rights Reserved 4 | * 5 | **************************************************************************/ 6 | 7 | 8 | 9 | /** 10 | * @file election_thread.h 11 | * @author aishuyu(asy5178@163.com) 12 | * @date 2016/07/22 15:47:05 13 | * @brief 14 | * 15 | **/ 16 | 17 | 18 | 19 | 20 | #ifndef __ELECTION_THREAD_H 21 | #define __ELECTION_THREAD_H 22 | 23 | #include 24 | #include 25 | 26 | #include "center_proto/centers.pb.h" 27 | #include "util/thread.h" 28 | #include "util/pthread_mutex.h" 29 | 30 | namespace libevrpc { 31 | 32 | typedef struct ElectionItem EL_ITEM; 33 | struct ElectionItem { 34 | int32_t conn_fd; 35 | CentersProto centers_proto; 36 | EL_ITEM* prev; 37 | EL_ITEM* next; 38 | }; 39 | 40 | typedef struct ElectionQueue EQ; 41 | struct ElectionQueue { 42 | EL_ITEM* head; 43 | EL_ITEM* tail; 44 | }; 45 | 46 | /* 47 | * 选举时候,启动该线程;选举结束,结束该线程 48 | */ 49 | class ElectionThread : public Thread { 50 | public: 51 | ElectionThread(); 52 | ~ElectionThread(); 53 | 54 | virtual void Run(); 55 | void StopThread(); 56 | 57 | bool PushElectionMessage(int32_t fd, const CentersProto& centers_proto); 58 | ElectionItem* PopElectionMessage(); 59 | 60 | private: 61 | void Destory(); 62 | 63 | private: 64 | volatile std::atomic running_; 65 | EQ* election_q_; 66 | 67 | Mutex eq_mutex_; 68 | }; 69 | 70 | 71 | } // end of namespace libevrpc 72 | 73 | 74 | 75 | 76 | #endif // __ELECTION_THREAD_H 77 | 78 | 79 | 80 | /* vim: set expandtab ts=4 sw=4 sts=4 tw=100: */ 81 | -------------------------------------------------------------------------------- /src/rpc_center/rpc_center_server.cc: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * 3 | * Copyright (c) 2016 aishuyu, Inc. All Rights Reserved 4 | * 5 | **************************************************************************/ 6 | 7 | 8 | 9 | /** 10 | * @file rpc_center_server.cc 11 | * @author aishuyu(asy5178@163.com) 12 | * @date 2016/08/19 20:46:12 13 | * @brief 14 | * 15 | **/ 16 | 17 | 18 | #include 19 | #include 20 | #include 21 | 22 | #include "rpc_center.h" 23 | 24 | 25 | using namespace libevrpc; 26 | 27 | inline void InitSignal() { 28 | struct sigaction sa; 29 | memset(&sa, 0, sizeof(struct sigaction)); 30 | 31 | sa.sa_handler = SIG_IGN; 32 | sigemptyset(&sa.sa_mask); 33 | if (-1 == sigaction(SIGPIPE, &sa, NULL)) { 34 | exit(1); 35 | } 36 | } 37 | 38 | inline void Daemonize() { 39 | if (0 != fork()) { 40 | exit(0); 41 | } 42 | if (-1 == setsid()) { 43 | fprintf(stderr, "set sid error!\n"); 44 | exit(-1); 45 | } 46 | umask(0); 47 | int fd = open("/dev/null", O_RDWR, 0); 48 | if (-1 != fd) { 49 | dup2(fd, STDIN_FILENO); 50 | dup2(fd, STDOUT_FILENO); 51 | dup2(fd, STDERR_FILENO); 52 | if (fd > STDERR_FILENO) { 53 | close(fd); 54 | } 55 | } 56 | } 57 | 58 | int main(int argc, char* argv[]) { 59 | InitSignal(); 60 | if (true) { 61 | Daemonize(); 62 | } 63 | RpcCenter& rc = RpcCenter::GetInstance("conf/rpc_center.ini"); 64 | rc.StartCenter(); 65 | rc.WaitCenter(); 66 | rc.StopCenter(); 67 | return 0; 68 | } 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | /* vim: set expandtab ts=4 sw=4 sts=4 tw=100: */ 78 | -------------------------------------------------------------------------------- /src/rpc_client/client_rpc_controller.h: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * 3 | * Copyright (c) 2016 aishuyu, Inc. All Rights Reserved 4 | * 5 | **************************************************************************/ 6 | 7 | 8 | 9 | /** 10 | * @file client_rpc_controller.h 11 | * @author aishuyu(asy5178@163.com) 12 | * @date 2016/04/04 00:02:36 13 | * @brief 14 | * 15 | **/ 16 | 17 | 18 | 19 | 20 | #ifndef __CLIENT_RPC_CONTROLLER_H 21 | #define __CLIENT_RPC_CONTROLLER_H 22 | 23 | #include 24 | 25 | #include "util/pthread_rwlock.h" 26 | 27 | namespace libevrpc { 28 | 29 | class ClientRpcController : public google::protobuf::RpcController { 30 | public: 31 | ClientRpcController(); 32 | ~ClientRpcController(); 33 | 34 | /* 35 | * 36 | */ 37 | virtual void Reset(); 38 | /* 39 | * 40 | */ 41 | virtual bool Failed() const; 42 | /* 43 | * 44 | */ 45 | virtual std::string ErrorText() const; 46 | /* 47 | * 48 | */ 49 | virtual void StartCancel(); 50 | /* 51 | * 52 | */ 53 | virtual void SetFailed(const std::string& reason); 54 | /* 55 | * 56 | */ 57 | virtual bool IsCanceled() const; 58 | /* 59 | * 60 | */ 61 | virtual void NotifyOnCancel(google::protobuf::Closure* callback); 62 | 63 | private: 64 | std::string error_info_; 65 | mutable RWLock error_info_rwlock_; 66 | 67 | }; 68 | 69 | } // end of namespace libevrpc 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | #endif // __CLIENT_RPC_CONTROLLER_H 78 | 79 | 80 | 81 | /* vim: set expandtab ts=4 sw=4 sts=4 tw=100: */ 82 | -------------------------------------------------------------------------------- /src/config_parser/config_parser.h: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * 3 | * Copyright (c) 2015 aishuyu, Inc. All Rights Reserved 4 | * 5 | **************************************************************************/ 6 | 7 | 8 | 9 | /** 10 | * @file config_parser.h 11 | * @author aishuyu(asy5178@163.com) 12 | * @date 2016/04/06 19:48:07 13 | * @brief 14 | * 15 | **/ 16 | 17 | 18 | 19 | 20 | #ifndef __CONFIG_PARSER_H 21 | #define __CONFIG_PARSER_H 22 | 23 | #include 24 | 25 | #include "iniparser.h" 26 | #include "util/disallow_copy_and_assign.h" 27 | 28 | namespace libevrpc { 29 | 30 | #define DEFAULT_INT -1 31 | #define DEFAULT_DOUBLE -1.0 32 | #define DEFAULT_CHAR NULL 33 | #define DEFAULT_BOOL false 34 | 35 | class ConfigParser { 36 | public: 37 | ~ConfigParser(); 38 | 39 | static ConfigParser& GetInstance(const std::string& ini_file); 40 | 41 | int32_t GetSecKeysNum(const char* sec_key, int32_t defalut_val); 42 | int32_t IniGetInt(const char* sec_key, int32_t defalut_val); 43 | double IniGetDouble(const char* sec_key, double defalut_val); 44 | const char *IniGetString(const char* sec_key, const char* defalut_val); 45 | bool IniGetBool(const char* sec_key, bool defalut_val); 46 | 47 | void PrintErrorInfo(); 48 | 49 | ConfigParser(const std::string& ini_file); 50 | 51 | bool InitConfigParser(); 52 | 53 | DISALLOW_COPY_AND_ASSIGN(ConfigParser); 54 | 55 | private: 56 | bool is_init_; 57 | std::string ini_file_; 58 | std::string error_info_; 59 | 60 | dictionary* dict_ini_; 61 | }; 62 | 63 | } // end of namespace libevrpc 64 | 65 | 66 | #endif // __CONFIG_PARSER_H 67 | 68 | 69 | 70 | /* vim: set expandtab ts=4 sw=4 sts=4 tw=100: */ 71 | -------------------------------------------------------------------------------- /src/unit_test/test_hb_server.cc: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * 3 | * Copyright (c) 2016 aishuyu, Inc. All Rights Reserved 4 | * 5 | **************************************************************************/ 6 | 7 | 8 | 9 | /** 10 | * @file test_hb_server.cc 11 | * @author aishuyu(asy5178@163.com) 12 | * @date 2016/05/08 21:41:40 13 | * @brief 14 | * 15 | **/ 16 | 17 | #include 18 | 19 | #include "rpc_server/connection_timer_manager.h" 20 | #include "rpc_server/rpc_heartbeat_server.h" 21 | #include "util/rpc_util.h" 22 | #include "util/rpc_communication.h" 23 | 24 | using namespace libevrpc; 25 | 26 | int main() { 27 | ConnectionTimerManager& ctm = ConnectionTimerManager::GetInstance("test_conf/test.ini"); 28 | int32_t buf_index = ctm.InitTimerBuf(); 29 | ctm.Start(); 30 | 31 | printf("Test start connect\n"); 32 | const char* addr = GetLocalAddress(); 33 | printf("Test the addr is : %s\n", addr); 34 | 35 | int32_t listen_fd = TcpListen(addr, "7777", false); 36 | 37 | struct sockaddr_in client_addr; 38 | socklen_t len = sizeof(struct sockaddr_in); 39 | printf("Test the listen_fd is : %d\n", listen_fd); 40 | int32_t cfd = Accept(listen_fd, client_addr, len, false); 41 | if (cfd < 0) { 42 | printf("accpet eror!\n"); 43 | return 0; 44 | } 45 | std::string guest_addr; 46 | GetPeerAddr(cfd, guest_addr); 47 | ctm.InsertConnectionTimer(guest_addr, cfd, buf_index, 1, pthread_self()); 48 | printf("InsertConnectionTimer done!\n"); 49 | 50 | printf("Start done!\n"); 51 | 52 | sleep(200); 53 | std::string recv_msg; 54 | int id = RpcRecv(cfd, recv_msg, true); 55 | printf("Test string is :%s\n", recv_msg.c_str()); 56 | sleep(1000); 57 | 58 | ctm.Stop(); 59 | 60 | return 0; 61 | } 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | /* vim: set expandtab ts=4 sw=4 sts=4 tw=100: */ 73 | -------------------------------------------------------------------------------- /src/rpc_client/center_client_heartbeat.h: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * 3 | * Copyright (c) 2016 aishuyu, Inc. All Rights Reserved 4 | * 5 | **************************************************************************/ 6 | 7 | 8 | 9 | /** 10 | * @file center_client_heartbeat.h 11 | * @author aishuyu(asy5178@163.com) 12 | * @date 2016/09/07 20:52:26 13 | * @brief 14 | * 15 | **/ 16 | 17 | 18 | 19 | 20 | #ifndef __CENTER_CLIENT_HEARTBEAT_H 21 | #define __CENTER_CLIENT_HEARTBEAT_H 22 | 23 | #include 24 | #include 25 | 26 | #include 27 | 28 | #include "util/thread.h" 29 | #include "util/pthread_rwlock.h" 30 | 31 | namespace libevrpc { 32 | 33 | typedef std::vector ADDRS_LIST_TYPE; 34 | 35 | class CenterClientHeartbeat : public Thread { 36 | public: 37 | CenterClientHeartbeat(const std::string& config_file); 38 | 39 | ~CenterClientHeartbeat(); 40 | 41 | virtual void Run(); 42 | 43 | void GetRpcServerList(ADDRS_LIST_TYPE& server_list); 44 | std::string RandomGetRpcServerAddr(); 45 | 46 | private: 47 | bool InitCenterClientHB(); 48 | 49 | void UpdateCenterAddrs(const ::google::protobuf::RepeatedPtrField* center_list); 50 | void UpdateServerAddrs(const ::google::protobuf::RepeatedPtrField* server_list); 51 | 52 | private: 53 | std::string config_file_; 54 | ADDRS_LIST_TYPE* center_addrs_ptr_; 55 | ADDRS_LIST_TYPE* updatecenter_addrs_ptr_; 56 | ADDRS_LIST_TYPE* cluster_server_addrs_list_ptr_; 57 | 58 | bool running_; 59 | char* center_port_; 60 | 61 | RWLock centers_rwlock_; 62 | RWLock servers_rwlock_; 63 | }; 64 | 65 | } // end of namespace libevrpc 66 | 67 | 68 | 69 | 70 | #endif // __CENTER_CLIENT_HEARTBEAT_H 71 | 72 | 73 | 74 | /* vim: set expandtab ts=4 sw=4 sts=4 tw=100: */ 75 | -------------------------------------------------------------------------------- /deps_build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | DEPS_PRFIX=https://github.com/igithu 4 | BUILD_ROOT=$PWD/.. 5 | INSTALL_ROOT_DIR=$BUILD_ROOT/third-64 6 | 7 | function check_directory() { 8 | if [ ! -f $BUILD_ROOT/$1/mark_done ] 9 | then 10 | if [ -d $BUILD_ROOT/$1 ] 11 | then 12 | rm -rf $BUILD_ROOT/$1 13 | fi 14 | mkdir -p $BUILD_ROOT/$1 15 | return 0 16 | fi 17 | return 1 18 | } 19 | 20 | function get_sources_deps() { 21 | if [ ! -f $BUILD_ROOT/$1/mark_done ] 22 | then 23 | if [ -d $BUILD_ROOT/$1 ] 24 | then 25 | rm -rf $BUILD_ROOT/$1 26 | fi 27 | git clone $DEPS_PRFIX/$1.git 28 | if [ $? -eq 0 ] 29 | then 30 | touch $1/mark_done 31 | fi 32 | fi 33 | 34 | if [ ! -f $BUILD_ROOT/$1/mark_done ] 35 | then 36 | echo "Get $1 file failed!" 37 | exit -1 38 | else 39 | echo "Get $1 files done" 40 | fi 41 | } 42 | 43 | # $1:must be with version number 44 | function install_deps() { 45 | if [ -f $INSTALL_ROOT_DIR/$2/mark_done ] 46 | then 47 | echo "$1 hash been installed in $INSTALL_ROOT_DIR/$2" 48 | return 0 49 | fi 50 | 51 | if [ -d $BUILD_ROOT/deps/$1 ] 52 | then 53 | rm -rf $BUILD_ROOT/deps/$1 54 | fi 55 | 56 | cd $BUILD_ROOT/deps && tar -zxvf $1.tar.gz 57 | if [ $? -ne 0 ] 58 | then 59 | echo "Get $1 dir failed!" 60 | exit -1 61 | fi 62 | cd $1 63 | mkdir -p $INSTALL_ROOT_DIR/$2 64 | echo "the install dir is $INSTALL_ROOT_DIR/$2" 65 | ./configure --prefix=$INSTALL_ROOT_DIR/$2 && make && make install 66 | if [ $? -ne 0 ] 67 | then 68 | echo "Build the $1 failed!" 69 | exit -1 70 | fi 71 | touch $INSTALL_ROOT_DIR/$2/mark_done 72 | touch $BUILD_ROOT/third-64/mark_done 73 | } 74 | 75 | 76 | cd $BUILD_ROOT 77 | get_sources_deps deps 78 | 79 | check_directory third-64 80 | 81 | install_deps libev-4.19 libev && install_deps protobuf-2.6.0 protobuf 82 | 83 | 84 | -------------------------------------------------------------------------------- /src/rpc_center/center_server_thread.h: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * 3 | * Copyright (c) 2016 aishuyu, Inc. All Rights Reserved 4 | * 5 | **************************************************************************/ 6 | 7 | 8 | 9 | /** 10 | * @file center_server_thread.h 11 | * @author aishuyu(asy5178@163.com) 12 | * @date 2016/07/17 02:29:13 13 | * @brief 14 | * 15 | **/ 16 | 17 | 18 | 19 | 20 | #ifndef __CENTER_SERVER_THREAD_H 21 | #define __CENTER_SERVER_THREAD_H 22 | 23 | #include 24 | 25 | #include "util/thread.h" 26 | 27 | namespace libevrpc { 28 | 29 | typedef struct CenterEIOItem CEIO_ITEM; 30 | struct CenterEIOItem { 31 | ev_io eio; 32 | CEIO_ITEM* prev; 33 | CEIO_ITEM* next; 34 | }; 35 | 36 | struct CenterEioQueue { 37 | CEIO_ITEM* head; 38 | CEIO_ITEM* tail; 39 | }; 40 | 41 | class CenterServerThread : public Thread { 42 | public: 43 | CenterServerThread(const char* local_center, const char* server_port); 44 | ~CenterServerThread(); 45 | 46 | bool InitCenterServer(); 47 | 48 | virtual void Run(); 49 | 50 | private: 51 | static void AcceptCb(struct ev_loop *loop, struct ev_io *watcher, int revents); 52 | static void Processor(struct ev_loop *loop, struct ev_io *watcher, int revents); 53 | 54 | CEIO_ITEM* NewCEIO(); 55 | void FreeCEIO(CEIO_ITEM* eio_item); 56 | static void PushCEIO(CenterEioQueue& eq, CEIO_ITEM* eio_item); 57 | static CEIO_ITEM* PopCEIO(CenterEioQueue& eq); 58 | 59 | private: 60 | char* local_center_; 61 | char* center_port_; 62 | 63 | struct ev_loop *epoller_; 64 | struct ev_io socket_watcher_; 65 | 66 | CEIO_ITEM* eio_freelist_; 67 | static int32_t ei_per_alloc_; 68 | static CenterEioQueue eio_uselist_; 69 | 70 | }; 71 | 72 | } // end of namespace libevrpc 73 | 74 | 75 | 76 | 77 | #endif // __CENTER_SERVER_THREAD_H 78 | 79 | 80 | 81 | /* vim: set expandtab ts=4 sw=4 sts=4 tw=100: */ 82 | -------------------------------------------------------------------------------- /src/rpc_center/load_balancer/consistent_hash_load_balancer.h: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * 3 | * Copyright (c) 2016 aishuyu, Inc. All Rights Reserved 4 | * 5 | **************************************************************************/ 6 | 7 | 8 | 9 | /** 10 | * @file consistent_hash_load_balancer.h 11 | * @author aishuyu(asy5178@163.com) 12 | * @date 2016/09/08 20:11:27 13 | * @brief 14 | * 15 | **/ 16 | 17 | 18 | 19 | 20 | #ifndef __CONSISTENT_HASH_LOAD_BALANCER_H 21 | #define __CONSISTENT_HASH_LOAD_BALANCER_H 22 | 23 | #include "load_balancer.h" 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | #include "util/pthread_rwlock.h" 31 | 32 | namespace libevrpc { 33 | 34 | /* 35 | * 虚拟节点, 对应多个实际RpcServer 36 | */ 37 | struct VirtualNode { 38 | uint32_t vid; 39 | std::vector py_node_list; 40 | }; 41 | 42 | typedef std::shared_ptr VN_PTR; 43 | typedef std::map VN_HASH_MAP; 44 | 45 | class ConsistentHashLoadBalancer : public LoadBalancer { 46 | public: 47 | ConsistentHashLoadBalancer(const std::string& config_file); 48 | virtual ~ConsistentHashLoadBalancer(); 49 | 50 | bool InitBalancer(); 51 | void SetConfigFile(const std::string& file_name); 52 | bool AddRpcServer(const RpcClusterServer& rpc_cluster_server); 53 | bool GetRpcServer( 54 | const std::string& rpc_client, 55 | std::vector& rpc_server_list); 56 | bool GetCurrentLBResult( 57 | ::google::protobuf::RepeatedPtrField& lb_result_list); 58 | bool UpdateLBResult( 59 | const ::google::protobuf::RepeatedPtrField& lb_result_list); 60 | 61 | private: 62 | std::string config_file_; 63 | int32_t virtual_node_num_; 64 | 65 | VN_HASH_MAP* vn_map_ptr_; 66 | 67 | RWLock vmap_rwlock_; 68 | }; 69 | 70 | } // end of namespace 71 | 72 | 73 | 74 | 75 | 76 | #endif // __CONSISTENT_HASH_LOAD_BALANCER_H 77 | 78 | 79 | 80 | /* vim: set expandtab ts=4 sw=4 sts=4 tw=100: */ 81 | -------------------------------------------------------------------------------- /src/util/rpc_util.cpp: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * 3 | * Copyright (c) 2014 Aishuyu. All Rights Reserved 4 | * 5 | **************************************************************************/ 6 | 7 | 8 | 9 | /** 10 | * @file rpc_util.cpp 11 | * @author aishuyu(asy5178@163.com) 12 | * @date 2014/11/30 17:49:07 13 | * @brief 14 | * 15 | **/ 16 | 17 | #include "rpc_util.h" 18 | 19 | #include 20 | #include 21 | #include 22 | 23 | #include 24 | #include 25 | #include 26 | 27 | namespace libevrpc { 28 | 29 | uint32_t BKDRHash(const char *orig_str) { 30 | uint32_t seed = 1313; 31 | uint32_t hash_code = 0; 32 | 33 | while (*orig_str) { 34 | hash_code = hash_code * seed + (*orig_str++); 35 | } 36 | 37 | return (hash_code & 0x7FFFFFFF); 38 | } 39 | 40 | void PrintErrorInfo(const char* error_info) { 41 | time_t nowtime = time(NULL); 42 | struct tm *local = localtime(&nowtime); 43 | 44 | char time[30]; 45 | strftime(time, 30, "%Y-%m-%d %H:%M:%S", local); 46 | fprintf(stderr, "%s [] %s\n", time, error_info); 47 | } 48 | 49 | const char* GetLocalAddress() { 50 | char hname[128]; 51 | gethostname(hname, sizeof(hname)); 52 | struct hostent *hptr = gethostbyname(hname); 53 | const char* addr = inet_ntoa(*(struct in_addr*)(hptr->h_addr_list[0])); 54 | return addr; 55 | } 56 | 57 | 58 | uint32_t MurMurHash2(const char* key_str, int32_t len) { 59 | const unsigned int m = 0x5bd1e995; 60 | const int r = 24; 61 | const int seed = 97; 62 | unsigned int h = seed ^ len; 63 | 64 | // Mix 4 bytes at a time into the hash 65 | const unsigned char *data = (const unsigned char *)key_str; 66 | while (len >= 4) { 67 | unsigned int k = *(unsigned int *)data; 68 | k *= m; 69 | k ^= k >> r; 70 | k *= m; 71 | h *= m; 72 | h ^= k; 73 | data += 4; 74 | len -= 4; 75 | } 76 | 77 | switch (len) { 78 | case 3: h ^= data[2] << 16; 79 | case 2: h ^= data[1] << 8; 80 | case 1: h ^= data[0]; 81 | h *= m; 82 | } 83 | // Do a few final mixes of the hash to ensure the last few 84 | // bytes are well-incorporated. 85 | h ^= h >> 13; 86 | h *= m; 87 | h ^= h >> 15; 88 | return h; 89 | } 90 | 91 | } // end of namespace libevrpc 92 | 93 | 94 | 95 | 96 | 97 | /* vim: set expandtab ts=4 sw=4 sts=4 tw=100: */ 98 | -------------------------------------------------------------------------------- /src/util/rpc_communication.h: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * 3 | * Copyright (c) 2015 aishuyu, Inc. All Rights Reserved 4 | * 5 | **************************************************************************/ 6 | 7 | 8 | 9 | /** 10 | * @file rpc_commonication.h 11 | * @author aishuyu(asy5178@163.com) 12 | * @date 2015/09/03 18:22:08 13 | * @brief 14 | * 15 | **/ 16 | 17 | 18 | 19 | 20 | #ifndef __RPC_COMMONICATION_H 21 | #define __RPC_COMMONICATION_H 22 | 23 | 24 | #include 25 | #include 26 | 27 | #include 28 | 29 | namespace libevrpc { 30 | 31 | // #define SER_INTERNAL_ERROR 500 32 | // #define SER_RETURN_SUCC 200 33 | #define ERROR_META -300 34 | #define ERROR_SEND -500 35 | #define ERROR_RECV -200 36 | #define TCP_CONN_TIMEOUT -999 37 | 38 | #define MAX_INFO_LEN 512 39 | #define BODY_SIZE 512 40 | 41 | typedef struct MetaDataStruct { 42 | int32_t h_code; 43 | char body[BODY_SIZE]; 44 | } MetaData; 45 | 46 | const static int32_t MetaSize = sizeof(MetaData); 47 | 48 | 49 | /* 50 | * wrapper socket, imitate the code 51 | * for TcpListen Accept api have the flag mark non_block, the non_block is true for test, 52 | * default false for the rpc 53 | */ 54 | int32_t Socket(int32_t family = 0, int32_t type = 0, int32_t protocol = 0); 55 | 56 | int32_t TcpListen(const char *host, const char *port, bool non_block = true, int32_t family = AF_UNSPEC); 57 | 58 | int32_t TcpConnect(const char *host, const char *port, const int32_t conn_overtime, int32_t family = AF_UNSPEC); 59 | 60 | int32_t UdpServerInit(const char *host, const char *port); 61 | 62 | int32_t UdpClientInit(const char *server_host, const char *port, struct sockaddr_in &servaddr); 63 | 64 | int32_t Accept(int fd, struct sockaddr_in& sa, int32_t addrlen, bool non_block = true); 65 | 66 | int32_t RpcRecv(int32_t fd, std::string& recv_info_str, bool need_closed = false); 67 | 68 | int32_t RpcSend(int32_t fd, int32_t transfer_id, std::string& send_info_str, bool need_closed = false); 69 | 70 | int32_t RpcRecvFrom(int32_t fd, std::string& recv_info_str, bool need_closed = false); 71 | 72 | int32_t RpcSendTo(int32_t fd, struct sockaddr_in &to, std::string& send_info_str, bool need_closed); 73 | 74 | int32_t GetPeerAddr(int32_t fd, std::string& guest_addr); 75 | 76 | bool SetNonBlock(int32_t sock); 77 | 78 | 79 | } // end of namespace libevrpc 80 | 81 | 82 | 83 | #endif // __RPC_COMMONICATION_H 84 | 85 | 86 | 87 | /* vim: set expandtab ts=4 sw=4 sts=4 tw=100: */ 88 | -------------------------------------------------------------------------------- /src/rpc_server/dispatch_thread.h: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * 3 | * Copyright (c) 2015 aishuyu, Inc. All Rights Reserved 4 | * 5 | **************************************************************************/ 6 | 7 | 8 | 9 | /** 10 | * @file dispatch_thread.h 11 | * @author aishuyu(asy5178@163.com) 12 | * @date 2015/12/31 00:04:24 13 | * @brief 14 | * 15 | **/ 16 | 17 | 18 | 19 | 20 | #ifndef __DISPATCH_THREAD_H 21 | #define __DISPATCH_THREAD_H 22 | 23 | #include 24 | #include 25 | 26 | #include "util/thread.h" 27 | 28 | namespace libevrpc { 29 | 30 | 31 | /* 32 | * callback in dispatch_thread 33 | */ 34 | typedef struct { 35 | void *(*callback)(void * arg); 36 | void *params; 37 | } DCallBack; 38 | 39 | /* 40 | * ev_io item to link all ev_io 41 | */ 42 | typedef struct EIOItem EIO_ITEM; 43 | struct EIOItem { 44 | ev_io eio; 45 | EIO_ITEM* prev; 46 | EIO_ITEM* next; 47 | }; 48 | 49 | struct EioQueue { 50 | EIO_ITEM* head; 51 | EIO_ITEM* tail; 52 | }; 53 | 54 | typedef void (*RpcCallBackPtr)(int32_t, void *arg); 55 | class DispatchThread : public Thread { 56 | public: 57 | DispatchThread(); 58 | 59 | ~DispatchThread(); 60 | 61 | bool InitializeService( 62 | const char *host, 63 | const char *port, 64 | RpcCallBackPtr cb, 65 | void *arg); 66 | 67 | virtual void Run(); 68 | 69 | private: 70 | /* 71 | * libev callback 72 | */ 73 | static void AcceptCb(struct ev_loop *loop, struct ev_io *watcher, int revents); 74 | static void ProcessCb(struct ev_loop *loop, struct ev_io *watcher, int revents); 75 | 76 | /* 77 | * eio new and free 78 | */ 79 | EIO_ITEM* NewEIO(); 80 | void FreeEIO(EIO_ITEM* eio_item); 81 | static void PushEIO(EioQueue& eq, EIO_ITEM* eio_item); 82 | static EIO_ITEM* PopEIO(EioQueue& eq); 83 | 84 | private: 85 | struct ev_loop *epoller_; 86 | struct ev_io socket_watcher_; 87 | EIO_ITEM* eio_freelist_; 88 | 89 | RpcCallBackPtr cb_ptr_; 90 | void* cb_arg_; 91 | 92 | static int32_t ei_per_alloc_; 93 | static EioQueue eio_uselist_; 94 | }; 95 | 96 | } // end of namespace libevrpc 97 | 98 | 99 | #endif // __DISPATCH_THREAD_H 100 | 101 | 102 | 103 | /* vim: set expandtab ts=4 sw=4 sts=4 tw=100: */ 104 | -------------------------------------------------------------------------------- /src/config_parser/config_parser.cpp: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * 3 | * Copyright (c) 2015 aishuyu, Inc. All Rights Reserved 4 | * 5 | **************************************************************************/ 6 | 7 | 8 | 9 | /** 10 | * @file config_parser.cpp 11 | * @author aishuyu(asy5178@163.com) 12 | * @date 2016/04/06 20:12:14 13 | * @brief 14 | * 15 | **/ 16 | 17 | #include "config_parser.h" 18 | 19 | namespace libevrpc { 20 | 21 | using std::string; 22 | 23 | ConfigParser::ConfigParser(const std::string& ini_file) : 24 | is_init_(false), 25 | ini_file_(ini_file), 26 | dict_ini_(NULL) { 27 | InitConfigParser(); 28 | } 29 | 30 | ConfigParser::~ConfigParser() { 31 | if (NULL != dict_ini_) { 32 | iniparser_freedict(dict_ini_); 33 | } 34 | } 35 | 36 | // ConfigParser& ConfigParser::GetInstance() { 37 | // static ConfigParser cp_instance; 38 | // return cp_instance; 39 | // } 40 | 41 | ConfigParser& ConfigParser::GetInstance(const std::string& ini_file) { 42 | static ConfigParser cp_instance(ini_file); 43 | return cp_instance; 44 | } 45 | 46 | bool ConfigParser::InitConfigParser() { 47 | dict_ini_ = iniparser_load(ini_file_.c_str()); 48 | return true; 49 | } 50 | 51 | int32_t ConfigParser::GetSecKeysNum(const char* sec_key, int32_t defalut_val) { 52 | if (NULL == dict_ini_) { 53 | return defalut_val; 54 | } 55 | return iniparser_getsecnkeys(dict_ini_, const_cast(sec_key)); 56 | } 57 | 58 | int32_t ConfigParser::IniGetInt(const char* sec_key, int32_t defalut_val) { 59 | if (NULL == dict_ini_) { 60 | return defalut_val; 61 | } 62 | return iniparser_getint(dict_ini_, sec_key, defalut_val); 63 | } 64 | 65 | double ConfigParser::IniGetDouble(const char* sec_key, double defalut_val) { 66 | if (NULL == dict_ini_) { 67 | return defalut_val; 68 | } 69 | return iniparser_getdouble(dict_ini_, sec_key, defalut_val); 70 | } 71 | 72 | const char* ConfigParser::IniGetString(const char* sec_key, const char* defalut_val) { 73 | if (NULL == dict_ini_) { 74 | defalut_val; 75 | } 76 | return iniparser_getstring(dict_ini_, sec_key, const_cast(defalut_val)); 77 | } 78 | 79 | bool ConfigParser::IniGetBool(const char* sec_key, bool defalut_val) { 80 | if (NULL == dict_ini_) { 81 | defalut_val; 82 | } 83 | return iniparser_getboolean(dict_ini_, sec_key, defalut_val);; 84 | } 85 | 86 | 87 | } // end of namespace libevrpc 88 | 89 | 90 | 91 | 92 | 93 | /* vim: set expandtab ts=4 sw=4 sts=4 tw=100: */ 94 | -------------------------------------------------------------------------------- /sample/src/libev_client.cc: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * 3 | * Copyright (c) 2014 Aishuyu. All Rights Reserved 4 | * 5 | **************************************************************************/ 6 | 7 | 8 | 9 | /** 10 | * @file rpc_client.cpp 11 | * @author aishuyu(asy5178@163.com) 12 | * @date 2014/12/02 14:41:35 13 | * @brief 14 | * 15 | **/ 16 | 17 | #include 18 | 19 | #include "proto/rpc_sample.pb.h" 20 | #include "rpc_client/rpc_client.h" 21 | 22 | using namespace libevrpc; 23 | using namespace google::protobuf; 24 | using namespace echo; 25 | 26 | class RpcClientImp : public RpcClient { 27 | public: 28 | RpcClientImp(); 29 | 30 | ~RpcClientImp(); 31 | 32 | EchoService_Stub& RpcCall(); 33 | 34 | private: 35 | EchoService_Stub* service_call_ptr_; 36 | }; 37 | 38 | RpcClientImp::RpcClientImp() { 39 | // InitClient("127.0.0.1", "9999"); 40 | service_call_ptr_ = new EchoService_Stub(GetRpcChannel()); 41 | } 42 | 43 | RpcClientImp::~RpcClientImp() { 44 | } 45 | 46 | EchoService_Stub& RpcClientImp::RpcCall() { 47 | return (*service_call_ptr_); 48 | } 49 | 50 | void SysncCall() { 51 | 52 | EchoRequest echo_request; 53 | echo_request.set_request("Hello! test123456789012345678901234567890"); 54 | 55 | EchoResponse echo_response; 56 | RpcClientImp rpc_client; 57 | rpc_client.RpcCall().Echo(NULL, &echo_request, &echo_response, NULL);; 58 | if (!rpc_client.IsCallOk()) { 59 | printf("error call in rpc client! error info is %d\n", rpc_client.GetErrorInfo().c_str()); 60 | } 61 | echo_response.PrintDebugString(); 62 | string ret = echo_response.response(); 63 | printf("echo recv msg is %s\n", ret.c_str()); 64 | 65 | } 66 | 67 | void AsyscCall() { 68 | EchoRequest echo_request; 69 | echo_request.set_request("Hello! test123456789012345678901234567890"); 70 | 71 | RpcClientImp rpc_client; 72 | rpc_client.OpenRpcAsyncMode(); 73 | EchoResponse echo_response; 74 | rpc_client.RpcCall().Echo(rpc_client.Status(), &echo_request, &echo_response, NULL); 75 | 76 | sleep(5); 77 | rpc_client.RpcClient::GetAsyncResponse("Echo", &echo_response); 78 | if (!rpc_client.IsCallOk()) { 79 | printf("error call in rpc client! error info is %d\n", rpc_client.GetErrorInfo().c_str()); 80 | } 81 | echo_response.PrintDebugString(); 82 | string ret = echo_response.response(); 83 | printf("Async call echo recv msg is %s\n", ret.c_str()); 84 | 85 | } 86 | 87 | int main() { 88 | SysncCall(); 89 | // AsyscCall(); 90 | return 0; 91 | } 92 | 93 | 94 | 95 | 96 | 97 | 98 | /* vim: set expandtab ts=4 sw=4 sts=4 tw=100: */ 99 | -------------------------------------------------------------------------------- /src/rpc_client/rpc_client.h: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * 3 | * Copyright (c) 2015 aishuyu, Inc. All Rights Reserved 4 | * 5 | **************************************************************************/ 6 | 7 | 8 | 9 | /** 10 | * @file rpc_client.h 11 | * @author aishuyu(asy5178@163.com) 12 | * @date 2015/09/10 17:43:49 13 | * @brief 14 | * 15 | **/ 16 | 17 | 18 | 19 | 20 | #ifndef __RPC_CLIENT_H 21 | #define __RPC_CLIENT_H 22 | 23 | #include "rpc_channel.h" 24 | 25 | #include 26 | 27 | #include "rpc_heartbeat_client.h" 28 | #include "center_client_heartbeat.h" 29 | #include "config_parser/config_parser.h" 30 | 31 | namespace libevrpc { 32 | 33 | class RpcClient { 34 | public: 35 | RpcClient(const std::string& config_file = "./rpc_client.ini"); 36 | virtual ~RpcClient(); 37 | 38 | /* 39 | * open the async rpc call 40 | */ 41 | bool OpenRpcAsyncMode(); 42 | /* 43 | * in async call, get the result from local memory 44 | * if the async call is not finnished, will be blocked!! 45 | */ 46 | bool GetAsyncResponse(const std::string& method_name, google::protobuf::Message* response); 47 | /* 48 | * set the rpc connection timeout and if connection failed, tye times 49 | */ 50 | bool SetRpcConnectionInfo(int32_t rpc_timeout, int32_t try_time = 1); 51 | /* 52 | * get the rpc client 53 | */ 54 | google::protobuf::RpcController* Status(); 55 | 56 | /* 57 | * is the rpc call ok? 58 | */ 59 | bool IsCallOk(); 60 | /* 61 | * if the rpc failed, YOU may get error info 62 | */ 63 | std::string GetErrorInfo() const; 64 | 65 | protected: 66 | bool InitClient(const std::string& config_file); 67 | 68 | Channel* GetRpcChannel(); 69 | 70 | private: 71 | /* 72 | * rpc channel: communication with server 73 | */ 74 | Channel* rpc_channel_ptr_; 75 | /* 76 | *controll the rpc client action 77 | */ 78 | google::protobuf::RpcController* rpc_controller_ptr_; 79 | /* 80 | * heartbeat in client 81 | */ 82 | RpcHeartbeatClient* rpc_heartbeat_ptr_; 83 | /* 84 | * update info from center 85 | */ 86 | CenterClientHeartbeat* center_client_heartbeat_ptr_; 87 | /* 88 | * when init, read config from config file 89 | */ 90 | ConfigParser& config_parser_instance_; 91 | 92 | }; 93 | 94 | } // end of namespace libevrpc 95 | 96 | 97 | 98 | #endif // __RPC_CLIENT_H 99 | 100 | 101 | 102 | /* vim: set expandtab ts=4 sw=4 sts=4 tw=100: */ 103 | -------------------------------------------------------------------------------- /src/util/thread.h: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * 3 | * Copyright (c) 2014 aishuyu.com, Inc. All Rights Reserved 4 | * 5 | **************************************************************************/ 6 | 7 | 8 | 9 | /** 10 | * @file thread.h 11 | * @author aishuyu(asy5178@163.com) 12 | * @date 2014/10/30 21:39:40 13 | * @brief 14 | * 15 | **/ 16 | 17 | 18 | 19 | 20 | #ifndef __THREAD_H_ 21 | #define __THREAD_H_ 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #include 29 | 30 | namespace libevrpc { 31 | 32 | class Thread { 33 | public: 34 | Thread() : thread_running_(false) { 35 | } 36 | 37 | virtual ~Thread() { 38 | Stop(); 39 | Wait(); 40 | } 41 | 42 | bool Start() { 43 | if (true == thread_running_) { 44 | return true; 45 | } 46 | if (pthread_create(&tid_, NULL, hook, this) != 0) { 47 | return false; 48 | } 49 | thread_running_ = true; 50 | return true; 51 | } 52 | 53 | // return false: cancel the thread failed. 54 | bool Stop(bool immediately = true) { 55 | if (!IsAlive() || !thread_running_) { 56 | return true; 57 | } 58 | if (immediately) { 59 | pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); 60 | } 61 | if (pthread_cancel(tid_) != 0) { 62 | return false; 63 | } 64 | thread_running_ = false; 65 | return true; 66 | } 67 | 68 | bool Wait() { 69 | if (!IsAlive() || !thread_running_) { 70 | return true; 71 | } 72 | if (pthread_join(tid_, NULL) != 0) { 73 | return false; 74 | } 75 | return true; 76 | } 77 | 78 | bool IsAlive() { 79 | int sig = pthread_kill(tid_, 0); 80 | if (ESRCH == sig) { 81 | return false; 82 | } 83 | // EINVAL: The value specified for the argument is not correct. 84 | // the argument is 0, should not be return the EINVAL 85 | return true; 86 | } 87 | 88 | private: 89 | static void* hook(void* args) { 90 | reinterpret_cast(args)->Run(); 91 | return NULL; 92 | } 93 | private: 94 | volatile std::atomic thread_running_; 95 | pthread_t tid_; 96 | 97 | protected: 98 | virtual void Run() = 0; 99 | }; 100 | 101 | } // end of namespace 102 | 103 | 104 | 105 | 106 | #endif //__THREAD_H_ 107 | 108 | /* vim: set expandtab ts=4 sw=4 sts=4 tw=100: */ 109 | -------------------------------------------------------------------------------- /src/center_proto/center_type.pb.h: -------------------------------------------------------------------------------- 1 | // Generated by the protocol buffer compiler. DO NOT EDIT! 2 | // source: center_type.proto 3 | 4 | #ifndef PROTOBUF_center_5ftype_2eproto__INCLUDED 5 | #define PROTOBUF_center_5ftype_2eproto__INCLUDED 6 | 7 | #include 8 | 9 | #include 10 | 11 | #if GOOGLE_PROTOBUF_VERSION < 2006000 12 | #error This file was generated by a newer version of protoc which is 13 | #error incompatible with your Protocol Buffer headers. Please update 14 | #error your headers. 15 | #endif 16 | #if 2006000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION 17 | #error This file was generated by an older version of protoc which is 18 | #error incompatible with your Protocol Buffer headers. Please 19 | #error regenerate this file with a newer version of protoc. 20 | #endif 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | // @@protoc_insertion_point(includes) 27 | 28 | namespace libevrpc { 29 | 30 | // Internal implementation detail -- do not call these. 31 | void protobuf_AddDesc_center_5ftype_2eproto(); 32 | void protobuf_AssignDesc_center_5ftype_2eproto(); 33 | void protobuf_ShutdownFile_center_5ftype_2eproto(); 34 | 35 | 36 | enum CenterType { 37 | CENTER2CENTER = 100, 38 | CENTER2CLIENT = 101, 39 | CENTER2CLUSTER = 102 40 | }; 41 | bool CenterType_IsValid(int value); 42 | const CenterType CenterType_MIN = CENTER2CENTER; 43 | const CenterType CenterType_MAX = CENTER2CLUSTER; 44 | const int CenterType_ARRAYSIZE = CenterType_MAX + 1; 45 | 46 | const ::google::protobuf::EnumDescriptor* CenterType_descriptor(); 47 | inline const ::std::string& CenterType_Name(CenterType value) { 48 | return ::google::protobuf::internal::NameOfEnum( 49 | CenterType_descriptor(), value); 50 | } 51 | inline bool CenterType_Parse( 52 | const ::std::string& name, CenterType* value) { 53 | return ::google::protobuf::internal::ParseNamedEnum( 54 | CenterType_descriptor(), name, value); 55 | } 56 | // =================================================================== 57 | 58 | 59 | // =================================================================== 60 | 61 | 62 | // =================================================================== 63 | 64 | 65 | // @@protoc_insertion_point(namespace_scope) 66 | 67 | } // namespace libevrpc 68 | 69 | #ifndef SWIG 70 | namespace google { 71 | namespace protobuf { 72 | 73 | template <> struct is_proto_enum< ::libevrpc::CenterType> : ::google::protobuf::internal::true_type {}; 74 | template <> 75 | inline const EnumDescriptor* GetEnumDescriptor< ::libevrpc::CenterType>() { 76 | return ::libevrpc::CenterType_descriptor(); 77 | } 78 | 79 | } // namespace google 80 | } // namespace protobuf 81 | #endif // SWIG 82 | 83 | // @@protoc_insertion_point(global_scope) 84 | 85 | #endif // PROTOBUF_center_5ftype_2eproto__INCLUDED 86 | -------------------------------------------------------------------------------- /src/rpc_center/leader_thread.cpp: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * 3 | * Copyright (c) 2016 aishuyu, Inc. All Rights Reserved 4 | * 5 | **************************************************************************/ 6 | 7 | 8 | 9 | /** 10 | * @file leader_thread.cpp 11 | * @author aishuyu(asy5178@163.com) 12 | * @date 2016/08/26 20:17:50 13 | * @brief 14 | * 15 | **/ 16 | 17 | 18 | 19 | #include "leader_thread.h" 20 | 21 | #include "rpc_center.h" 22 | 23 | 24 | namespace libevrpc { 25 | 26 | LeaderThread::LeaderThread(): 27 | follower_q_(new FollowerQueue()), 28 | running_(false) { 29 | follower_q_->head = NULL; 30 | follower_q_->tail = NULL; 31 | } 32 | 33 | LeaderThread::~LeaderThread() { 34 | Destory(); 35 | } 36 | 37 | void LeaderThread::Destory() { 38 | if (NULL != follower_q_) { 39 | for (FW_ITEM* fw_item = follower_q_->head; 40 | fw_item != follower_q_->tail && fw_item != NULL; 41 | fw_item = fw_item->next) { 42 | delete fw_item; 43 | } 44 | follower_q_ = NULL; 45 | } 46 | } 47 | 48 | void LeaderThread::Run() { 49 | if (NULL == follower_q_) { 50 | follower_q_ = new FollowerQueue(); 51 | } 52 | while (running_) { 53 | FollowerItem* fw_item = PopFollowerMessage(); 54 | if (NULL == fw_item) { 55 | sleep(20); 56 | continue; 57 | } 58 | RpcCenter::GetInstance(g_config_file).ProcessCenterData(fw_item->conn_fd, fw_item->centers_proto); 59 | close(fw_item->conn_fd); 60 | delete fw_item; 61 | } 62 | Destory(); 63 | } 64 | 65 | void LeaderThread::StopThread() { 66 | running_ = false; 67 | } 68 | 69 | bool LeaderThread::PushFollowerMessage(int32_t fd, const CentersProto& centers_proto) { 70 | FollowerItem* fi = new FollowerItem(); 71 | fi->centers_proto.CopyFrom(centers_proto); 72 | fi->conn_fd = fd; 73 | fi->next = NULL; 74 | { 75 | MutexLockGuard lock(fq_mutex_); 76 | if (NULL == follower_q_->tail) { 77 | follower_q_->head = fi; 78 | } else { 79 | follower_q_->tail->next = fi; 80 | } 81 | follower_q_->tail = fi; 82 | } 83 | return true; 84 | } 85 | 86 | FollowerItem* LeaderThread::PopFollowerMessage() { 87 | FollowerItem* fw_item = NULL; 88 | { 89 | MutexLockGuard lock(fq_mutex_); 90 | fw_item = follower_q_->head; 91 | if (NULL != fw_item) { 92 | follower_q_->head = fw_item->next; 93 | if (NULL == follower_q_->head) { 94 | follower_q_->tail = NULL; 95 | } 96 | } 97 | } 98 | return fw_item; 99 | } 100 | 101 | 102 | 103 | } // end of namespace libevrpc 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | /* vim: set expandtab ts=4 sw=4 sts=4 tw=100: */ 116 | -------------------------------------------------------------------------------- /src/rpc_center/reporter_thread.cpp: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * 3 | * Copyright (c) 2016 aishuyu, Inc. All Rights Reserved 4 | * 5 | **************************************************************************/ 6 | 7 | 8 | 9 | /** 10 | * @file reporter_thread.cpp 11 | * @author aishuyu(asy5178@163.com) 12 | * @date 2016/07/17 00:43:25 13 | * @brief 14 | * 15 | **/ 16 | 17 | #include "reporter_thread.h" 18 | 19 | #include 20 | 21 | #include "rpc_center.h" 22 | #include "util/rpc_communication.h" 23 | #include "util/rpc_util.h" 24 | 25 | namespace libevrpc { 26 | 27 | using std::string; 28 | 29 | ReporterThread::ReporterThread(): 30 | leader_addr_(NULL), 31 | leader_port_(NULL), 32 | reporter_running_(false) { 33 | } 34 | 35 | ReporterThread::~ReporterThread() { 36 | if (NULL != leader_addr_) { 37 | free(leader_addr_); 38 | } 39 | if (NULL != leader_port_) { 40 | free(leader_port_); 41 | } 42 | } 43 | 44 | bool ReporterThread::StartReporter( 45 | const char* leader_addr, 46 | const char* leader_port) { 47 | if (reporter_running_) { 48 | if (NULL != leader_addr_) { 49 | free(leader_addr_); 50 | } 51 | if (NULL != leader_port_) { 52 | free(leader_port_); 53 | } 54 | close(conn_fd_); 55 | Stop(); 56 | } 57 | 58 | leader_addr_ = (char*)malloc(strlen(leader_addr)); 59 | leader_port_ = (char*)malloc(strlen(leader_port)); 60 | reporter_running_ = true; 61 | Start(); 62 | 63 | return true; 64 | } 65 | 66 | void ReporterThread::Run() { 67 | 68 | if (!reporter_running_) { 69 | return; 70 | } 71 | 72 | RpcCenter& rc = RpcCenter::GetInstance(g_config_file); 73 | 74 | int32_t failed_cnt = 10, retry_time = 3; 75 | while (reporter_running_) { 76 | conn_fd_ = TcpConnect(leader_addr_, leader_port_, 15); 77 | 78 | if (failed_cnt > 0 && !rc.ReporterProcessor(conn_fd_)) { 79 | --failed_cnt; 80 | } 81 | if (failed_cnt <= 0) { 82 | /* 83 | * 重新连接 84 | */ 85 | conn_fd_ = TcpConnect(leader_addr_, leader_port_, 15); 86 | if (conn_fd_ < 0) { 87 | --retry_time; 88 | } else { 89 | /* 90 | * 重试连接成功恢复初始状态 91 | */ 92 | failed_cnt = 10; 93 | retry_time = 3; 94 | } 95 | 96 | if (retry_time <= 0) { 97 | /* 98 | * Leader彻底无法连接 开始新一轮选举 并且当前线程退出 99 | */ 100 | rc.StartFastLeaderElection(); 101 | close(conn_fd_); 102 | break; 103 | } 104 | } 105 | close(conn_fd_); 106 | sleep(10); 107 | } 108 | } 109 | 110 | } // end of namespace libevrpc 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | /* vim: set expandtab ts=4 sw=4 sts=4 tw=100: */ 120 | -------------------------------------------------------------------------------- /src/rpc_center/election_thread.cpp: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * 3 | * Copyright (c) 2016 aishuyu, Inc. All Rights Reserved 4 | * 5 | **************************************************************************/ 6 | 7 | 8 | 9 | /** 10 | * @file election_thread.cpp 11 | * @author aishuyu(asy5178@163.com) 12 | * @date 2016/07/22 16:54:22 13 | * @brief 14 | * 15 | **/ 16 | 17 | 18 | #include "election_thread.h" 19 | 20 | #include "rpc_center.h" 21 | 22 | 23 | namespace libevrpc { 24 | 25 | using std::string; 26 | 27 | ElectionThread::ElectionThread() : 28 | election_q_(new ElectionQueue()), 29 | running_(true) { 30 | election_q_->head = NULL; 31 | election_q_->tail = NULL; 32 | } 33 | 34 | ElectionThread::~ElectionThread() { 35 | Destory(); 36 | } 37 | 38 | void ElectionThread::Destory() { 39 | if (NULL != election_q_) { 40 | for (EL_ITEM* el_item = election_q_->head; 41 | el_item != election_q_->tail && el_item != NULL; 42 | el_item = el_item->next) { 43 | delete el_item; 44 | } 45 | delete election_q_; 46 | election_q_ = NULL; 47 | } 48 | } 49 | 50 | void ElectionThread::Run() { 51 | if (NULL == election_q_) { 52 | election_q_ = new ElectionQueue(); 53 | } 54 | 55 | while (running_) { 56 | ElectionItem* el_item = PopElectionMessage(); 57 | if (NULL == el_item) { 58 | sleep(30); 59 | continue; 60 | } 61 | RpcCenter::GetInstance(g_config_file).ProcessCenterData(el_item->conn_fd, el_item->centers_proto); 62 | close(el_item->conn_fd); 63 | 64 | delete el_item; 65 | sleep(30); 66 | } 67 | Destory(); 68 | RpcCenter::GetInstance(g_config_file).SetFastLeaderRunning(false); 69 | } 70 | 71 | void ElectionThread::StopThread() { 72 | running_ = false; 73 | } 74 | 75 | bool ElectionThread::PushElectionMessage(int32_t fd, const CentersProto& centers_proto) { 76 | ElectionItem* ei = new ElectionItem(); 77 | ei->centers_proto.CopyFrom(centers_proto); 78 | ei->conn_fd = fd; 79 | ei->next = NULL; 80 | { 81 | MutexLockGuard lock(eq_mutex_); 82 | if (NULL == election_q_->tail) { 83 | election_q_->head = ei; 84 | } else { 85 | election_q_->tail->next = ei; 86 | } 87 | election_q_->tail = ei; 88 | } 89 | return true; 90 | } 91 | 92 | ElectionItem* ElectionThread::PopElectionMessage() { 93 | ElectionItem* el_item = NULL; 94 | { 95 | MutexLockGuard lock(eq_mutex_); 96 | el_item = election_q_->head; 97 | if (NULL != el_item) { 98 | election_q_->head = el_item->next; 99 | if (NULL == election_q_->head) { 100 | election_q_->tail = NULL; 101 | } 102 | } 103 | } 104 | return el_item; 105 | } 106 | 107 | 108 | } // end of namespace libevrpc 109 | 110 | 111 | 112 | 113 | 114 | 115 | /* vim: set expandtab ts=4 sw=4 sts=4 tw=100: */ 116 | -------------------------------------------------------------------------------- /src/center_proto/center_type.pb.cc: -------------------------------------------------------------------------------- 1 | // Generated by the protocol buffer compiler. DO NOT EDIT! 2 | // source: center_type.proto 3 | 4 | #define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION 5 | #include "center_type.pb.h" 6 | 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | // @@protoc_insertion_point(includes) 18 | 19 | namespace libevrpc { 20 | 21 | namespace { 22 | 23 | const ::google::protobuf::EnumDescriptor* CenterType_descriptor_ = NULL; 24 | 25 | } // namespace 26 | 27 | 28 | void protobuf_AssignDesc_center_5ftype_2eproto() { 29 | protobuf_AddDesc_center_5ftype_2eproto(); 30 | const ::google::protobuf::FileDescriptor* file = 31 | ::google::protobuf::DescriptorPool::generated_pool()->FindFileByName( 32 | "center_type.proto"); 33 | GOOGLE_CHECK(file != NULL); 34 | CenterType_descriptor_ = file->enum_type(0); 35 | } 36 | 37 | namespace { 38 | 39 | GOOGLE_PROTOBUF_DECLARE_ONCE(protobuf_AssignDescriptors_once_); 40 | inline void protobuf_AssignDescriptorsOnce() { 41 | ::google::protobuf::GoogleOnceInit(&protobuf_AssignDescriptors_once_, 42 | &protobuf_AssignDesc_center_5ftype_2eproto); 43 | } 44 | 45 | void protobuf_RegisterTypes(const ::std::string&) { 46 | protobuf_AssignDescriptorsOnce(); 47 | } 48 | 49 | } // namespace 50 | 51 | void protobuf_ShutdownFile_center_5ftype_2eproto() { 52 | } 53 | 54 | void protobuf_AddDesc_center_5ftype_2eproto() { 55 | static bool already_here = false; 56 | if (already_here) return; 57 | already_here = true; 58 | GOOGLE_PROTOBUF_VERIFY_VERSION; 59 | 60 | ::google::protobuf::DescriptorPool::InternalAddGeneratedFile( 61 | "\n\021center_type.proto\022\010libevrpc*F\n\nCenterT" 62 | "ype\022\021\n\rCENTER2CENTER\020d\022\021\n\rCENTER2CLIENT\020" 63 | "e\022\022\n\016CENTER2CLUSTER\020f", 101); 64 | ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile( 65 | "center_type.proto", &protobuf_RegisterTypes); 66 | ::google::protobuf::internal::OnShutdown(&protobuf_ShutdownFile_center_5ftype_2eproto); 67 | } 68 | 69 | // Force AddDescriptors() to be called at static initialization time. 70 | struct StaticDescriptorInitializer_center_5ftype_2eproto { 71 | StaticDescriptorInitializer_center_5ftype_2eproto() { 72 | protobuf_AddDesc_center_5ftype_2eproto(); 73 | } 74 | } static_descriptor_initializer_center_5ftype_2eproto_; 75 | const ::google::protobuf::EnumDescriptor* CenterType_descriptor() { 76 | protobuf_AssignDescriptorsOnce(); 77 | return CenterType_descriptor_; 78 | } 79 | bool CenterType_IsValid(int value) { 80 | switch(value) { 81 | case 100: 82 | case 101: 83 | case 102: 84 | return true; 85 | default: 86 | return false; 87 | } 88 | } 89 | 90 | 91 | // @@protoc_insertion_point(namespace_scope) 92 | 93 | } // namespace libevrpc 94 | 95 | // @@protoc_insertion_point(global_scope) 96 | -------------------------------------------------------------------------------- /src/util/pthread_mutex.h: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * 3 | * Copyright (c) 2014 aishuyu.com, Inc. All Rights Reserved 4 | * 5 | **************************************************************************/ 6 | 7 | 8 | 9 | /** 10 | * @file pthread_mutex.h 11 | * @author aishuyu(asy5178@163.com) 12 | * @date 2014/11/16 22:45:00 13 | * @brief 14 | * 15 | **/ 16 | 17 | 18 | 19 | 20 | #ifndef __PTHREAD_MUTEX_H_ 21 | #define __PTHREAD_MUTEX_H_ 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | 29 | namespace libevrpc { 30 | 31 | class Mutex { 32 | public: 33 | Mutex() : create_success_(false)/*, mutex_(PTHREAD_MUTEX_INITIALIZER)*/ { 34 | int ret = pthread_mutex_init(&mutex_, NULL); 35 | if (0 == ret) { 36 | create_success_ = true; 37 | } else { 38 | fprintf(stderr, "pthread init mutex failed! the error num is %d\n", ret); 39 | } 40 | } 41 | 42 | ~Mutex() { 43 | int ret = pthread_mutex_destroy(&mutex_); 44 | if (0 != ret) { 45 | fprintf(stderr,"pthread destroy mutex failed! the error num is %d\n", ret); 46 | } 47 | } 48 | 49 | bool IsSuccess() { 50 | return create_success_; 51 | } 52 | 53 | pthread_mutex_t& MMutex() { 54 | return mutex_; 55 | } 56 | private: 57 | bool create_success_; 58 | pthread_mutex_t mutex_; 59 | }; 60 | 61 | 62 | class MutexLockGuard { 63 | public: 64 | MutexLockGuard(Mutex &mutex, bool trylock = false) 65 | : mutex_(mutex.MMutex()), lock_success_(false) { 66 | if (false == trylock) { 67 | int ret = pthread_mutex_lock(&mutex_); 68 | if (0 == ret) { 69 | lock_success_ = true; 70 | } else { 71 | fprintf(stderr, "pthread lock mutex failed! the error num is %d\n", ret); 72 | } 73 | } else { 74 | // bad desgin? 75 | int ret = 0; 76 | while ((ret = pthread_mutex_trylock(&mutex_)) == EBUSY) { 77 | usleep(1); 78 | } 79 | if (0 == ret) { 80 | lock_success_ = true; 81 | } else { 82 | fprintf(stderr, "pthread trylock mutex failed! the error num is %d\n", ret); 83 | } 84 | } 85 | } 86 | 87 | ~MutexLockGuard() { 88 | int ret = pthread_mutex_unlock(&mutex_); 89 | if (0 != ret) { 90 | fprintf(stderr, "pthread unlock mutex failed! the error num is %d\n", ret); 91 | } 92 | } 93 | 94 | bool IsSuccess() { 95 | return lock_success_; 96 | } 97 | private: 98 | pthread_mutex_t& mutex_; 99 | bool lock_success_; 100 | 101 | }; 102 | 103 | 104 | } // end of namespace 105 | 106 | #endif //__PTHREAD_MUTEX_H_ 107 | 108 | /* vim: set expandtab ts=4 sw=4 sts=4 tw=100: */ 109 | -------------------------------------------------------------------------------- /src/rpc_client/rpc_heartbeat_client.cpp: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * 3 | * Copyright (c) 2016 aishuyu, Inc. All Rights Reserved 4 | * 5 | **************************************************************************/ 6 | 7 | 8 | 9 | /** 10 | * @file rpc_heartbeat_client.cpp 11 | * @author aishuyu(asy5178@163.com) 12 | * @date 2016/04/04 21:13:38 13 | * @brief 14 | * 15 | **/ 16 | 17 | #include "rpc_heartbeat_client.h" 18 | 19 | #include 20 | #include 21 | 22 | #include "util/rpc_util.h" 23 | #include "util/rpc_communication.h" 24 | 25 | namespace libevrpc { 26 | 27 | using std::string; 28 | 29 | RpcHeartbeatClient::RpcHeartbeatClient( 30 | const char* hb_server_addr, const char* hb_server_port, int32_t timeout) : 31 | hb_server_addr_(NULL), 32 | hb_server_port_(NULL), 33 | running_(true) { 34 | 35 | if (NULL != hb_server_addr && NULL != hb_server_port) { 36 | hb_server_addr_ = (char*)malloc(strlen(hb_server_addr)); 37 | hb_server_port_ = (char*)malloc(strlen(hb_server_port)); 38 | strcpy(hb_server_addr_, hb_server_addr); 39 | strcpy(hb_server_port_, hb_server_port); 40 | } 41 | 42 | timeout_ = timeout; 43 | } 44 | 45 | RpcHeartbeatClient::~RpcHeartbeatClient() { 46 | if (NULL != hb_server_addr_) { 47 | free(hb_server_addr_); 48 | } 49 | 50 | if (NULL != hb_server_port_) { 51 | free(hb_server_port_); 52 | } 53 | } 54 | 55 | bool RpcHeartbeatClient::CreateRpcConnection() { 56 | /* 57 | int32_t try_times = 3; 58 | do { 59 | connect_fd_ = TcpConnect(hb_server_addr_, hb_server_port_, timeout_); 60 | if (TCP_CONN_TIMEOUT != connect_fd_) { 61 | break; 62 | } 63 | --try_times; 64 | PrintErrorInfo("Heart beat tcp connect timeout! try again!"); 65 | } while (try_times <= 0); 66 | 67 | if (connect_fd_ < 0) { 68 | return false; 69 | } 70 | */ 71 | 72 | /* 73 | * UDP connection 74 | */ 75 | if (NULL == hb_server_addr_ || NULL == hb_server_port_) { 76 | PrintErrorInfo("hb server port or addr is NULL!"); 77 | return false; 78 | } 79 | connect_fd_ = UdpClientInit(hb_server_addr_, hb_server_port_, to_); 80 | if (connect_fd_ < 0) { 81 | PrintErrorInfo("Init udp server failed!"); 82 | return false; 83 | } 84 | 85 | return true; 86 | } 87 | 88 | void RpcHeartbeatClient::Run() { 89 | if (!CreateRpcConnection()) { 90 | PrintErrorInfo("Create the rpc heartbeat connection failed! Heartbeat thread exit!"); 91 | return; 92 | } 93 | /* 94 | * send local address to server 95 | */ 96 | string ping = GetLocalAddress(); 97 | while (running_) { 98 | if (RpcSendTo(connect_fd_, to_, ping, false) < 0) { 99 | PrintErrorInfo("Rpc Heartbeat send info failed!"); 100 | sleep(3); 101 | continue; 102 | } 103 | sleep(10); 104 | } 105 | close(connect_fd_); 106 | } 107 | 108 | 109 | } // end of namespace libevrpc 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | /* vim: set expandtab ts=4 sw=4 sts=4 tw=100: */ 123 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # libevrpc 2 | 3 | 4 | 技术简述 5 | 6 | 1.现阶段使用memcached线程池模型,实现IO接收机制和线程池机制(固定线程数),其中用libev代替libevent 7 | 2.客户端与服务端通信之间的框架与序列化, 使用protobuf框架进行实现 8 | 9 | 10 | 编译说明: 11 | 12 | 1.预备安装需要automake, gcc(4.8版本以上). 13 | 2.拉去安装相关依赖,确保当前目录有root权限后,执行deps_build.sh,安装需要的依赖编译文件,如果出错,按照出错信息进行修复依赖错误 14 | 3.安装好后,执行build.sh脚本 需要参数,命令示例: sh build.sh --prefix=/home/xxx/lib/libevrpc (确保目录有权限读写,否则会出现错误) 15 | 4.执行 make install 安装链接文件到指定目录 16 | 5.执行sh build.sh clean 清理编译文件 17 | 18 | 19 | 代码说明: 20 | 21 | 1.config_parser:配置文件解析 22 | 2.cs_sample: RPC客户端和RPC服务端实现实例 23 | 3.rpc_client:RPC客户端调相关实现目录,代码文件如下 24 | 1).rpc_client:对外实现RPC客户端接口,RPC客户端使用者实现RPC功能时,需要继承RpcClient后 实现自己的Rpc客户端逻辑 25 | 2).rpc_channel: 主要为提供客户端RPC访问,内部主要实现了socket 客户端实现 26 | 3).rpc_heartbeat_client:RPC心跳客户端,实际为一个后台普通线程,定时没隔一定时间,想RPC服务器发送心跳 27 | 4).client_rpc_controller:RPC客户端内部实现控制对象,现阶段只用于错误信息的输出 28 | 4.rpc_server:RPC服务端调相关实现目录,代码文件如下: 29 | 1).rpc_server: RPC服务端主程序实现,负责RPC服务端所有线程的启动和控制 30 | 2).dispatch_thread:libev IO线程,负责监听和接受网络请求,将网络请求分发给后台的libev线程池当中,期间无任何CPU密集型处理逻辑 31 | 3).libev_thread_pool:libev线程池.线程池中每个线程维护一个epoller,并负责RPC服务端逻辑的运行承载 32 | 4).connection_timer_manager:管理链接计时器,对超时的链接进行销毁处理 33 | 5).rpc_heartbeat_server:RPC服务端心跳线程,接受从客户端发送来的心跳,并将心跳信息更新到connection_timer_manager中 34 | 6).server_rpc_controller:RPC服务端内部实现控制对象,现阶段只用于错误信息的输出 35 |    5.rpc_center:rpc center功能实现代码 主要实现rpc server与rpc client之间的关联请求规则 36 |    6.unit_test:单元代码测试 37 | 7.util:工具类和函数 38 | 39 | 40 | 设计说明: 41 | 42 | 1.线程池每个线程维护一个epoller, IO每次请求都会向线程池中某个线程发送pipe信息,epoller线程开始处理 43 | 2.RPC添加心跳模式 保证客户端在崩溃,并且调用长调用的情况下,RPC服务端能够主动断掉无用连接,避免浪费服务的资源 44 | 3.因为采用线程池,一般线程数建议最佳线程数目 = ((线程等待时间+线程CPU时间)/线程CPU时间)*CPU数目,具体看RPC服务端的任务是IO密集型还是CPU密集型,IO密集型一般线程数偏小 减少或者避免线程上下文切换 45 | 4.本设计暂时只提供P2P中 不包含负载均衡功能 46 | 47 | 48 | Rpc Center集群选举算法:为了协调Center集群信息数据一致性,实现负载均衡等功能,必须从集群中选举出Leader进行计算,最后同步计算结果到所有机器上,集群运行步骤如下(FastLeaderElection,网络失联情况待补充) 49 | 50 | 1.RpcCenter集群中每台机器/tmp/centers_list下都会预先放置好 初始集群的机器列表 51 | 2.集群启动,每个机器启动服务线程准备接受请求 52 | 3.每台机器向其他机器询问信息(主要是启动时间等,同时同步本地Center 服务信息到其他Center服务上) 53 | 4.收集到其他机器Center服务信息后,按照既定规则 选取出本地Center判断出的Leader,然后发起Proposal,同时启动选举线程 54 | 5.每台机器会收到集群其他机器的Proposal,同时根据Proposal的信息进行判断,发起者建议的leader是否可以选举为leader 55 | Yes:选票记录在案,No:忽略其选票 最后更新当前发起者Center在本地的记录信息 56 | 6.当选票过程中出现选票 超过集群机器数量的 2 / n + 1的时候 57 | 如果当前机器为Leader,进入Leading状态,并广播确认自己的身份 58 | 否则,进入Observering状态,等待Leader机器确认 59 | 7.每台机器收到Leader机器的确认后,按照选举规则复查,是否与本地选取的出的leader机器比较,如本地尚未有选举结果,则直接通过 60 | 通过,进入Following状态,广播宣布自己跟随当前Leader机器,选举线程退出 61 | 未通过,发起新一轮选举,整个集群进入新一轮选举状态 回到步骤4,直到通过 62 | 8.每台机器收到其他机器宣布的结果 。更新本地内存中 所有Center服务器相应信息,标示起跟随的Leader 63 | 9.选举结束 64 | 65 | Rpc Center集群LoadBalancer实现: 66 | 67 | 1.RpcCenter集群正常启动完成, ConfigServe启动(管理RpcCenter机器列表等信息, 统一向RpcClient或者RpcServer提供全局服务器读取器信息) 68 | 2.RpcServer Cluster机器启动与RpcCenter之间的心跳线程, 初始化过程中从ConfigServer读取RpcCenter机器列表, 然后随机从这些RpcCenter列表中, 选取一个Center地址与之通信 69 | 3.接收到Rpc服务器的Center的根据CenterCluster统一的Hash算法计算出该Rpc服务机器应该向哪个(或哪些)Center汇报, 将结果返回该RpcServer服务器 70 | 4.RpcServer得到对应汇报Center机器,记录到内存和磁盘上,然后周期向对应汇报Center服务器心跳,汇报本地发Load CPU等信息 71 | 5.RpcCenter Cluster会根据所有RpcServer汇总上来的信息进行LoadBalancer计算(例如哪些虚节点与RpcServer对应) 72 | 6.RpcClient启动, 从ConfigServer获取Center列表, 随机选取一个与之进行通信(或者与RpcServer类似,初始化获取Center机器最后确定与之服务的Center服务器) 73 | 6.RpcCenter返回给RpcClient 对应的虚节点以及和虚节点下面对应的RpcServer服务器(选取虚节点遵循改虚节点对应RpcCenter为当时资源消耗最小原则) 74 | 7.RpcClient获取RpcServer列表之后, 随机选取一个RPCServer, 开始运行P2P(点对点)模式 Rpc 75 | 8.RpcClient 30s ~ 1分钟左右 重新执行6, 更新RpcServer信息 76 | 77 | 78 | -------------------------------------------------------------------------------- /src/rpc_server/rpc_heartbeat_server.cpp: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * 3 | * Copyright (c) 2016 aishuyu, Inc. All Rights Reserved 4 | * 5 | **************************************************************************/ 6 | 7 | 8 | 9 | /** 10 | * @file rpc_heartbeat_server.cpp 11 | * @author aishuyu(asy5178@163.com) 12 | * @date 2016/04/04 22:10:45 13 | * @brief 14 | * 15 | **/ 16 | 17 | #include "rpc_heartbeat_server.h" 18 | 19 | #include 20 | #include 21 | 22 | #include "connection_timer_manager.h" 23 | #include "util/rpc_communication.h" 24 | #include "util/rpc_util.h" 25 | 26 | 27 | namespace libevrpc { 28 | 29 | using std::string; 30 | 31 | 32 | RpcHeartbeatServer::RpcHeartbeatServer( 33 | const char* hb_host, 34 | const char* hb_port, 35 | const char* config_file) : 36 | hb_host_(NULL), 37 | hb_port_(NULL), 38 | config_file_(NULL), 39 | hb_running_(true) { 40 | 41 | hb_host_ = (char*)malloc(strlen(hb_host)); 42 | hb_port_ = (char*)malloc(strlen(hb_port)); 43 | config_file_ = (char*)malloc(strlen(config_file)); 44 | strcpy(hb_host_, hb_host); 45 | strcpy(hb_port_, hb_port); 46 | strcpy(config_file_, config_file); 47 | } 48 | 49 | RpcHeartbeatServer::~RpcHeartbeatServer() { 50 | if (NULL != config_file_) { 51 | free(config_file_); 52 | } 53 | 54 | if (NULL != hb_host_) { 55 | free(hb_host_); 56 | } 57 | 58 | if (NULL != hb_port_) { 59 | free(hb_port_); 60 | } 61 | } 62 | 63 | bool RpcHeartbeatServer::InitHeartbeatServer() { 64 | int32_t server_fd = UdpServerInit(hb_host_, hb_port_); 65 | if (server_fd < 0) { 66 | return false; 67 | } 68 | 69 | epoller_ = ev_loop_new(0); 70 | socket_watcher_.data = this; 71 | ev_io_init(&socket_watcher_, RpcHeartbeatServer::HeartBeatProcessor, server_fd, EV_READ); 72 | ev_io_start(epoller_, &socket_watcher_); 73 | return true; 74 | } 75 | 76 | void RpcHeartbeatServer::Run() { 77 | /* 78 | * UDP libev version 79 | */ 80 | if (InitHeartbeatServer()) { 81 | PrintErrorInfo("Rpc heartbeat Thread init failed!\n"); 82 | return; 83 | }; 84 | if (NULL == epoller_) { 85 | PrintErrorInfo("The epoller ptr is null!\n"); 86 | return; 87 | } 88 | 89 | ev_run(epoller_, 0); 90 | ev_loop_destroy(epoller_); 91 | epoller_ = NULL; 92 | 93 | /** 94 | * UDP common version 95 | */ 96 | /* 97 | int32_t server_fd = UdpServerInit(hb_host_, hb_port_); 98 | while(hb_running_) { 99 | string clien_addr; 100 | if (RpcRecvFrom(server_fd, clien_addr, false) < 0) { 101 | PrintErrorInfo("HeartBeatSeerver recv info error!"); 102 | } 103 | ConnectionTimerManager& ctm_instance = ConnectionTimerManager::GetInstance(config_file_); 104 | ctm_instance.InsertRefreshConnectionInfo(clien_addr); 105 | } 106 | close(server_fd); 107 | */ 108 | } 109 | 110 | void RpcHeartbeatServer::HeartBeatProcessor(struct ev_loop *loop, struct ev_io *watcher, int revents) { 111 | if (NULL == loop) { 112 | return; 113 | } 114 | if (EV_ERROR & revents) { 115 | return; 116 | } 117 | RpcHeartbeatServer* rhs = (RpcHeartbeatServer*)(watcher->data); 118 | string client_addr; 119 | if (RpcRecvFrom(watcher->fd, client_addr, false) < 0) { 120 | PrintErrorInfo("HeartBeatSeerver recv info error!"); 121 | } 122 | ConnectionTimerManager& ctm_instance = ConnectionTimerManager::GetInstance(rhs->config_file_); 123 | ctm_instance.InsertRefreshConnectionInfo(client_addr); 124 | } 125 | 126 | 127 | } // end of namespace libevrpc 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | /* vim: set expandtab ts=4 sw=4 sts=4 tw=100: */ 138 | -------------------------------------------------------------------------------- /src/rpc_server/libev_thread_pool.h: -------------------------------------------------------------------------------- 1 | /***************************************************************************A 2 | * 3 | * Copyright (c) 2014 aishuyu.com, Inc. All Rights Reserved 4 | * 5 | **************************************************************************/ 6 | 7 | 8 | 9 | /** 10 | * @file libev_thread_pool.h 11 | * @author aishuyu(asy5178@163.com) 12 | * @date 2014/11/07 15:32:07 13 | * @brief 14 | * 15 | **/ 16 | 17 | 18 | 19 | 20 | #ifndef __LIBEV_THREAD_POOL_H_ 21 | #define __LIBEV_THREAD_POOL_H_ 22 | 23 | 24 | #include 25 | #include 26 | #include 27 | 28 | #include 29 | 30 | #include "util/pthread_mutex.h" 31 | 32 | namespace libevrpc { 33 | 34 | /* 35 | * rpc call info item 36 | */ 37 | typedef struct RequestQueueItem RQ_ITEM; 38 | struct RequestQueueItem { 39 | // callback funtion 40 | void *(*processor)(void * arg); 41 | void *param; 42 | RQ_ITEM *prev; 43 | RQ_ITEM *next; 44 | int32_t connection_id; 45 | }; 46 | 47 | /* 48 | * rpc call queue 49 | */ 50 | class RequestQueue; 51 | typedef RequestQueue RQ; 52 | class RequestQueue { 53 | public: 54 | RQ_ITEM* head; 55 | RQ_ITEM* tail; 56 | Mutex q_mutex; 57 | }; 58 | 59 | /* 60 | * thread with libev info 61 | */ 62 | class LibevThreadPool; 63 | typedef struct { 64 | pthread_t thread_id; 65 | struct ev_loop* epoller; 66 | struct ev_io libev_watcher; 67 | int32_t notify_receive_fd; 68 | int32_t notify_send_fd; 69 | int32_t pool_index; 70 | long running_version; 71 | RQ* new_request_queue; 72 | LibevThreadPool* lt_pool; 73 | 74 | Mutex version_mutex; 75 | } LIBEV_THREAD; 76 | 77 | /* 78 | * use to retrieve data when the thread to be terminated 79 | */ 80 | struct RetrieveData { 81 | LibevThreadPool* retrieve_ltp; 82 | RQ_ITEM* retrieve_item; 83 | }; 84 | 85 | class LibevThreadPool { 86 | public: 87 | LibevThreadPool(); 88 | 89 | virtual ~LibevThreadPool(); 90 | 91 | bool Start(int32_t num_threads = 10); 92 | bool Wait(); 93 | 94 | /* 95 | * kill the current thread and restart a new thread to 96 | * replace it 97 | */ 98 | bool RestartThread(pthread_t thread_id, long running_version); 99 | 100 | /* 101 | * nonblock call the processor and return shortly 102 | */ 103 | bool DispatchRpcCall(void *(*process) (void *arg), void *arg); 104 | 105 | private: 106 | bool LibevThreadInitialization(int32_t num_threads); 107 | 108 | /* 109 | * request itesm op 110 | */ 111 | RQ_ITEM* RQItemNew(); 112 | RQ_ITEM* RQItemPop(RQ* req_queue); 113 | bool RQItemPush(RQ* req_queue, RQ_ITEM* req_item); 114 | bool RQItemFree(RQ_ITEM* req_item); 115 | 116 | /* 117 | * static fuction 118 | */ 119 | static void LibevProcessor(struct ev_loop *loop, struct ev_io *watcher, int revents); 120 | static void *LibevWorker(void *arg); 121 | /* 122 | * where the thread exit exceedingly, do retrieve the data! 123 | */ 124 | static void RetrieveDataAction(void *arg); 125 | 126 | bool Destroy(); 127 | 128 | private: 129 | /* 130 | * threads 131 | */ 132 | int32_t current_thread_; 133 | int32_t num_threads_; 134 | 135 | LIBEV_THREAD* libev_threads_; 136 | RQ_ITEM* rqi_freelist_; 137 | 138 | Mutex rqi_freelist_mutex_; 139 | 140 | static int32_t item_per_alloc_; 141 | //static atomic_bool running_; 142 | 143 | // public: 144 | private: 145 | /* 146 | * for unit test 147 | */ 148 | LIBEV_THREAD* GetTestThreadInfo() const; 149 | 150 | }; 151 | 152 | 153 | } // end of namespace libevrpc 154 | 155 | #endif //__LIBEV_THREAD_POOL_H_ 156 | 157 | /* vim: set expandtab ts=4 sw=4 sts=4 tw=100: */ 158 | -------------------------------------------------------------------------------- /src/rpc_client/rpc_channel.h: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * 3 | * Copyright (c) 2014 Aishuyu. All Rights Reserved 4 | * 5 | **************************************************************************/ 6 | 7 | 8 | 9 | /** 10 | * @file rpc_channel.h 11 | * @author aishuyu(asy5178@163.com) 12 | * @date 2014/11/23 16:37:20 13 | * @brief 14 | * 15 | **/ 16 | 17 | 18 | 19 | 20 | #ifndef __RPC_CHANNEL_H_ 21 | #define __RPC_CHANNEL_H_ 22 | 23 | #include 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | #include 32 | #include 33 | 34 | #include "center_client_heartbeat.h" 35 | #include "util/pthread_rwlock.h" 36 | 37 | namespace libevrpc { 38 | 39 | using google::protobuf::Message; 40 | using google::protobuf::Closure; 41 | using google::protobuf::RpcChannel; 42 | using google::protobuf::RpcController; 43 | using google::protobuf::MethodDescriptor; 44 | 45 | typedef std::list TidList; 46 | typedef std::shared_ptr TidListPtr; 47 | typedef std::unordered_map PthreadHashMap; 48 | typedef std::unordered_map MsgHashMap; 49 | 50 | 51 | class Channel; 52 | 53 | struct RpcCallParams { 54 | RpcCallParams( 55 | const std::string& method_full_name, 56 | const std::string& method_client_name, 57 | const Message* request, 58 | Message* response, 59 | Channel* channel) : 60 | method_full_name(method_full_name), 61 | method_client_name(method_client_name), 62 | p_request(request), 63 | p_response(response), 64 | p_channel(const_cast(channel)) { 65 | } 66 | 67 | const std::string method_full_name; 68 | const std::string method_client_name; 69 | const Message* p_request; 70 | 71 | std::string response_str; 72 | Message* p_response; 73 | Channel* p_channel; 74 | }; 75 | 76 | class Channel : public RpcChannel { 77 | public: 78 | Channel(const char* addr, const char* port); 79 | /** 80 | * FOR server distribution mode 81 | */ 82 | Channel(CenterClientHeartbeat* center_client_heartbeat_ptr, const char* port); 83 | 84 | virtual ~Channel(); 85 | 86 | virtual void CallMethod(const MethodDescriptor* method, 87 | RpcController* controller, 88 | const Message* request, 89 | Message* response, 90 | Closure* done); 91 | 92 | bool OpenRpcAsyncMode(); 93 | bool RpcCommunication(RpcCallParams* rpc_params); 94 | bool AsyncRpcCall(RpcCallParams* rpc_params_ptr); 95 | bool GetAsyncResponse(const std::string& method_name, Message* response); 96 | 97 | /* 98 | * try_time for timeout 99 | */ 100 | void SetConnectionInfo(int32_t timeout, int32_t try_time = 1); 101 | void SetCallLimit(int32_t limit); 102 | 103 | static void* RpcProcessor(void *arg); 104 | 105 | private: 106 | char* addr_; 107 | char* port_; 108 | int32_t connect_fd_; 109 | 110 | bool is_channel_async_call_; 111 | int32_t call_limit_; 112 | 113 | int32_t tcp_conn_timeout_; 114 | /* 115 | * only for time out 116 | */ 117 | int32_t try_time_; 118 | CenterClientHeartbeat* center_client_heartbeat_ptr_; 119 | std::string error_info_; 120 | 121 | std::vector thread_ids_vec_; 122 | MsgHashMap call_results_map_; 123 | PthreadHashMap call_tids_map_; 124 | 125 | RWLock tids_map_rwlock_; 126 | RWLock ret_map_rwlock_; 127 | }; 128 | 129 | } // end of namespace libevrpc 130 | 131 | 132 | 133 | #endif //__RPC_CHANNEL_H_ 134 | 135 | /* vim: set expandtab ts=4 sw=4 sts=4 tw=100: */ 136 | -------------------------------------------------------------------------------- /src/rpc_center/load_balancer/consistent_hash_load_balancer.cpp: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * 3 | * Copyright (c) 2016 aishuyu, Inc. All Rights Reserved 4 | * 5 | **************************************************************************/ 6 | 7 | 8 | 9 | /** 10 | * @file consistent_hash_load_balancer.cpp 11 | * @author aishuyu(asy5178@163.com) 12 | * @date 2016/09/08 20:22:19 13 | * @brief 14 | * 15 | **/ 16 | 17 | 18 | #include "consistent_hash_load_balancer.h" 19 | 20 | #include "center_proto/center_cluster.pb.h" 21 | #include "config_parser/config_parser.h" 22 | #include "util/rpc_util.h" 23 | 24 | 25 | namespace libevrpc { 26 | 27 | using std::string; 28 | using std::vector; 29 | using ::google::protobuf::RepeatedPtrField; 30 | 31 | ConsistentHashLoadBalancer::ConsistentHashLoadBalancer(const string& config_file) : 32 | config_file_(config_file), 33 | virtual_node_num_(20), 34 | vn_map_ptr_(new VN_HASH_MAP()) { 35 | 36 | } 37 | 38 | ConsistentHashLoadBalancer::~ConsistentHashLoadBalancer() { 39 | if (NULL != vn_map_ptr_) { 40 | delete vn_map_ptr_; 41 | } 42 | } 43 | 44 | bool ConsistentHashLoadBalancer::InitBalancer() { 45 | if ("" == config_file_) { 46 | return false; 47 | } 48 | ConfigParser& config_parser_instance = ConfigParser::GetInstance(config_file_); 49 | virtual_node_num_ = config_parser_instance.IniGetInt("rpc_center:virtual_node_num", 20); 50 | return true; 51 | } 52 | 53 | void ConsistentHashLoadBalancer::SetConfigFile(const std::string& file_name) { 54 | config_file_ = file_name; 55 | } 56 | 57 | bool ConsistentHashLoadBalancer::AddRpcServer(const RpcClusterServer& rpc_cluster_server) { 58 | WriteLockGuard wguard(vmap_rwlock_); 59 | string rpc_server = rpc_cluster_server.cluster_server_addr(); 60 | for (int32_t i = 0; i < virtual_node_num_; ++i) { 61 | string hash_str = "SHARD-" + rpc_server + "-NODE-" + static_cast(i); 62 | uint32_t hash_id = MurMurHash2(hash_str.c_str(), hash_str.size()); 63 | vn_map_ptr_->insert(std::make_pair(hash_id, rpc_server)); 64 | } 65 | return true; 66 | } 67 | 68 | bool ConsistentHashLoadBalancer::GetRpcServer( 69 | const string& rpc_client, vector& rpc_server_list) { 70 | uint32_t hash_id = MurMurHash2(rpc_client.c_str(), rpc_client.size()); 71 | 72 | ReadLockGuard rguard(vmap_rwlock_); 73 | if (vn_map_ptr_->empty()) { 74 | return false; 75 | } 76 | VN_HASH_MAP::iterator vn_iter = vn_map_ptr_->lower_bound(hash_id); 77 | if (vn_map_ptr_->end() == vn_iter) { 78 | VN_HASH_MAP::iterator sub_iter = vn_map_ptr_->begin(); 79 | if (sub_iter != vn_map_ptr_->end()) { 80 | rpc_server_list.push_back(sub_iter->second); 81 | } 82 | } else { 83 | rpc_server_list.push_back(vn_iter->second); 84 | } 85 | return true; 86 | } 87 | 88 | 89 | bool ConsistentHashLoadBalancer::GetCurrentLBResult(RepeatedPtrField& lb_result_list) { 90 | ReadLockGuard rguard(vmap_rwlock_); 91 | for (VN_HASH_MAP::iterator iter = vn_map_ptr_->begin(); 92 | iter != vn_map_ptr_->end(); 93 | ++iter) { 94 | LoadBalancerMetaData* lb_mdata_ptr = lb_result_list.Add(); 95 | lb_mdata_ptr->set_vid(iter->first); 96 | lb_mdata_ptr->set_server_addr(iter->second); 97 | } 98 | return true; 99 | } 100 | 101 | bool ConsistentHashLoadBalancer::UpdateLBResult(const RepeatedPtrField& lb_result_list) { 102 | WriteLockGuard wguard(vmap_rwlock_); 103 | for (RepeatedPtrField::const_iterator iter = lb_result_list.begin(); 104 | iter != lb_result_list.end(); 105 | ++iter) { 106 | vn_map_ptr_->insert(std::make_pair(iter->vid(), iter->server_addr())); 107 | } 108 | return true; 109 | } 110 | 111 | 112 | } // end of namespace libevrpc 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | /* vim: set expandtab ts=4 sw=4 sts=4 tw=100: */ 126 | -------------------------------------------------------------------------------- /src/rpc_server/rpc_server.h: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * 3 | * Copyright (c) 2014 Aishuyu. All Rights Reserved 4 | * 5 | **************************************************************************/ 6 | 7 | 8 | 9 | /** 10 | * @file rpc_server.h 11 | * @author aishuyu(asy5178@163.com) 12 | * @date 2014/11/23 16:49:42 13 | * @brief 14 | * 15 | **/ 16 | 17 | 18 | 19 | 20 | #ifndef __RPC_SERVER_H_ 21 | #define __RPC_SERVER_H_ 22 | 23 | #include 24 | 25 | #include 26 | 27 | #include "dispatch_thread.h" 28 | #include "connection_timer_manager.h" 29 | #include "libev_thread_pool.h" 30 | #include "center_cluster_heartbeat.h" 31 | #include "config_parser/config_parser.h" 32 | #include "util/disallow_copy_and_assign.h" 33 | #include "util/pthread_mutex.h" 34 | #include "util/pthread_rwlock.h" 35 | 36 | 37 | namespace libevrpc { 38 | 39 | using namespace google::protobuf; 40 | using __gnu_cxx::hash_map; 41 | 42 | struct RpcMethod { 43 | RpcMethod(Service* p_service, 44 | const Message* p_req, 45 | const Message* p_rep, 46 | const MethodDescriptor* p_meth) 47 | : service(p_service), 48 | request(p_req), 49 | response(p_rep), 50 | method(p_meth) { 51 | } 52 | 53 | Service* service; 54 | const Message* request; 55 | const Message* response; 56 | const MethodDescriptor* method; 57 | }; 58 | 59 | typedef hash_map HashMap; 60 | 61 | // single thread 62 | class RpcServer { 63 | public: 64 | ~RpcServer(); 65 | 66 | static RpcServer& GetInstance(); 67 | static RpcServer& GetInstance(const std::string& config_file); 68 | 69 | bool RegisteService(Service* reg_service); 70 | bool Start(); 71 | bool Wait(); 72 | 73 | /* 74 | * in fact, terminate the current thread, and new one thread replace it. 75 | */ 76 | bool RestartWorkerThread(pthread_t thread_id, long running_version); 77 | 78 | static void RpcCall(int32_t event_fd, void *arg); 79 | static void* RpcProcessor(void *arg); 80 | static void* RpcReader(void *arg); 81 | static void* RpcWriter(void *arg); 82 | 83 | 84 | private: 85 | RpcServer(const std::string& config_file = "./rpc_server.ini"); 86 | 87 | bool Initialize(const std::string& config_file); 88 | 89 | bool ErrorSendMsg(int32_t event_fd, const string& error_msg); 90 | 91 | DISALLOW_COPY_AND_ASSIGN(RpcServer); 92 | 93 | 94 | private: 95 | /* 96 | * RPC函数注册列表读写锁 97 | */ 98 | RWLock hashmap_rwlock_; 99 | 100 | /* 101 | * RPC函数注册列表 102 | */ 103 | HashMap method_hashmap_; 104 | 105 | std::string config_file_; 106 | 107 | DispatchThread* dispatcher_thread_ptr_; 108 | LibevThreadPool* worker_threads_ptr_; 109 | LibevThreadPool* reader_threads_ptr_; 110 | LibevThreadPool* writer_threads_ptr_; 111 | RpcController* rpc_controller_ptr_; 112 | CenterClusterHeartbeat* center_cluster_heartbeat_ptr_; 113 | 114 | ConfigParser& config_parser_instance_; 115 | ConnectionTimerManager& connection_timer_manager_; 116 | 117 | int32_t active_wtd_num_; 118 | bool connection_timer_open_; 119 | 120 | struct CallBackParams { 121 | CallBackParams() : 122 | rpc_server_ptr(NULL), 123 | response_ptr(NULL){ 124 | } 125 | 126 | ~CallBackParams() { 127 | if (NULL != response_ptr) { 128 | delete response_ptr; 129 | } 130 | } 131 | 132 | int32_t event_fd; 133 | int32_t call_id; 134 | /* 135 | * current rpc server ptr 136 | */ 137 | RpcServer* rpc_server_ptr; 138 | 139 | std::string recv_info; 140 | Message* response_ptr; 141 | RpcController* rpc_controller_ptr; 142 | }; 143 | }; 144 | 145 | } // end of namespace libevrpc 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | #endif //__RPC_SERVER_H_ 155 | 156 | /* vim: set expandtab ts=4 sw=4 sts=4 tw=100: */ 157 | -------------------------------------------------------------------------------- /src/unit_test/Makefile.am: -------------------------------------------------------------------------------- 1 | AUTOMAKE_OPTIONS=foreign subdir-objects 2 | 3 | proj_dir = ${top_srcdir}/.. 4 | top_dir = ${proj_dir}/../.. 5 | center_rootdir = ${proj_dir}/rpc_center 6 | server_rootdir = ${proj_dir}/rpc_server 7 | client_rootdir = ${proj_dir}/rpc_client 8 | config_parser = ${proj_dir}/config_parser 9 | center_proto = ${proj_dir}/center_proto 10 | util_dir = ${proj_dir}/util 11 | ut_dir = ${proj_dir}/unit_test 12 | third_dir = ${top_dir}/third-64 13 | 14 | AM_CPPFLAGS = -I${proj_dir}/ \ 15 | -I${third_dir}/gperftools/include/ \ 16 | -I${third_dir}/protobuf/include/ \ 17 | -I${third_dir}/libev/include/ 18 | 19 | #AM_LDFLAGS = -lz -lrt 20 | #AM_LDFLAGS = -lz -lstdc++ -lprotobuf 21 | AM_LDFLAGS = -lz -lstdc++ 22 | 23 | LDADD = ${third_dir}/protobuf/lib/*.a \ 24 | ${third_dir}/libev/lib/*.a 25 | 26 | RPC_SRC = ${config_parser}/config_parser.h \ 27 | ${config_parser}/config_parser.cpp \ 28 | ${config_parser}/dictionary.h \ 29 | ${config_parser}/dictionary.cpp \ 30 | ${config_parser}/iniparser.h \ 31 | ${config_parser}/iniparser.cpp \ 32 | ${util_dir}/rpc_util.h \ 33 | ${util_dir}/rpc_util.cpp \ 34 | ${util_dir}/thread.h \ 35 | ${util_dir}/pthread_mutex.h \ 36 | ${util_dir}/pthread_rwlock.h \ 37 | ${util_dir}/disallow_copy_and_assign.h \ 38 | ${util_dir}/rpc_communication.h \ 39 | ${util_dir}/rpc_communication.cpp \ 40 | ${center_proto}/center_cluster.pb.h \ 41 | ${center_proto}/center_cluster.pb.cc \ 42 | ${center_proto}/center_client.pb.h \ 43 | ${center_proto}/center_client.pb.cc \ 44 | ${center_proto}/centers.pb.h \ 45 | ${center_proto}/centers.pb.cc \ 46 | ${center_proto}/center_type.pb.h \ 47 | ${center_proto}/center_type.pb.cc 48 | 49 | RPC_SERVER = ${server_rootdir}/rpc_server.h \ 50 | ${server_rootdir}/rpc_server.cpp \ 51 | ${server_rootdir}/dispatch_thread.h \ 52 | ${server_rootdir}/dispatch_thread.cpp \ 53 | ${server_rootdir}/libev_thread_pool.h \ 54 | ${server_rootdir}/libev_thread_pool.cpp \ 55 | ${server_rootdir}/connection_timer_manager.h \ 56 | ${server_rootdir}/connection_timer_manager.cpp \ 57 | ${server_rootdir}/center_cluster_heartbeat.h \ 58 | ${server_rootdir}/center_cluster_heartbeat.cpp \ 59 | ${server_rootdir}/rpc_heartbeat_server.h \ 60 | ${server_rootdir}/rpc_heartbeat_server.cpp 61 | 62 | 63 | RPC_CENTER = ${center_rootdir}/rpc_center.h \ 64 | ${center_rootdir}/rpc_center.cpp \ 65 | ${center_rootdir}/reporter_thread.h \ 66 | ${center_rootdir}/reporter_thread.cpp \ 67 | ${center_rootdir}/leader_thread.h \ 68 | ${center_rootdir}/leader_thread.cpp \ 69 | ${center_rootdir}/election_thread.h \ 70 | ${center_rootdir}/election_thread.cpp \ 71 | ${center_rootdir}/center_server_thread.h \ 72 | ${center_rootdir}/center_server_thread.cpp \ 73 | ${center_rootdir}/load_balancer/load_balancer.h \ 74 | ${center_rootdir}/load_balancer/consistent_hash_load_balancer.h \ 75 | ${center_rootdir}/load_balancer/consistent_hash_load_balancer.cpp 76 | 77 | # LTP = ${ut_dir}/test_libev_tp.cpp ${util_dir}/pthread_mutex.h ${server_rootdir}/libev_thread_pool.h ${server_rootdir}/libev_thread_pool.cpp 78 | 79 | #bin_PROGRAMS = ltp_client ltp_server 80 | #bin_PROGRAMS = ltp_test 81 | bin_PROGRAMS = cc_cluster cc_client cc_center 82 | 83 | LTP_CLIENT = ${ut_dir}/test_hb_client.cc ${RPC_SRC} \ 84 | ${client_rootdir}/rpc_heartbeat_client.h \ 85 | ${client_rootdir}/rpc_heartbeat_client.cpp 86 | ltp_client_SOURCES = ${LTP_CLIENT} 87 | 88 | LTP_SERVER = ${ut_dir}/test_hb_server.cc ${RPC_SRC} ${RPC_SERVER} 89 | ltp_server_SOURCES = ${LTP_SERVER} 90 | 91 | LTP_TEST = ${ut_dir}/test_libev_tp.cc ${RPC_SRC} ${RPC_SERVER} 92 | ltp_test_SOURCES = ${LTP_TEST} 93 | 94 | CC_CLUSTER_TEST = ${ut_dir}/center_test/cluster_test.cc ${RPC_SRC} \ 95 | ${server_rootdir}/center_cluster_heartbeat.h \ 96 | ${server_rootdir}/center_cluster_heartbeat.cpp 97 | cc_cluster_SOURCES = ${CC_CLUSTER_TEST} 98 | 99 | 100 | CC_CLIENT_TEST = ${ut_dir}/center_test/client_test.cc ${RPC_SRC} \ 101 | ${client_rootdir}/center_client_heartbeat.h \ 102 | ${client_rootdir}/center_client_heartbeat.cpp 103 | cc_client_SOURCES = ${CC_CLIENT_TEST} 104 | 105 | 106 | CC_CENTER_TEST = ${ut_dir}/center_test/center_test.cc \ 107 | ${RPC_SRC} \ 108 | ${RPC_SERVER} \ 109 | ${RPC_CENTER} 110 | cc_center_SOURCES = ${CC_CENTER_TEST} 111 | 112 | 113 | 114 | #SUBDIRS = test 115 | -------------------------------------------------------------------------------- /src/rpc_client/rpc_client.cpp: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * 3 | * Copyright (c) 2015 aishuyu, Inc. All Rights Reserved 4 | * 5 | **************************************************************************/ 6 | 7 | 8 | 9 | /** 10 | * @file rpc_client.cpp 11 | * @author aishuyu(asy5178@163.com) 12 | * @date 2015/09/10 20:08:23 13 | * @brief 14 | * 15 | **/ 16 | 17 | #include "rpc_client.h" 18 | 19 | #include "client_rpc_controller.h" 20 | #include "util/rpc_util.h" 21 | 22 | namespace libevrpc { 23 | 24 | using std::string; 25 | 26 | RpcClient::RpcClient(const string& config_file) : 27 | rpc_channel_ptr_(NULL), 28 | rpc_controller_ptr_(NULL), 29 | rpc_heartbeat_ptr_(NULL), 30 | center_client_heartbeat_ptr_(NULL), 31 | config_parser_instance_(ConfigParser::GetInstance(config_file)){ 32 | 33 | InitClient(config_file); 34 | } 35 | 36 | RpcClient::~RpcClient() { 37 | if (NULL != rpc_heartbeat_ptr_) { 38 | rpc_heartbeat_ptr_->Stop(); 39 | rpc_heartbeat_ptr_->Wait(); 40 | delete rpc_heartbeat_ptr_; 41 | } 42 | 43 | if (NULL != center_client_heartbeat_ptr_) { 44 | center_client_heartbeat_ptr_->Stop(); 45 | center_client_heartbeat_ptr_->Wait(); 46 | delete center_client_heartbeat_ptr_; 47 | } 48 | 49 | if (NULL != rpc_channel_ptr_) { 50 | delete rpc_channel_ptr_; 51 | } 52 | 53 | if (NULL != rpc_controller_ptr_) { 54 | delete rpc_controller_ptr_; 55 | } 56 | } 57 | 58 | bool RpcClient::InitClient(const string& config_file) { 59 | const char* rpc_server_addr = config_parser_instance_.IniGetString("rpc_server:addr", "127.0.0.1"); 60 | const char* rpc_server_port = config_parser_instance_.IniGetString("rpc_server:port", "9998"); 61 | const char* hb_server_port = config_parser_instance_.IniGetString("heartbeat:port", "9999"); 62 | bool distributed_mode = config_parser_instance_.IniGetBool("rpc_server:distributed_mode", false); 63 | bool hb_open = config_parser_instance_.IniGetBool("heartbeat:open", true); 64 | int32_t rpc_connection_timeout = config_parser_instance_.IniGetInt("connection:timeout", 10); 65 | 66 | if (distributed_mode) { 67 | center_client_heartbeat_ptr_ = new CenterClientHeartbeat(config_file); 68 | center_client_heartbeat_ptr_->Start(); 69 | rpc_channel_ptr_ = new Channel(center_client_heartbeat_ptr_, rpc_server_port); 70 | } else if (NULL != rpc_server_addr && NULL != rpc_server_port) { 71 | rpc_channel_ptr_ = new Channel(rpc_server_addr, rpc_server_port); 72 | } else { 73 | rpc_channel_ptr_ = new Channel("127.0.0.1", "9999"); 74 | PrintErrorInfo("Attention! rpc client cann't read config file! Init with local server address and default port:8899! \n"); 75 | } 76 | 77 | if (hb_open) { 78 | rpc_heartbeat_ptr_ = new RpcHeartbeatClient(rpc_server_addr, hb_server_port, rpc_connection_timeout); 79 | rpc_heartbeat_ptr_->Start(); 80 | } 81 | 82 | rpc_controller_ptr_ = new ClientRpcController(); 83 | SetRpcConnectionInfo(1000, 1); 84 | return true; 85 | } 86 | 87 | RpcController* RpcClient::Status() { 88 | return rpc_controller_ptr_; 89 | } 90 | 91 | bool RpcClient::IsCallOk() { 92 | if (NULL == rpc_controller_ptr_) { 93 | return true; 94 | } 95 | return !rpc_controller_ptr_->Failed(); 96 | } 97 | 98 | string RpcClient::GetErrorInfo() const { 99 | if (NULL == rpc_controller_ptr_) { 100 | return ""; 101 | } 102 | return rpc_controller_ptr_->ErrorText(); 103 | } 104 | 105 | Channel* RpcClient::GetRpcChannel() { 106 | return rpc_channel_ptr_; 107 | } 108 | 109 | bool RpcClient::OpenRpcAsyncMode() { 110 | if (NULL == rpc_channel_ptr_) { 111 | PrintErrorInfo("Maybe YOU DIDNOT call InitClient first! open the async failed!"); 112 | exit(0); 113 | } 114 | rpc_channel_ptr_->OpenRpcAsyncMode(); 115 | return true; 116 | } 117 | 118 | bool RpcClient::GetAsyncResponse(const string& method_name, Message* response) { 119 | if (NULL == rpc_channel_ptr_) { 120 | return false; 121 | } 122 | return rpc_channel_ptr_->GetAsyncResponse(method_name, response); 123 | } 124 | 125 | bool RpcClient::SetRpcConnectionInfo(int32_t rpc_timeout, int32_t try_time) { 126 | if (NULL == rpc_channel_ptr_) { 127 | return false; 128 | } 129 | rpc_channel_ptr_->SetConnectionInfo(rpc_timeout, try_time); 130 | return true; 131 | } 132 | 133 | 134 | } // end of namespace libevrpc 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | /* vim: set expandtab ts=4 sw=4 sts=4 tw=100: */ 148 | -------------------------------------------------------------------------------- /src/util/pthread_rwlock.h: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * 3 | * Copyright (c) 2015 aishuyu, Inc. All Rights Reserved 4 | * 5 | **************************************************************************/ 6 | 7 | 8 | 9 | /** 10 | * @file pthread_rwlock.h 11 | * @author aishuyu(asy5178@163.com) 12 | * @date 2015/01/04 17:09:52 13 | * @brief 14 | * 15 | **/ 16 | 17 | 18 | 19 | 20 | #ifndef __PTHREAD_LOCK_H_ 21 | #define __PTHREAD_LOCK_H_ 22 | 23 | 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | 30 | namespace libevrpc { 31 | 32 | class RWLock { 33 | public: 34 | RWLock() : create_success_(false)/*, rwlock_(PTHREAD_MUTEX_INITIALIZER)*/ { 35 | int ret = pthread_rwlock_init(&rwlock_, NULL); 36 | if (0 == ret) { 37 | create_success_ = true; 38 | } else { 39 | fprintf(stderr, "pthread init rwlock failed! the error num is %d\n", ret); 40 | } 41 | } 42 | 43 | ~RWLock() { 44 | int ret = pthread_rwlock_destroy(&rwlock_); 45 | if (0 != ret) { 46 | fprintf(stderr,"pthread destroy rwlock failed! the error num is %d\n", ret); 47 | } 48 | } 49 | 50 | bool IsSuccess() { 51 | return create_success_; 52 | } 53 | 54 | pthread_rwlock_t& MLock() { 55 | return rwlock_; 56 | } 57 | private: 58 | bool create_success_; 59 | pthread_rwlock_t rwlock_; 60 | }; 61 | 62 | 63 | class ReadLockGuard { 64 | public: 65 | ReadLockGuard(RWLock &rwlock, bool trylock = false) 66 | : rwlock_(rwlock.MLock()), lock_success_(false) { 67 | if (false == trylock) { 68 | int ret = pthread_rwlock_rdlock(&rwlock_); 69 | if (0 == ret) { 70 | lock_success_ = true; 71 | } else { 72 | fprintf(stderr, "pthread lock rwlock failed! the error num is %d\n", ret); 73 | } 74 | } else { 75 | // bad desgin? 76 | int ret = 0; 77 | while ((ret = pthread_rwlock_tryrdlock(&rwlock_)) == EBUSY) { 78 | usleep(1); 79 | } 80 | if (0 == ret) { 81 | lock_success_ = true; 82 | } else { 83 | fprintf(stderr, "pthread trylock rwlock failed! the error num is %d\n", ret); 84 | } 85 | } 86 | } 87 | 88 | ~ReadLockGuard() { 89 | int ret = pthread_rwlock_unlock(&rwlock_); 90 | if (0 != ret) { 91 | fprintf(stderr, "pthread unlock rwlock failed! the error num is %d\n", ret); 92 | } 93 | } 94 | 95 | bool IsSuccess() { 96 | return lock_success_; 97 | } 98 | private: 99 | pthread_rwlock_t& rwlock_; 100 | bool lock_success_; 101 | 102 | }; 103 | 104 | 105 | class WriteLockGuard { 106 | public: 107 | WriteLockGuard(RWLock &rwlock, bool trylock = false) 108 | : rwlock_(rwlock.MLock()), lock_success_(false) { 109 | if (false == trylock) { 110 | int ret = pthread_rwlock_wrlock(&rwlock_); 111 | if (0 == ret) { 112 | lock_success_ = true; 113 | } else { 114 | fprintf(stderr, "pthread lock rwlock failed! the error num is %d\n", ret); 115 | } 116 | } else { 117 | // bad desgin? 118 | int ret = 0; 119 | while ((ret = pthread_rwlock_trywrlock(&rwlock_)) == EBUSY) { 120 | usleep(1); 121 | } 122 | if (0 == ret) { 123 | lock_success_ = true; 124 | } else { 125 | fprintf(stderr, "pthread trylock rwlock failed! the error num is %d\n", ret); 126 | } 127 | } 128 | } 129 | 130 | ~WriteLockGuard() { 131 | int ret = pthread_rwlock_unlock(&rwlock_); 132 | if (0 != ret) { 133 | fprintf(stderr, "pthread unlock rwlock failed! the error num is %d\n", ret); 134 | } 135 | } 136 | 137 | bool IsSuccess() { 138 | return lock_success_; 139 | } 140 | private: 141 | pthread_rwlock_t& rwlock_; 142 | bool lock_success_; 143 | 144 | }; 145 | 146 | } // end of namespace libervpc 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | #endif //__PTHREAD_LOCK_H_ 161 | 162 | /* vim: set expandtab ts=4 sw=4 sts=4 tw=100: */ 163 | -------------------------------------------------------------------------------- /src/rpc_server/connection_timer_manager.h: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * 3 | * Copyright (c) 2016 aishuyu, Inc. All Rights Reserved 4 | * 5 | **************************************************************************/ 6 | 7 | 8 | 9 | /** 10 | * @file connection_timer_manager.h 11 | * @author aishuyu(asy5178@163.com) 12 | * @date 2016/03/08 23:39:34 13 | * @brief 14 | * 15 | **/ 16 | 17 | 18 | 19 | 20 | #ifndef __CONNECTION_TIMER_MANAGER_H 21 | #define __CONNECTION_TIMER_MANAGER_H 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | #include "rpc_heartbeat_server.h" 31 | #include "config_parser/config_parser.h" 32 | #include "util/pthread_mutex.h" 33 | #include "util/disallow_copy_and_assign.h" 34 | #include "util/thread.h" 35 | 36 | namespace libevrpc { 37 | 38 | 39 | struct ConnectionTimer { 40 | time_t start_time; 41 | time_t expire_time; 42 | int32_t fd; 43 | long running_version; 44 | pthread_t thread_id; 45 | std::string client_addr; 46 | 47 | // ConnectionTimer* next; 48 | }; 49 | 50 | typedef std::shared_ptr CT_PTR; 51 | 52 | typedef std::map CT_MAP; 53 | typedef std::unordered_map CT_HASH_MAP; 54 | typedef std::shared_ptr CT_MAP_PTR; 55 | typedef std::shared_ptr CT_HASH_MAP_PTR; 56 | 57 | typedef std::vector CTM_VEC; 58 | typedef std::shared_ptr CTM_VEC_PTR; 59 | typedef std::vector CTHM_VEC; 60 | typedef std::shared_ptr CTHM_VEC_PTR; 61 | 62 | typedef std::vector MUTEX_VEC; 63 | typedef std::shared_ptr MUTEX_VEC_PTR; 64 | 65 | typedef std::vector LIST; 66 | typedef std::shared_ptr LIST_PTR; 67 | typedef std::vector LIST_PTR_LIST; 68 | typedef std::shared_ptr LIST_PPTR; 69 | 70 | typedef std::unordered_set HASH_SET; 71 | typedef std::shared_ptr HASH_SET_PTR; 72 | 73 | const int32_t buckets_size = 60; 74 | 75 | class ConnectionTimerManager : public Thread { 76 | public: 77 | ~ConnectionTimerManager(); 78 | 79 | static ConnectionTimerManager& GetInstance(const char* config_file); 80 | /* 81 | * every thread call InitTimerBuf once best, 82 | * otherwise make the connection_buf heavy! 83 | */ 84 | int32_t InitTimerBuf(); 85 | /* 86 | * every connection has come, PLEASE call, 87 | * otherwise the hearbeat is nothing to work 88 | */ 89 | int32_t InsertConnectionTimer( 90 | const std::string& ip_addr, 91 | int32_t fd, 92 | int32_t buf_index, 93 | long version, 94 | pthread_t thread_id); 95 | 96 | void DeleteConnectionTimer( 97 | const std::string& ip_addr, 98 | int32_t fd, 99 | int32_t buf_index); 100 | 101 | bool InsertRefreshConnectionInfo(std::string& ip_addr); 102 | 103 | virtual void Run(); 104 | 105 | private: 106 | ConnectionTimerManager(const char* config_file); 107 | 108 | std::string GenerateTimerKey(const std::string& ip_addr, int32_t fd); 109 | int32_t GenerateBucketNum(const std::string& ori_key); 110 | /* 111 | * background thread call 112 | */ 113 | bool ConnectionBufCrawler(); 114 | 115 | DISALLOW_COPY_AND_ASSIGN(ConnectionTimerManager); 116 | 117 | private: 118 | /* 119 | * in fact, is vector and thread no safe! 120 | * connection_buf_ptr : 121 | * one thread, on buf element 122 | * thread buf index -> hash map(connection key -> connection timer) 123 | */ 124 | CTHM_VEC_PTR connection_buf_ptr_; 125 | /* 126 | * one step, one time to update and refresh one buckets 127 | */ 128 | CT_MAP_PTR connection_pool_buckets_[buckets_size]; 129 | /* 130 | * connection_del_list_ptr_ : 131 | * one thread, one connection deleted list 132 | * thread index -> deleted list 133 | */ 134 | LIST_PPTR connection_del_list_ptr_; 135 | /* 136 | * contains all client address 137 | */ 138 | HASH_SET_PTR refresh_client_list_ptr_; 139 | 140 | MUTEX_VEC_PTR connection_buf_mutex_ptr_; 141 | MUTEX_VEC_PTR connection_bucket_mutex_ptr_; 142 | MUTEX_VEC_PTR connection_dellist_mutex_ptr_; 143 | ConfigParser& config_parser_instance_; 144 | 145 | RpcHeartbeatServer* rpc_heartbeat_server_ptr_; 146 | 147 | 148 | /* 149 | * buf_index_ : user to get the init index in order that multiThreads 150 | * call InitTimerBuf and get its buf index in connection_buf 151 | */ 152 | int32_t buf_index_; 153 | int32_t bucket_index_; 154 | int32_t refresh_interval_; 155 | 156 | volatile bool running_; 157 | Mutex connection_pool_mutex_; 158 | Mutex refresh_client_list_mutex_; 159 | 160 | }; 161 | 162 | } // end of namespace libevrpc 163 | 164 | 165 | #endif // __CONNECTION_TIMER_MANAGER_H 166 | 167 | 168 | 169 | /* vim: set expandtab ts=4 sw=4 sts=4 tw=100: */ 170 | -------------------------------------------------------------------------------- /src/Makefile.am: -------------------------------------------------------------------------------- 1 | AUTOMAKE_OPTIONS=foreign subdir-objects 2 | #SUBDIRS=rpc_client rpc_server cs_sample 3 | 4 | top_dir = ${top_srcdir}/.. 5 | src_dir = ${top_srcdir}/src 6 | config_dir = ${src_dir}/config_parser 7 | client_dir = ${src_dir}/rpc_client 8 | server_dir = ${src_dir}/rpc_server 9 | third_dir = ${top_dir}/third-64 10 | 11 | 12 | CLIENT_INCLUDES = \ 13 | rpc_client/rpc_client.h \ 14 | rpc_client/rpc_channel.h \ 15 | rpc_client/client_rpc_controller.h \ 16 | rpc_client/rpc_heartbeat_client.h 17 | 18 | CLIENT_SORCS = \ 19 | rpc_client/rpc_client.cpp \ 20 | rpc_client/rpc_channel.cpp \ 21 | rpc_client/client_rpc_controller.cpp \ 22 | rpc_client/rpc_heartbeat_client.cpp 23 | 24 | SERVER_INCLUDES = \ 25 | rpc_server/rpc_server.h \ 26 | rpc_server/dispatch_thread.h \ 27 | rpc_server/libev_thread_pool.h \ 28 | rpc_server/server_rpc_controller.h \ 29 | rpc_server/connection_timer_manager.h \ 30 | rpc_server/center_cluster_heartbeat.h \ 31 | rpc_server/rpc_heartbeat_server.h 32 | 33 | SERVER_SRCS = \ 34 | rpc_server/rpc_server.cpp \ 35 | rpc_server/dispatch_thread.cpp \ 36 | rpc_server/libev_thread_pool.cpp \ 37 | rpc_server/server_rpc_controller.cpp \ 38 | rpc_server/connection_timer_manager.cpp \ 39 | rpc_server/center_cluster_heartbeat.cpp \ 40 | rpc_server/rpc_heartbeat_server.cpp 41 | 42 | 43 | CENTER_INCLUDES = \ 44 | rpc_center/rpc_center.h \ 45 | rpc_center/center_server_thread.h \ 46 | rpc_center/election_thread.h \ 47 | rpc_center/leader_thread.h \ 48 | rpc_center/load_balancer/load_balancer.h \ 49 | rpc_center/load_balancer/consistent_hash_load_balancer.h \ 50 | rpc_center/reporter_thread.h \ 51 | center_proto/centers.pb.h \ 52 | center_proto/center_type.pb.h \ 53 | center_proto/center_client.pb.h \ 54 | center_proto/center_cluster.pb.h \ 55 | ${COMMON_INCLUDES} 56 | 57 | 58 | CENTER_SRCS = \ 59 | rpc_center/rpc_center.cpp \ 60 | rpc_center/center_server_thread.cpp \ 61 | rpc_center/election_thread.cpp \ 62 | rpc_center/leader_thread.cpp \ 63 | rpc_center/reporter_thread.cpp \ 64 | rpc_center/load_balancer/consistent_hash_load_balancer.cpp\ 65 | center_proto/centers.pb.cc \ 66 | center_proto/center_type.pb.cc \ 67 | center_proto/center_client.pb.cc \ 68 | center_proto/center_cluster.pb.cc \ 69 | ${COMMON_SRCS} 70 | 71 | 72 | COMMON_INCLUDES = \ 73 | config_parser/config_parser.h \ 74 | config_parser/dictionary.h \ 75 | config_parser/iniparser.h \ 76 | util/rpc_util.h \ 77 | util/thread.h \ 78 | util/disallow_copy_and_assign.h \ 79 | util/rpc_communication.h \ 80 | util/pthread_mutex.h \ 81 | util/pthread_rwlock.h 82 | 83 | COMMON_SRCS = \ 84 | config_parser/config_parser.cpp \ 85 | config_parser/dictionary.cpp \ 86 | config_parser/iniparser.cpp \ 87 | util/rpc_util.cpp \ 88 | util/rpc_communication.cpp 89 | 90 | 91 | nobase_include_HEADERS = \ 92 | ${CLIENT_INCLUDES} \ 93 | ${SERVER_INCLUDES} \ 94 | ${COMMON_INCLUDES} 95 | 96 | 97 | lib_LTLIBRARIES = librpc_client.la librpc_server.la 98 | 99 | librpc_client_la_CPPFLAGS = \ 100 | -I${top_srcdir}/src \ 101 | -I${third_dir}/gperftools/include/ \ 102 | -I${third_dir}/protobuf/include/ 103 | librpc_client_la_LIBADD = \ 104 | #${third_dir}/gperftools/lib/libtcmalloc_minimal.a \ 105 | ${third_dir}/protobuf/lib/*.a 106 | librpc_client_la_LDFLAGS = -lz -std=c++11 107 | librpc_client_la_SOURCES = \ 108 | ${CLIENT_SORCS} \ 109 | ${COMMON_SRCS} 110 | 111 | 112 | librpc_server_la_CPPFLAGS = \ 113 | -I${top_srcdir}/src \ 114 | -I${third_dir}/gperftools/include/ \ 115 | -I${third_dir}/protobuf/include/ \ 116 | -I${third_dir}/libev/include/ 117 | librpc_server_la_LIBADD = \ 118 | #${third_dir}/gperftools/lib/libtcmalloc_minimal.a \ 119 | ${third_dir}/protobuf/lib/*.a \ 120 | ${third_dir}/libev/lib/*.a 121 | librpc_server_la_LDFLAGS = -lz -std=c++11 122 | librpc_server_la_SOURCES = \ 123 | ${SERVER_SRCS} \ 124 | ${COMMON_SRCS} 125 | 126 | 127 | AM_LDFLAGS = -lz -lm -lpthread -std=c++11 #-lprotobuf -lrt 128 | #AM_LDFLAGS = -lz -lm -lpthread -std=c++11 129 | bin_PROGRAMS = rpc_center_server 130 | rpc_center_server_SOURCES = rpc_center/rpc_center_server.cc ${CENTER_INCLUDES} ${CENTER_SRCS} 131 | rpc_center_server_LDADD = ${third_dir}/protobuf/lib/*.a ${third_dir}/libev/lib/*.a 132 | INCLUDES = -I${top_srcdir}/src \ 133 | -I${third_dir}/gperftools/include/ \ 134 | -I${third_dir}/protobuf/include/ \ 135 | -I${third_dir}/libev/include/ \ 136 | -I${top_srcdir}/src/center_proto/ 137 | 138 | -------------------------------------------------------------------------------- /src/rpc_center/center_server_thread.cpp: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * 3 | * Copyright (c) 2016 aishuyu, Inc. All Rights Reserved 4 | * 5 | **************************************************************************/ 6 | 7 | 8 | 9 | /** 10 | * @file center_server_thread.cpp 11 | * @author aishuyu(asy5178@163.com) 12 | * @date 2016/07/17 02:31:37 13 | * @brief 14 | * 15 | **/ 16 | 17 | #include "center_server_thread.h" 18 | 19 | #include "rpc_center.h" 20 | #include "util/rpc_communication.h" 21 | 22 | 23 | namespace libevrpc { 24 | 25 | using std::string; 26 | 27 | int32_t CenterServerThread::ei_per_alloc_ = 4; 28 | CenterEioQueue CenterServerThread::eio_uselist_ = {NULL, NULL}; 29 | 30 | CenterServerThread::CenterServerThread( 31 | const char* local_center, 32 | const char* server_port) : 33 | local_center_(NULL), 34 | center_port_(NULL), 35 | epoller_(NULL) { 36 | 37 | local_center_ = (char*)malloc(strlen(local_center)); 38 | center_port_ = (char*)malloc(strlen(server_port)); 39 | 40 | strcpy(local_center_, local_center); 41 | strcpy(center_port_, server_port); 42 | } 43 | 44 | CenterServerThread::~CenterServerThread() { 45 | if (NULL != local_center_) { 46 | free(local_center_); 47 | } 48 | 49 | if (NULL != center_port_) { 50 | free(center_port_); 51 | } 52 | 53 | if (NULL != epoller_) { 54 | ev_loop_destroy(epoller_); 55 | } 56 | } 57 | 58 | bool CenterServerThread::InitCenterServer() { 59 | int32_t listenfd = TcpListen(local_center_, center_port_); 60 | if (listenfd < 0) { 61 | fprintf(stderr, "Center Listen Server Init failed!\n"); 62 | return false; 63 | } 64 | epoller_ = ev_loop_new(EVBACKEND_EPOLL | EVFLAG_NOENV); 65 | if (NULL == epoller_) { 66 | fprintf(stderr,"Center new epoller failed!\n"); 67 | return false; 68 | } 69 | 70 | socket_watcher_.data = this; 71 | /* 72 | * 初始启动 Accept epoller事件 负责接收请求 73 | */ 74 | ev_io_init(&socket_watcher_, CenterServerThread::AcceptCb, listenfd, EV_READ); 75 | ev_io_start(epoller_, &socket_watcher_); 76 | 77 | return true; 78 | } 79 | 80 | void CenterServerThread::Run() { 81 | if (!InitCenterServer()) { 82 | fprintf(stderr, "Center epoller is NULL\n"); 83 | return; 84 | } 85 | if (NULL == epoller_) { 86 | fprintf(stderr, "Center epoller is NULL\n"); 87 | return; 88 | } 89 | ev_run(epoller_, 0); 90 | ev_loop_destroy(epoller_); 91 | epoller_ = NULL; 92 | } 93 | 94 | void CenterServerThread::AcceptCb(struct ev_loop *loop, struct ev_io *watcher, int revents) { 95 | if (NULL == loop) { 96 | fprintf(stderr, "Center Ev loop ptr is null!\n"); 97 | return; 98 | } 99 | 100 | if (EV_ERROR & revents) { 101 | fprintf(stderr, "Center EV_ERROR in AcceptCb\n"); 102 | return; 103 | } 104 | 105 | struct sockaddr_in client_addr; 106 | socklen_t len = sizeof(struct sockaddr_in); 107 | int32_t cfd = Accept(watcher->fd, client_addr, len); 108 | if (cfd < 0) { 109 | fprintf(stderr, "Center Accept failed!\n"); 110 | return; 111 | } 112 | 113 | /* 114 | * 初始化启动处理epoller事件 115 | */ 116 | CenterServerThread* cst = (CenterServerThread*)(watcher->data); 117 | CEIO_ITEM *eio_item = cst->NewCEIO(); 118 | struct ev_io& client_eio = eio_item->eio; 119 | client_eio.data = watcher->data; 120 | ev_io_init(&client_eio, CenterServerThread::Processor, cfd, EV_READ); 121 | ev_io_start(loop, &client_eio); 122 | PushCEIO(eio_uselist_, eio_item); 123 | } 124 | 125 | void CenterServerThread::Processor(struct ev_loop *loop, struct ev_io *watcher, int revents) { 126 | if (EV_ERROR & revents) { 127 | fprintf(stderr, "EV_ERROR in AcceptCb callback!\n"); 128 | return; 129 | } 130 | RpcCenter::GetInstance(g_config_file).CenterProcessor(watcher->fd); 131 | /* 132 | * 每一次执行结束, 关闭链接 133 | */ 134 | close(watcher->fd); 135 | ev_io_stop(loop, watcher); 136 | CEIO_ITEM* ci = PopCEIO(eio_uselist_); 137 | CenterServerThread* cst_ptr = (CenterServerThread*)(watcher->data); 138 | cst_ptr->FreeCEIO(ci); 139 | } 140 | 141 | CEIO_ITEM* CenterServerThread::NewCEIO() { 142 | CEIO_ITEM* ei = NULL; 143 | if (NULL != eio_freelist_) { 144 | ei = eio_freelist_; 145 | eio_freelist_ = eio_freelist_->next; 146 | } 147 | if (NULL == ei) { 148 | ei = (CEIO_ITEM*)malloc(sizeof(CEIO_ITEM) * ei_per_alloc_); 149 | if (NULL == ei) { 150 | fprintf(stderr, "Center error, Alloc the ei item mem failed!\n"); 151 | return NULL; 152 | } 153 | for (int i = 0; i < ei_per_alloc_; ++i) { 154 | ei[i - 1].next = &ei[i]; 155 | } 156 | ei[ei_per_alloc_ - 1].next = NULL; 157 | ei[ei_per_alloc_ - 1].next = eio_freelist_; 158 | eio_freelist_ = &ei[1]; 159 | } 160 | return ei; 161 | } 162 | 163 | void CenterServerThread::FreeCEIO(CEIO_ITEM* eio_item) { 164 | eio_item->next = eio_freelist_; 165 | eio_freelist_ = eio_item; 166 | } 167 | 168 | void CenterServerThread::PushCEIO(CenterEioQueue& eq, CEIO_ITEM* eio_item) { 169 | eio_item->next = NULL; 170 | if (NULL == eq.tail) { 171 | eq.head = eio_item; 172 | } else { 173 | eq.tail->next = eio_item; 174 | } 175 | eq.tail = eio_item; 176 | } 177 | 178 | CEIO_ITEM* CenterServerThread::PopCEIO(CenterEioQueue& eq) { 179 | CEIO_ITEM* ei = NULL; 180 | ei = eq.head; 181 | if (NULL != ei) { 182 | eq.head = ei->next; 183 | if (NULL == eq.head) { 184 | eq.tail = NULL; 185 | } 186 | } 187 | return ei; 188 | } 189 | 190 | } // end of namespace libevrpc 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | /* vim: set expandtab ts=4 sw=4 sts=4 tw=100: */ 200 | -------------------------------------------------------------------------------- /src/rpc_server/dispatch_thread.cpp: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * 3 | * Copyright (c) 2015 aishuyu, Inc. All Rights Reserved 4 | * 5 | **************************************************************************/ 6 | 7 | 8 | 9 | /** 10 | * @file dispatch_thread.cpp 11 | * @author aishuyu(asy5178@163.com) 12 | * @date 2015/12/31 00:15:08 13 | * @brief 14 | * 15 | **/ 16 | 17 | #include "dispatch_thread.h" 18 | 19 | #include "util/rpc_communication.h" 20 | #include "util/rpc_util.h" 21 | 22 | namespace libevrpc { 23 | 24 | int32_t DispatchThread::ei_per_alloc_ = 4; 25 | EioQueue DispatchThread::eio_uselist_ = {NULL, NULL}; 26 | 27 | DispatchThread::DispatchThread() : epoller_(NULL), eio_freelist_(NULL) { 28 | } 29 | 30 | DispatchThread::~DispatchThread() { 31 | Stop(); 32 | Wait(); 33 | if (NULL != epoller_) { 34 | ev_loop_destroy(epoller_); 35 | } 36 | if (NULL != eio_freelist_) { 37 | for (EIO_ITEM* eif = eio_freelist_->next; eio_freelist_ != NULL; ) { 38 | free(eio_freelist_); 39 | eio_freelist_ = NULL; 40 | eio_freelist_ = eif; 41 | if (NULL != eif) { 42 | eif = eif->next; 43 | } 44 | } 45 | } 46 | EioQueue& eul = DispatchThread::eio_uselist_; 47 | for (EIO_ITEM* eiptr = eul.head ; eiptr != eul.tail && eiptr != NULL; ) { 48 | eul.head = eiptr->next; 49 | free(eiptr); 50 | eiptr = eul.head; 51 | } 52 | } 53 | 54 | bool DispatchThread::InitializeService( 55 | const char *host, 56 | const char *port, 57 | RpcCallBackPtr cb, 58 | void *arg) { 59 | /* 60 | * copy the callback function to mem callback_ 61 | */ 62 | cb_ptr_ = cb; 63 | cb_arg_ = arg; 64 | 65 | int32_t listenfd = TcpListen(host, port); 66 | if (listenfd < 0) { 67 | PrintErrorInfo("Rpc server listen current port failed\n"); 68 | return false; 69 | } 70 | 71 | epoller_ = ev_loop_new(EVBACKEND_EPOLL | EVFLAG_NOENV); 72 | // epoller_ = ev_loop_new(0); 73 | 74 | if (NULL == epoller_) { 75 | PrintErrorInfo("Call ev_loop_new failed!\n"); 76 | return false; 77 | } 78 | 79 | /* 80 | * set callback AcceptCb, Note the function AcceptCb must be static function 81 | */ 82 | socket_watcher_.data = this; 83 | ev_io_init(&socket_watcher_, DispatchThread::AcceptCb, listenfd, EV_READ); 84 | ev_io_start(epoller_, &socket_watcher_); 85 | 86 | return true; 87 | } 88 | 89 | /* 90 | * start to run 91 | */ 92 | void DispatchThread::Run() { 93 | if (NULL == epoller_) { 94 | PrintErrorInfo("The epoller ptr is null!\n"); 95 | return; 96 | } 97 | ev_run(epoller_, 0); 98 | ev_loop_destroy(epoller_); 99 | epoller_ = NULL; 100 | } 101 | 102 | void DispatchThread::AcceptCb(struct ev_loop *loop, struct ev_io *watcher, int revents) { 103 | if (NULL == loop) { 104 | PrintErrorInfo("Ev loop ptr is null!\n"); 105 | return; 106 | } 107 | 108 | if (EV_ERROR & revents) { 109 | PrintErrorInfo("EV_ERROR in AcceptCb callback!\n"); 110 | return; 111 | } 112 | struct sockaddr_in client_addr; 113 | socklen_t len = sizeof(struct sockaddr_in); 114 | int32_t cfd = Accept(watcher->fd, client_addr, len); 115 | if (cfd < 0) { 116 | PrintErrorInfo("Accept connection failed!"); 117 | return; 118 | } 119 | 120 | DispatchThread* dt = (DispatchThread*)(watcher->data); 121 | EIO_ITEM *eio_item = dt->NewEIO(); 122 | struct ev_io& client_eio = eio_item->eio; 123 | client_eio.data = watcher->data; 124 | ev_io_init(&client_eio, DispatchThread::ProcessCb, cfd, EV_READ); 125 | ev_io_start(loop, &client_eio); 126 | PushEIO(eio_uselist_, eio_item); 127 | } 128 | 129 | /* 130 | * handle the connection and callback 131 | */ 132 | void DispatchThread::ProcessCb(struct ev_loop *loop, struct ev_io *watcher, int revents) { 133 | if (EV_ERROR & revents) { 134 | PrintErrorInfo("EV_ERROR in AcceptCb callback!\n"); 135 | return; 136 | } 137 | DispatchThread* dt = (DispatchThread*)(watcher->data); 138 | dt->cb_ptr_(watcher->fd, dt->cb_arg_); 139 | ev_io_stop(loop, watcher); 140 | EIO_ITEM* ei = PopEIO(eio_uselist_); 141 | dt->FreeEIO(ei); 142 | } 143 | 144 | EIO_ITEM* DispatchThread::NewEIO() { 145 | EIO_ITEM* ei = NULL; 146 | if (NULL != eio_freelist_) { 147 | ei = eio_freelist_; 148 | eio_freelist_ = eio_freelist_->next; 149 | } 150 | if (NULL == ei) { 151 | ei = (EIO_ITEM*)malloc(sizeof(EIO_ITEM) * ei_per_alloc_); 152 | if (NULL == ei) { 153 | PrintErrorInfo("Alloc the ei item mem failed!"); 154 | return NULL; 155 | } 156 | for (int i = 0; i < ei_per_alloc_; ++i) { 157 | ei[i - 1].next = &ei[i]; 158 | } 159 | ei[ei_per_alloc_ - 1].next = NULL; 160 | ei[ei_per_alloc_ - 1].next = eio_freelist_; 161 | eio_freelist_ = &ei[1]; 162 | } 163 | return ei; 164 | } 165 | 166 | void DispatchThread::FreeEIO(EIO_ITEM* eio_item) { 167 | eio_item->next = eio_freelist_; 168 | eio_freelist_ = eio_item; 169 | } 170 | 171 | void DispatchThread::PushEIO(EioQueue& eq, EIO_ITEM* eio_item) { 172 | eio_item->next = NULL; 173 | if (NULL == eq.tail) { 174 | eq.head = eio_item; 175 | } else { 176 | eq.tail->next = eio_item; 177 | } 178 | eq.tail = eio_item; 179 | } 180 | 181 | EIO_ITEM* DispatchThread::PopEIO(EioQueue& eq) { 182 | EIO_ITEM* ei = NULL; 183 | ei = eq.head; 184 | if (NULL != ei) { 185 | eq.head = ei->next; 186 | if (NULL == eq.head) { 187 | eq.tail = NULL; 188 | } 189 | } 190 | return ei; 191 | } 192 | 193 | 194 | } // end of namespace libevrpc 195 | 196 | 197 | 198 | 199 | 200 | 201 | /* vim: set expandtab ts=4 sw=4 sts=4 tw=100: */ 202 | -------------------------------------------------------------------------------- /src/rpc_server/center_cluster_heartbeat.cpp: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * 3 | * Copyright (c) 2016 aishuyu, Inc. All Rights Reserved 4 | * 5 | **************************************************************************/ 6 | 7 | 8 | 9 | /** 10 | * @file center_cluster_heartbeat.cpp 11 | * @author aishuyu(asy5178@163.com) 12 | * @date 2016/09/07 19:44:39 13 | * @brief 14 | * 15 | **/ 16 | 17 | #include "center_cluster_heartbeat.h" 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | #include 26 | 27 | #include "center_proto/center_cluster.pb.h" 28 | #include "config_parser/config_parser.h" 29 | #include "util/rpc_communication.h" 30 | #include "util/rpc_util.h" 31 | 32 | #if defined(__linux__) 33 | #include 34 | #include 35 | #elif defined(__osx__) 36 | #include 37 | #endif 38 | 39 | #define random(x) (rand()%x) 40 | 41 | 42 | namespace libevrpc { 43 | 44 | using ::google::protobuf::RepeatedPtrField; 45 | using std::string; 46 | 47 | const int32_t sleep_time = 10; 48 | 49 | CenterClusterHeartbeat::CenterClusterHeartbeat(const string& config_file) : 50 | config_file_(config_file), 51 | center_addrs_ptr_(new ADDRS_LIST_TYPE()), 52 | reporter_center_addrs_ptr_(new ADDRS_LIST_TYPE()), 53 | running_(false), 54 | center_port_(NULL) { 55 | } 56 | 57 | CenterClusterHeartbeat::~CenterClusterHeartbeat() { 58 | if (NULL != center_addrs_ptr_) { 59 | delete center_addrs_ptr_; 60 | } 61 | 62 | if (NULL != reporter_center_addrs_ptr_) { 63 | delete reporter_center_addrs_ptr_; 64 | } 65 | 66 | if (NULL != center_port_) { 67 | free(center_port_); 68 | } 69 | } 70 | 71 | bool CenterClusterHeartbeat::InitCenterClusterHB() { 72 | const string cfile = "/tmp/centers.data"; 73 | int ftyp = access(cfile.c_str(), 0); 74 | if (0 != ftyp) { 75 | /* 76 | * 需要的服务器列表文件不存在,无法初始化后与其他机器进行通信 77 | * 启动失败!!! 78 | */ 79 | return false; 80 | } 81 | const char* center_port = ConfigParser::GetInstance(config_file_).IniGetString("rpc_center:port", "8899"); 82 | strcpy(center_port_ = (char*)malloc(strlen(center_port) + 1), center_port); 83 | 84 | std::ifstream in(cfile); 85 | string line; 86 | 87 | const char* local_addr = GetLocalAddress(); 88 | while (getline (in, line)) { 89 | // FOR test to remove 90 | if (strcmp(line.c_str(), local_addr) == 0) { 91 | continue; 92 | } 93 | center_addrs_ptr_->push_back(line); 94 | } 95 | 96 | int32_t cl_size = center_addrs_ptr_->size(); 97 | if (0 == cl_size) { 98 | fprintf(stderr, "The center addrs list is empty!\n"); 99 | return false; 100 | } 101 | 102 | int32_t random_index = random(cl_size); 103 | int32_t conn_fd = TcpConnect(center_addrs_ptr_->at(random_index).c_str(), center_port_, 15); 104 | if (conn_fd <= 0) { 105 | return false; 106 | } 107 | 108 | /* 109 | * 在RpcCenter注册本地RpcServer, 获取Report机器地址 110 | */ 111 | RpcClusterServer rcs; 112 | rcs.set_cluster_action(REGISTER); 113 | rcs.set_cluster_server_addr(local_addr); 114 | 115 | string rcs_str; 116 | if (!rcs.SerializeToString(&rcs_str)) { 117 | close(conn_fd); 118 | return false; 119 | } 120 | if (RpcSend(conn_fd, CENTER2CLUSTER, rcs_str, false < 0)) { 121 | fprintf(stderr, "Cluster send info to Center failed!\n"); 122 | close(conn_fd); 123 | return false; 124 | } 125 | 126 | string crc_str; 127 | if (RpcRecv(conn_fd, crc_str, true) < 0) { 128 | close(conn_fd); 129 | return false; 130 | } 131 | 132 | CenterResponseCluster crc_proto; 133 | if (!crc_proto.ParseFromString(crc_str)) { 134 | close(conn_fd); 135 | return false; 136 | } 137 | 138 | RepeatedPtrField* reporter_centers = crc_proto.mutable_should_reporter_center(); 139 | for (RepeatedPtrField::iterator iter = reporter_centers->begin(); 140 | iter != reporter_centers->end(); 141 | ++iter) { 142 | reporter_center_addrs_ptr_->push_back(std::move(*iter)); 143 | } 144 | 145 | running_ = true; 146 | return true; 147 | } 148 | 149 | void CenterClusterHeartbeat::Run() { 150 | 151 | if (!InitCenterClusterHB()) { 152 | fprintf(stderr, "Center Init HeartBeat failed!\n"); 153 | return; 154 | } 155 | int32_t rca_size = reporter_center_addrs_ptr_->size(); 156 | 157 | if (0 == rca_size) { 158 | fprintf(stderr, "Reporter center_addrs list is empty!\n"); 159 | return; 160 | } 161 | 162 | int32_t random_index = random(rca_size); 163 | 164 | int32_t should_reinit = ConfigParser::GetInstance(config_file_).IniGetInt("rpc_center:should_reinit", 10); 165 | int32_t reinit_cnt = 0; 166 | while (running_) { 167 | /** 168 | * 获取本地机器信息 CPU LOAD1等 169 | */ 170 | RpcClusterServer rcs_proto; 171 | rcs_proto.set_cluster_action(CLUSTER_PING); 172 | rcs_proto.set_cluster_server_addr(GetLocalAddress()); 173 | 174 | #if defined(__linux__) 175 | struct sysinfo s_info; 176 | int32_t error_no = sysinfo(&s_info); 177 | if (error_no < 0) { 178 | /* 179 | * 获取本地机器信息失败 180 | */ 181 | continue; 182 | } 183 | rcs_proto.set_load(s_info.loads[0]); 184 | #endif 185 | string rcs_str; 186 | if (!rcs_proto.SerializeToString(&rcs_str)) { 187 | continue; 188 | } 189 | 190 | int32_t conn_fd = TcpConnect(reporter_center_addrs_ptr_->at(random_index).c_str(), center_port_, 15); 191 | if (conn_fd < 0) { 192 | ++reinit_cnt; 193 | if (reinit_cnt > should_reinit) { 194 | reinit_cnt = 0; 195 | InitCenterClusterHB(); 196 | } 197 | random_index = random(rca_size); 198 | sleep(sleep_time); 199 | continue; 200 | } 201 | 202 | 203 | if (RpcSend(conn_fd, CENTER2CLUSTER, rcs_str, true) < 0) { 204 | fprintf(stderr, "Send info to Center failed!\n"); 205 | } 206 | sleep(5); 207 | } 208 | } 209 | 210 | 211 | } // end of namespace libevrpc 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | /* vim: set expandtab ts=4 sw=4 sts=4 tw=100: */ 229 | -------------------------------------------------------------------------------- /src/rpc_center/rpc_center.h: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * 3 | * Copyright (c) 2016 aishuyu, Inc. All Rights Reserved 4 | * 5 | **************************************************************************/ 6 | 7 | 8 | 9 | /** 10 | * @file rpc_center.h 11 | * @author aishuyu(asy5178@163.com) 12 | * @date 2016/07/12 20:33:03 13 | * @brief 14 | * 15 | **/ 16 | 17 | 18 | 19 | 20 | #ifndef __RPC_CENTER_H 21 | #define __RPC_CENTER_H 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | #include "center_server_thread.h" 30 | #include "election_thread.h" 31 | #include "reporter_thread.h" 32 | #include "leader_thread.h" 33 | #include "rpc_center/load_balancer/load_balancer.h" 34 | #include "center_proto/centers.pb.h" 35 | #include "center_proto/center_cluster.pb.h" 36 | #include "config_parser/config_parser.h" 37 | #include "util/disallow_copy_and_assign.h" 38 | #include "util/pthread_rwlock.h" 39 | 40 | namespace libevrpc { 41 | 42 | class RpcCenter; 43 | struct OtherCenter { 44 | time_t start_time; 45 | CenterStatus center_status; 46 | uint32_t vote_count; 47 | char current_follow_leader_center[128]; 48 | }; 49 | 50 | struct LeaderInfos { 51 | /* 52 | * lc: leader center 53 | */ 54 | time_t lc_start_time; 55 | std::string leader_center; 56 | }; 57 | 58 | class ServerSetHash { 59 | public: 60 | size_t operator()(const RpcClusterServer& rcs) const { 61 | return std::hash{}(rcs.cluster_server_addr()); 62 | } 63 | }; 64 | 65 | class ServerSetCmp { 66 | public: 67 | bool operator()(const RpcClusterServer& rcs1, const RpcClusterServer& rcs2) const { 68 | return rcs1.cluster_server_addr() == rcs2.cluster_server_addr(); 69 | } 70 | }; 71 | 72 | typedef std::shared_ptr OCPTR; 73 | typedef std::unordered_map HashMap; 74 | typedef std::unordered_map CountMap; 75 | typedef std::map CENTER_HASH_MAP; 76 | typedef std::unordered_set SERVER_SET; 77 | 78 | extern std::string g_config_file; 79 | 80 | class RpcCenter { 81 | public: 82 | ~RpcCenter(); 83 | 84 | static RpcCenter& GetInstance(const std::string& config_file); 85 | 86 | bool InitRpcCenter(); 87 | bool StartCenter(); 88 | bool StopCenter(); 89 | void WaitCenter(); 90 | 91 | void UpdateCenterStatus(CenterStatus cs); 92 | bool UpdateOCStatus(const CentersProto& centers_proto); 93 | void UpdateLeadingCenterInfos(const CentersProto& centers_proto); 94 | void IncreaseLogicalClock(); 95 | 96 | CenterStatus GetLocalCenterStatus(); 97 | time_t GetOCStartTime(const std::string& leader_center); 98 | std::string GetLeadingCenter(); 99 | time_t GetLeadingCenterStartTime(); 100 | unsigned long GetLogicalClock(); 101 | CenterStatus GetCenterStatus(); 102 | 103 | /* 104 | * FastLeaderElection算法 选举出 RPC Center集群的Leader 105 | */ 106 | bool FastLeaderElection(); 107 | /* 108 | * 群发信息,询问各个机器,获取各个Center机器的信息 109 | */ 110 | bool InquiryCenters(); 111 | /* 112 | * 发起Proposal 113 | */ 114 | bool ProposalLeaderElection(); 115 | /* 116 | * 判断新的Proposal数据进行预判,是否需要更新本地Leader信息 117 | */ 118 | CenterAction LeaderPredicate(const CentersProto& centers_proto); 119 | /* 120 | * 中心服务机器处理,服务于其他中心机器,RPC客户端,RPC集群 121 | */ 122 | bool CenterProcessor(int32_t conn_fd); 123 | 124 | bool ProcessCenterData(int32_t fd, const CentersProto& centers_proto); 125 | /* 126 | * 开始FastLeaderElection,同时启动Election线程 127 | */ 128 | bool StartFastLeaderElection(); 129 | /** 130 | * 标示判决FastLeaderElection是否在运行 131 | */ 132 | void SetFastLeaderRunning(bool is_running); 133 | 134 | bool ReporterProcessor(int32_t conn_fd); 135 | 136 | private: 137 | RpcCenter(const std::string& config_file); 138 | 139 | bool BroadcastInfo(std::string& bc_info); 140 | 141 | bool IsFastLeaderRunning(); 142 | 143 | bool RegistNewCenter(const std::string& new_center); 144 | 145 | bool CenterIsReady(); 146 | 147 | bool AddRpcServerToBuf(const RpcClusterServer& rpc_cluster_server); 148 | 149 | // 处理各个服务器还请求函数 150 | bool ProcessCenterRequest(const std::string& recv_message, int32_t fd); 151 | bool ProcessClientRequest(const std::string& recv_message, int32_t fd); 152 | bool ProcessClusterRequest(const std::string& recv_message, int32_t fd); 153 | 154 | private: 155 | /* 156 | * Center服务器统一端口 157 | */ 158 | char* center_port_; 159 | /* 160 | * 读取配置文件使用 161 | */ 162 | ConfigParser& config_parser_instance_; 163 | /* 164 | * 当前Center机器的状态,服务启动时间,当前LeaderCenter信息, 165 | */ 166 | CenterStatus center_status_; 167 | time_t start_time_; 168 | LeaderInfos* leader_infos_ptr_; 169 | 170 | /* 171 | * 记录其他Center服务器状态 172 | */ 173 | HashMap* other_centers_ptr_; 174 | 175 | /* 176 | * 选举生效票数 177 | */ 178 | uint32_t election_done_num_; 179 | /* 180 | * 投票轮次,启动时候为最小,与其他Center服务器通信时候 以最大 181 | * 投票轮次为准 182 | */ 183 | unsigned long logical_clock_; 184 | /* 185 | * FastLeaderElection算法是否在运行,主要防止多线程同时运行,运行两次FastLeaderElection 186 | */ 187 | bool fastleader_election_running_; 188 | 189 | /* 190 | * 各种RWLock 191 | */ 192 | RWLock status_rwlock_; 193 | RWLock oc_rwlock_; 194 | RWLock lc_rwlock_; 195 | RWLock logical_clock_rwlock_; 196 | RWLock fle_running_rwlock_; 197 | RWLock center_hash_map_rwlock_; 198 | RWLock rpc_server_buf_rwlock_; 199 | 200 | /* 201 | * 各种线程 202 | */ 203 | CenterServerThread* center_server_thread_; 204 | ElectionThread* election_thread_; 205 | ReporterThread* reporter_thread_; 206 | LeaderThread* leader_thread_; 207 | 208 | /* 209 | * 负载均衡插件 210 | */ 211 | LoadBalancer* load_balancer_ptr_; 212 | 213 | /* 214 | * Center机器Hash表 215 | */ 216 | CENTER_HASH_MAP* center_hash_map_ptr_; 217 | /* 218 | * 记录前来注册的机器地址列表 219 | */ 220 | SERVER_SET* rpc_server_buf_ptr_; 221 | 222 | DISALLOW_COPY_AND_ASSIGN(RpcCenter); 223 | }; 224 | 225 | 226 | 227 | } // end of namespace 228 | 229 | 230 | 231 | #endif // __RPC_CENTER_H 232 | 233 | 234 | 235 | /* vim: set expandtab ts=4 sw=4 sts=4 tw=100: */ 236 | -------------------------------------------------------------------------------- /src/config_parser/dictionary.h: -------------------------------------------------------------------------------- 1 | 2 | /*-------------------------------------------------------------------------*/ 3 | /** 4 | @file dictionary.h 5 | @author N. Devillard 6 | @brief Implements a dictionary for string variables. 7 | 8 | This module implements a simple dictionary object, i.e. a list 9 | of string/string associations. This object is useful to store e.g. 10 | informations retrieved from a configuration file (ini files). 11 | */ 12 | /*--------------------------------------------------------------------------*/ 13 | 14 | #ifndef _DICTIONARY_H_ 15 | #define _DICTIONARY_H_ 16 | 17 | /*--------------------------------------------------------------------------- 18 | Includes 19 | ---------------------------------------------------------------------------*/ 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | namespace libevrpc { 27 | 28 | #ifdef __cplusplus 29 | extern "C" { 30 | #endif 31 | 32 | 33 | /*--------------------------------------------------------------------------- 34 | New types 35 | ---------------------------------------------------------------------------*/ 36 | 37 | 38 | /*-------------------------------------------------------------------------*/ 39 | /** 40 | @brief Dictionary object 41 | 42 | This object contains a list of string/string associations. Each 43 | association is identified by a unique string key. Looking up values 44 | in the dictionary is speeded up by the use of a (hopefully collision-free) 45 | hash function. 46 | */ 47 | /*-------------------------------------------------------------------------*/ 48 | typedef struct _dictionary_ { 49 | int n ; /** Number of entries in dictionary */ 50 | int size ; /** Storage size */ 51 | char ** val ; /** List of string values */ 52 | char ** key ; /** List of string keys */ 53 | unsigned * hash ; /** List of hash values for keys */ 54 | } dictionary ; 55 | 56 | 57 | /*--------------------------------------------------------------------------- 58 | Function prototypes 59 | ---------------------------------------------------------------------------*/ 60 | 61 | /*-------------------------------------------------------------------------*/ 62 | /** 63 | @brief Compute the hash key for a string. 64 | @param key Character string to use for key. 65 | @return 1 unsigned int on at least 32 bits. 66 | 67 | This hash function has been taken from an Article in Dr Dobbs Journal. 68 | This is normally a collision-free function, distributing keys evenly. 69 | The key is stored anyway in the struct so that collision can be avoided 70 | by comparing the key itself in last resort. 71 | */ 72 | /*--------------------------------------------------------------------------*/ 73 | unsigned dictionary_hash(const char * key); 74 | 75 | /*-------------------------------------------------------------------------*/ 76 | /** 77 | @brief Create a new dictionary object. 78 | @param size Optional initial size of the dictionary. 79 | @return 1 newly allocated dictionary objet. 80 | 81 | This function allocates a new dictionary object of given size and returns 82 | it. If you do not know in advance (roughly) the number of entries in the 83 | dictionary, give size=0. 84 | */ 85 | /*--------------------------------------------------------------------------*/ 86 | dictionary * dictionary_new(size_t size); 87 | 88 | /*-------------------------------------------------------------------------*/ 89 | /** 90 | @brief Delete a dictionary object 91 | @param d dictionary object to deallocate. 92 | @return void 93 | 94 | Deallocate a dictionary object and all memory associated to it. 95 | */ 96 | /*--------------------------------------------------------------------------*/ 97 | void dictionary_del(dictionary * vd); 98 | 99 | /*-------------------------------------------------------------------------*/ 100 | /** 101 | @brief Get a value from a dictionary. 102 | @param d dictionary object to search. 103 | @param key Key to look for in the dictionary. 104 | @param def Default value to return if key not found. 105 | @return 1 pointer to internally allocated character string. 106 | 107 | This function locates a key in a dictionary and returns a pointer to its 108 | value, or the passed 'def' pointer if no such key can be found in 109 | dictionary. The returned character pointer points to data internal to the 110 | dictionary object, you should not try to free it or modify it. 111 | */ 112 | /*--------------------------------------------------------------------------*/ 113 | char * dictionary_get(dictionary * d, const char * key, char * def); 114 | 115 | 116 | /*-------------------------------------------------------------------------*/ 117 | /** 118 | @brief Set a value in a dictionary. 119 | @param d dictionary object to modify. 120 | @param key Key to modify or add. 121 | @param val Value to add. 122 | @return int 0 if Ok, anything else otherwise 123 | 124 | If the given key is found in the dictionary, the associated value is 125 | replaced by the provided one. If the key cannot be found in the 126 | dictionary, it is added to it. 127 | 128 | It is Ok to provide a NULL value for val, but NULL values for the dictionary 129 | or the key are considered as errors: the function will return immediately 130 | in such a case. 131 | 132 | Notice that if you dictionary_set a variable to NULL, a call to 133 | dictionary_get will return a NULL value: the variable will be found, and 134 | its value (NULL) is returned. In other words, setting the variable 135 | content to NULL is equivalent to deleting the variable from the 136 | dictionary. It is not possible (in this implementation) to have a key in 137 | the dictionary without value. 138 | 139 | This function returns non-zero in case of failure. 140 | */ 141 | /*--------------------------------------------------------------------------*/ 142 | int dictionary_set(dictionary * vd, const char * key, const char * val); 143 | 144 | /*-------------------------------------------------------------------------*/ 145 | /** 146 | @brief Delete a key in a dictionary 147 | @param d dictionary object to modify. 148 | @param key Key to remove. 149 | @return void 150 | 151 | This function deletes a key in a dictionary. Nothing is done if the 152 | key cannot be found. 153 | */ 154 | /*--------------------------------------------------------------------------*/ 155 | void dictionary_unset(dictionary * d, const char * key); 156 | 157 | 158 | /*-------------------------------------------------------------------------*/ 159 | /** 160 | @brief Dump a dictionary to an opened file pointer. 161 | @param d Dictionary to dump 162 | @param f Opened file pointer. 163 | @return void 164 | 165 | Dumps a dictionary onto an opened file pointer. Key pairs are printed out 166 | as @c [Key]=[Value], one per line. It is Ok to provide stdout or stderr as 167 | output file pointers. 168 | */ 169 | /*--------------------------------------------------------------------------*/ 170 | void dictionary_dump(dictionary * d, FILE * out); 171 | 172 | /*-------------------------------------------------------------------------*/ 173 | /** 174 | @brief Duplicate a string 175 | @param s String to duplicate 176 | @return Pointer to a newly allocated string, to be freed with free() 177 | 178 | This is a replacement for strdup(). This implementation is provided 179 | for systems that do not have it. 180 | */ 181 | /*--------------------------------------------------------------------------*/ 182 | char * xstrdup(const char * s); 183 | 184 | 185 | #ifdef __cplusplus 186 | } 187 | #endif 188 | 189 | } // end of namespace libevrpc 190 | 191 | #endif 192 | -------------------------------------------------------------------------------- /src/rpc_client/rpc_channel.cpp: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * 3 | * Copyright (c) 2014 Aishuyu. All Rights Reserved 4 | * 5 | **************************************************************************/ 6 | 7 | 8 | 9 | /** 10 | * @file rpc_channel.cpp 11 | * @author aishuyu(asy5178@163.com) 12 | * @date 2014/11/23 16:25:13 13 | * @brief 14 | * 15 | **/ 16 | 17 | 18 | #include "rpc_channel.h" 19 | 20 | #include 21 | 22 | #include "util/rpc_util.h" 23 | #include "util/rpc_communication.h" 24 | 25 | namespace libevrpc { 26 | 27 | using std::string; 28 | using std::vector; 29 | 30 | Channel::Channel(CenterClientHeartbeat* center_client_heartbeat_ptr, const char* port) : 31 | addr_(NULL), 32 | port_(NULL), 33 | is_channel_async_call_(false), 34 | call_limit_(100), 35 | tcp_conn_timeout_(1000), 36 | try_time_(1), 37 | center_client_heartbeat_ptr_(center_client_heartbeat_ptr) { 38 | 39 | strcpy(port_ = (char*)malloc(strlen(port) + 1), port); 40 | } 41 | 42 | 43 | Channel::Channel(const char* addr, const char* port) : 44 | is_channel_async_call_(false), 45 | call_limit_(100), 46 | tcp_conn_timeout_(1000), 47 | try_time_(1) { 48 | /** 49 | * copy the server addr and port when in single server 50 | */ 51 | strcpy(addr_ = (char*)malloc(strlen(addr) + 1), addr); 52 | strcpy(port_ = (char*)malloc(strlen(port) + 1), port); 53 | } 54 | 55 | Channel::~Channel() { 56 | if (NULL != addr_) { 57 | free(addr_); 58 | } 59 | 60 | if (NULL != port_) { 61 | free(port_); 62 | } 63 | 64 | if (!thread_ids_vec_.empty()) { 65 | for (int i = 0; i < thread_ids_vec_.size(); ++i) { 66 | pthread_join(thread_ids_vec_[i], NULL); 67 | } 68 | } 69 | } 70 | 71 | /** 72 | * 非线程安全! 73 | */ 74 | void Channel::CallMethod(const MethodDescriptor* method, 75 | RpcController* controller, 76 | const Message* request, 77 | Message* response, 78 | Closure* done) { 79 | 80 | if (NULL == center_client_heartbeat_ptr_ && 81 | (NULL == addr_ || NULL == port_)) { 82 | return; 83 | } 84 | 85 | int32_t try_times = try_time_; 86 | char* local_addr = NULL; 87 | if (NULL != center_client_heartbeat_ptr_) { 88 | local_addr = const_cast(center_client_heartbeat_ptr_->RandomGetRpcServerAddr().c_str()); 89 | } else { 90 | strcpy(local_addr = (char*)malloc(strlen(addr_) + 1), addr_); 91 | } 92 | do { 93 | connect_fd_ = TcpConnect(local_addr, port_, tcp_conn_timeout_); 94 | if (TCP_CONN_TIMEOUT != connect_fd_) { 95 | break; 96 | } 97 | --try_times; 98 | PrintErrorInfo("TcpConnect timeout! try again!"); 99 | } while (try_times <= 0); 100 | 101 | if (NULL != local_addr) { 102 | free(local_addr); 103 | } 104 | 105 | if (connect_fd_ < 0) { 106 | if (NULL != controller) { 107 | controller->SetFailed("Rpc connect server failed!"); 108 | } 109 | return; 110 | } 111 | 112 | RpcCallParams* rpc_params_ptr = new RpcCallParams(method->full_name(), method->name(), request, response, this); 113 | if (is_channel_async_call_) { 114 | AsyncRpcCall(rpc_params_ptr); 115 | } else { 116 | if (!RpcCommunication(rpc_params_ptr)) { 117 | if (NULL != controller) { 118 | controller->SetFailed(error_info_); 119 | } 120 | delete rpc_params_ptr; 121 | return; 122 | } 123 | if (!response->ParseFromString(rpc_params_ptr->response_str) && NULL != controller) { 124 | controller->SetFailed("SerializeToString response error in RpcChannel!"); 125 | } 126 | delete rpc_params_ptr; 127 | } 128 | } 129 | 130 | bool Channel::OpenRpcAsyncMode() { 131 | is_channel_async_call_ = true; 132 | return true; 133 | } 134 | 135 | bool Channel::RpcCommunication(RpcCallParams* rpc_params) { 136 | const string& method_name = rpc_params->method_full_name; 137 | const Message* request = rpc_params->p_request; 138 | string& recv_str = rpc_params->response_str; 139 | Message* response = rpc_params->p_response; 140 | if (NULL == response) { 141 | response->New(); 142 | } 143 | 144 | string send_str; 145 | if (!request->SerializeToString(&send_str)) { 146 | error_info_ = "SerializeToString request failed!"; 147 | return false; 148 | } 149 | uint32_t hash_code = BKDRHash(method_name.c_str()); 150 | if (RpcSend(connect_fd_, hash_code, send_str, false) < 0) { 151 | error_info_ = "Send data error in rpc channel."; 152 | return false; 153 | } 154 | 155 | int32_t ret_id = RpcRecv(connect_fd_, recv_str, true); 156 | if (ERROR_RECV == ret_id) { 157 | error_info_ = "Recv data error in rpc channel."; 158 | return false; 159 | } 160 | return true; 161 | } 162 | 163 | bool Channel::AsyncRpcCall(RpcCallParams* rpc_params_ptr) { 164 | { 165 | ReadLockGuard rguard(tids_map_rwlock_); 166 | if (call_tids_map_.size() >= call_limit_) { 167 | return false; 168 | } 169 | } 170 | pthread_t tid; 171 | pthread_create(&tid, NULL, Channel::RpcProcessor, rpc_params_ptr); 172 | uint32_t hash_code = BKDRHash(rpc_params_ptr->method_client_name.c_str()); 173 | { 174 | WriteLockGuard wguard(tids_map_rwlock_); 175 | PthreadHashMap::iterator ret_iter = call_tids_map_.find(hash_code); 176 | if (ret_iter == call_tids_map_.end()) { 177 | TidListPtr tids_ptr(new TidList()); 178 | tids_ptr->push_back(tid); 179 | call_tids_map_.insert(std::make_pair(hash_code, tids_ptr)); 180 | } else { 181 | ret_iter->second->push_back(tid); 182 | } 183 | } 184 | thread_ids_vec_.push_back(tid); 185 | return true; 186 | } 187 | 188 | bool Channel::GetAsyncResponse(const string& method_name, Message* response) { 189 | uint32_t method_code = BKDRHash(method_name.c_str()); 190 | PthreadHashMap::iterator ret_iter; 191 | pthread_t cur_tid; 192 | { 193 | ReadLockGuard rguard(tids_map_rwlock_); 194 | ret_iter = call_tids_map_.find(method_code); 195 | if (call_tids_map_.end() == ret_iter || ret_iter->second->size() == 0) { 196 | error_info_ = "Get the response list failed"; 197 | return false; 198 | } 199 | cur_tid = ret_iter->second->front(); 200 | ret_iter->second->pop_front(); 201 | } 202 | pthread_join(cur_tid, NULL); 203 | { 204 | WriteLockGuard wguard(ret_map_rwlock_); 205 | MsgHashMap::iterator msg_iter = call_results_map_.find(cur_tid); 206 | if (call_results_map_.end() == msg_iter) { 207 | return false; 208 | } 209 | response->ParseFromString(msg_iter->second); 210 | call_results_map_.erase(msg_iter); 211 | } 212 | return true; 213 | } 214 | 215 | void Channel::SetConnectionInfo(int32_t timeout, int32_t try_time) { 216 | tcp_conn_timeout_ = timeout; 217 | try_time_ = try_time; 218 | } 219 | 220 | void Channel::SetCallLimit(int32_t limit) { 221 | call_limit_ = limit; 222 | } 223 | 224 | void* Channel::RpcProcessor(void *arg) { 225 | if (NULL == arg) { 226 | return NULL; 227 | } 228 | RpcCallParams* rpc_params_ptr = (RpcCallParams*) arg; 229 | Channel* channel_ptr = rpc_params_ptr->p_channel; 230 | if (!channel_ptr->RpcCommunication(rpc_params_ptr)) { 231 | return NULL; 232 | } 233 | string& response_str = rpc_params_ptr->response_str; 234 | pthread_t cur_tid = pthread_self(); 235 | MsgHashMap& ret_map = channel_ptr->call_results_map_; 236 | { 237 | WriteLockGuard wguard(channel_ptr->ret_map_rwlock_); 238 | MsgHashMap::iterator ret_iter = ret_map.find(cur_tid); 239 | if (ret_map.end() == ret_iter) { 240 | ret_map.insert(std::make_pair(cur_tid, std::move(response_str))); 241 | } else { 242 | /* 243 | * if conflict, replace old one 244 | */ 245 | ret_map[cur_tid] = std::move(response_str); 246 | } 247 | } 248 | delete rpc_params_ptr; 249 | } 250 | 251 | } // end of namespace libevrpc 252 | 253 | 254 | 255 | /* vim: set expandtab ts=4 sw=4 sts=4 tw=100: */ 256 | -------------------------------------------------------------------------------- /src/rpc_client/center_client_heartbeat.cpp: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * 3 | * Copyright (c) 2016 aishuyu, Inc. All Rights Reserved 4 | * 5 | **************************************************************************/ 6 | 7 | 8 | 9 | /** 10 | * @file center_client_heartbeat.cpp 11 | * @author aishuyu(asy5178@163.com) 12 | * @date 2016/09/07 20:59:44 13 | * @brief 14 | * 15 | **/ 16 | 17 | 18 | #include "center_client_heartbeat.h" 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #include 29 | 30 | #include "center_proto/center_cluster.pb.h" 31 | #include "center_proto/center_client.pb.h" 32 | #include "config_parser/config_parser.h" 33 | #include "util/rpc_communication.h" 34 | #include "util/rpc_util.h" 35 | 36 | #define random(x) (rand()%x) 37 | 38 | namespace libevrpc { 39 | 40 | using std::string; 41 | using namespace google::protobuf; 42 | 43 | CenterClientHeartbeat::CenterClientHeartbeat(const string& config_file): 44 | config_file_(config_file), 45 | center_addrs_ptr_(new ADDRS_LIST_TYPE()), 46 | updatecenter_addrs_ptr_(new ADDRS_LIST_TYPE()), 47 | cluster_server_addrs_list_ptr_(new ADDRS_LIST_TYPE()), 48 | running_(false), 49 | center_port_(NULL) { 50 | } 51 | 52 | CenterClientHeartbeat::~CenterClientHeartbeat() { 53 | if (NULL != center_addrs_ptr_) { 54 | delete center_addrs_ptr_; 55 | } 56 | 57 | if (NULL != updatecenter_addrs_ptr_) { 58 | delete updatecenter_addrs_ptr_; 59 | } 60 | 61 | if (NULL != center_port_) { 62 | free(center_port_); 63 | } 64 | 65 | if (NULL != cluster_server_addrs_list_ptr_) { 66 | delete cluster_server_addrs_list_ptr_; 67 | } 68 | } 69 | 70 | void CenterClientHeartbeat::Run() { 71 | if (!InitCenterClientHB()) { 72 | fprintf(stderr, "Center Init HeartBeat failed!\n"); 73 | return; 74 | } 75 | int32_t rc_size = updatecenter_addrs_ptr_->size(); 76 | int32_t ca_size = center_addrs_ptr_->size(); 77 | 78 | if (0 == rc_size || 0 == ca_size) { 79 | fprintf(stderr, "updated center list size is %d\n center addrs list size is %d\n", rc_size, ca_size); 80 | return; 81 | } 82 | 83 | while (running_) { 84 | ClientWithCenter cwc_proto; 85 | cwc_proto.set_client_center_action(UPDATE_SERVER_INFO); 86 | 87 | string cwc_str; 88 | if (!cwc_proto.SerializeToString(&cwc_str)) { 89 | fprintf(stderr, "SerializeToString the client to center error!\n"); 90 | sleep(3); 91 | continue; 92 | } 93 | int32_t random_index = random(ca_size); 94 | int32_t conn_fd = TcpConnect(center_addrs_ptr_->at(random_index).c_str(), center_port_, 15); 95 | if (conn_fd <= 0) { 96 | close(conn_fd); 97 | fprintf(stderr, "Connect center failed!\n"); 98 | sleep(20); 99 | continue; 100 | } 101 | 102 | if (RpcSend(conn_fd, CENTER2CLIENT, cwc_str) < 0) { 103 | close(conn_fd); 104 | fprintf(stderr, "Send info to center error!\n"); 105 | sleep(10); 106 | continue; 107 | } 108 | 109 | string center_response_str; 110 | ClientWithCenter cwc_response_proto; 111 | if (RpcRecv(conn_fd, center_response_str, true) >= 0 || 112 | cwc_response_proto.ParseFromString(center_response_str)) { 113 | const RepeatedPtrField& center_list = cwc_response_proto.should_communicate_center(); 114 | UpdateCenterAddrs(¢er_list); 115 | const RepeatedPtrField& server_list = cwc_response_proto.cluster_server_list(); 116 | UpdateServerAddrs(&server_list); 117 | } 118 | close(conn_fd); 119 | sleep(5); 120 | } 121 | } 122 | 123 | void CenterClientHeartbeat::GetRpcServerList(ADDRS_LIST_TYPE& server_list) { 124 | ReadLockGuard wguard(servers_rwlock_); 125 | server_list.assign(cluster_server_addrs_list_ptr_->begin(), cluster_server_addrs_list_ptr_->end()); 126 | } 127 | 128 | string CenterClientHeartbeat::RandomGetRpcServerAddr() { 129 | ReadLockGuard wguard(servers_rwlock_); 130 | int32_t random = random(cluster_server_addrs_list_ptr_->size()); 131 | return cluster_server_addrs_list_ptr_->at(random); 132 | } 133 | 134 | bool CenterClientHeartbeat::InitCenterClientHB() { 135 | const string cfile = "/tmp/centers.data"; 136 | int ftyp = access(cfile.c_str(), 0); 137 | if (0 != ftyp) { 138 | /* 139 | * 需要的服务器列表文件不存在,无法初始化后与其他机器进行通信 140 | * 启动失败!!! 141 | */ 142 | fprintf(stderr, "Can't read center data file!\n"); 143 | return false; 144 | } 145 | const char* center_port = ConfigParser::GetInstance(config_file_).IniGetString("rpc_client:port", "8899"); 146 | strcpy(center_port_ = (char*)malloc(strlen(center_port) + 1), center_port); 147 | 148 | std::ifstream in(cfile); 149 | string line; 150 | 151 | const char* local_addr = GetLocalAddress(); 152 | while (getline(in, line)) { 153 | // FOR Test 154 | if (strcmp(line.c_str(), local_addr) == 0) { 155 | continue; 156 | } 157 | center_addrs_ptr_->push_back(line); 158 | } 159 | 160 | int32_t ca_size = center_addrs_ptr_->size(); 161 | if (0 == ca_size) { 162 | fprintf(stderr, "The center_addrs_ptr size is 0!\n"); 163 | return false; 164 | } 165 | 166 | int32_t random_index = random(ca_size); 167 | int32_t conn_fd = TcpConnect(center_addrs_ptr_->at(random_index).c_str(), center_port_, 15); 168 | if (conn_fd <= 0) { 169 | fprintf(stderr, "Tcp connect %d failed\n", conn_fd); 170 | return false; 171 | } 172 | 173 | ClientWithCenter cwc_proto; 174 | cwc_proto.set_client_center_action(CLIENT_INIT_REQ); 175 | 176 | string cwc_str; 177 | if (!cwc_proto.SerializeToString(&cwc_str)) { 178 | close(conn_fd); 179 | fprintf(stderr, "cwc_proto serialize to string failed!\n"); 180 | return false; 181 | } 182 | 183 | if (RpcSend(conn_fd, CENTER2CLIENT, cwc_str) < 0) { 184 | close(conn_fd); 185 | return false; 186 | } 187 | 188 | string center_response_str; 189 | if (RpcRecv(conn_fd, center_response_str, false) >= 0) { 190 | ClientWithCenter cwc_proto; 191 | if (cwc_proto.ParseFromString(center_response_str) && 192 | cwc_proto.client_center_action() == CENTER_RESP_OK) { 193 | /* 194 | * 获取与当前Client对应Center服务器列表 195 | */ 196 | const RepeatedPtrField& center_list = cwc_proto.should_communicate_center(); 197 | for (RepeatedPtrField::const_iterator iter = center_list.begin(); 198 | iter != center_list.end(); 199 | ++iter) { 200 | updatecenter_addrs_ptr_->push_back(*iter); 201 | } 202 | /* 203 | * 第一次获取与当前Client对应的Cluster服务器列表 204 | */ 205 | const RepeatedPtrField& rpc_server_list = cwc_proto.cluster_server_list(); 206 | for (RepeatedPtrField::const_iterator iter = rpc_server_list.begin(); 207 | iter != rpc_server_list.end(); 208 | ++iter) { 209 | cluster_server_addrs_list_ptr_->push_back(*iter); 210 | } 211 | } 212 | } 213 | close(conn_fd); 214 | 215 | running_ = true; 216 | return true; 217 | } 218 | 219 | void CenterClientHeartbeat::UpdateCenterAddrs(const RepeatedPtrField* center_list) { 220 | WriteLockGuard wguard(centers_rwlock_); 221 | for (RepeatedPtrField::const_iterator iter = center_list->begin(); 222 | iter != center_list->end(); 223 | ++iter) { 224 | updatecenter_addrs_ptr_->push_back(*iter); 225 | } 226 | } 227 | 228 | void CenterClientHeartbeat::UpdateServerAddrs(const RepeatedPtrField* server_list) { 229 | WriteLockGuard wguard(servers_rwlock_); 230 | for (RepeatedPtrField::const_iterator iter = server_list->begin(); 231 | iter != server_list->end(); 232 | ++iter) { 233 | cluster_server_addrs_list_ptr_->push_back(*iter); 234 | } 235 | } 236 | 237 | 238 | } // end of namespace libevrpc 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | /* vim: set expandtab ts=4 sw=4 sts=4 tw=100: */ 249 | -------------------------------------------------------------------------------- /src/rpc_server/libev_thread_pool.cpp: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * 3 | * Copyright (c) 2014 aishuyu.com, Inc. All Rights Reserved 4 | * 5 | **************************************************************************/ 6 | 7 | 8 | 9 | /** 10 | * @file thread_pool.cpp 11 | * @author aishuyu(asy5178@163.com) 12 | * @date 2014/11/07 18:44:20 13 | * @brief 14 | * 15 | **/ 16 | 17 | #include "libev_thread_pool.h" 18 | 19 | #include 20 | 21 | #include "util/rpc_util.h" 22 | 23 | namespace libevrpc { 24 | 25 | int32_t LibevThreadPool::item_per_alloc_ = 64; 26 | 27 | LibevThreadPool::LibevThreadPool() : 28 | current_thread_(-1), 29 | num_threads_(10), 30 | libev_threads_(NULL), 31 | rqi_freelist_(NULL) { 32 | } 33 | 34 | LibevThreadPool::~LibevThreadPool() { 35 | Destroy(); 36 | } 37 | 38 | bool LibevThreadPool::LibevThreadInitialization(int32_t num_threads) { 39 | num_threads_ = num_threads; 40 | libev_threads_ = (LIBEV_THREAD*)calloc(num_threads_, sizeof(LIBEV_THREAD)); 41 | rqi_freelist_ = NULL; 42 | 43 | if (NULL == libev_threads_) { 44 | return false; 45 | } 46 | 47 | for (int32_t i = 0; i < num_threads_; ++i) { 48 | int32_t fds[2]; 49 | if (pipe(fds)) { 50 | PrintErrorInfo("Create notify pipe failed!"); 51 | exit(1); 52 | } 53 | /* 54 | * start to init the libev info in every thread 55 | */ 56 | LIBEV_THREAD* cur_thread = &libev_threads_[i]; 57 | cur_thread->running_version = 0; 58 | cur_thread->notify_receive_fd = fds[0]; 59 | cur_thread->notify_send_fd = fds[1]; 60 | 61 | cur_thread->epoller = ev_loop_new(0); 62 | if (NULL == cur_thread->epoller) { 63 | PrintErrorInfo("Ev loop new failed!"); 64 | exit(-1); 65 | } 66 | cur_thread->lt_pool = this; 67 | cur_thread->libev_watcher.data = cur_thread; 68 | ev_io_init( 69 | &cur_thread->libev_watcher, 70 | LibevThreadPool::LibevProcessor, 71 | cur_thread->notify_receive_fd, 72 | EV_READ | EV_WRITE); 73 | ev_io_start(cur_thread->epoller, &cur_thread->libev_watcher); 74 | 75 | cur_thread->new_request_queue = new RQ(); 76 | if (NULL == cur_thread->new_request_queue) { 77 | PrintErrorInfo("Failed to allocate memory for request queue"); 78 | exit(-1); 79 | } 80 | cur_thread->new_request_queue->head = NULL; 81 | cur_thread->new_request_queue->tail = NULL; 82 | } 83 | 84 | for (int i = 0; i < num_threads_; ++i) { 85 | LIBEV_THREAD* lt = libev_threads_ + i; 86 | pthread_create(&(lt->thread_id), NULL, LibevThreadPool::LibevWorker, lt); 87 | } 88 | 89 | return true; 90 | } 91 | 92 | void *LibevThreadPool::LibevWorker(void *arg) { 93 | LIBEV_THREAD* me = (LIBEV_THREAD*)arg; 94 | 95 | ev_run(me->epoller, 0); 96 | ev_loop_destroy(me->epoller); 97 | } 98 | 99 | void LibevThreadPool::RetrieveDataAction(void *arg) { 100 | RetrieveData* rd = (RetrieveData*)arg; 101 | if (NULL == rd) { 102 | return; 103 | } 104 | LibevThreadPool* ltp = rd->retrieve_ltp; 105 | RQ_ITEM* item = rd->retrieve_item; 106 | if (NULL == ltp || NULL == item) { 107 | return; 108 | } 109 | ltp->RQItemFree(item); 110 | } 111 | 112 | RQ_ITEM* LibevThreadPool::RQItemNew() { 113 | RQ_ITEM *rq_item = NULL; 114 | { 115 | MutexLockGuard lock(rqi_freelist_mutex_); 116 | if (NULL != rqi_freelist_) { 117 | rq_item = rqi_freelist_; 118 | rqi_freelist_ = rq_item->next; 119 | } 120 | } 121 | 122 | if (NULL == rq_item) { 123 | rq_item = (RQ_ITEM*)malloc(sizeof(RQ_ITEM) * item_per_alloc_); 124 | if (NULL == rq_item) { 125 | PrintErrorInfo("Alloc the item mem failed!"); 126 | return NULL; 127 | } 128 | for (int i = 0; i < item_per_alloc_; ++i) { 129 | rq_item[i - 1].next = &rq_item[i]; 130 | } 131 | rq_item[item_per_alloc_ - 1].next = NULL; 132 | { 133 | MutexLockGuard lock(rqi_freelist_mutex_); 134 | rq_item[item_per_alloc_ - 1].next = rqi_freelist_; 135 | rqi_freelist_ = &rq_item[1]; 136 | } 137 | } 138 | return rq_item; 139 | } 140 | 141 | RQ_ITEM* LibevThreadPool::RQItemPop(RQ* req_queue) { 142 | RQ_ITEM* rq_item = NULL; 143 | { 144 | MutexLockGuard lock(req_queue->q_mutex); 145 | rq_item = req_queue->head; 146 | if (NULL != rq_item) { 147 | req_queue->head = rq_item->next; 148 | if (NULL == req_queue->head) { 149 | req_queue->tail = NULL; 150 | } 151 | } 152 | } 153 | return rq_item; 154 | } 155 | 156 | bool LibevThreadPool::RQItemPush(RQ* req_queue, RQ_ITEM* rq_item) { 157 | rq_item->next = NULL; 158 | { 159 | MutexLockGuard lock(req_queue->q_mutex); 160 | if (NULL == req_queue->tail) { 161 | req_queue->head = rq_item; 162 | } else { 163 | req_queue->tail->next = rq_item; 164 | } 165 | req_queue->tail = rq_item; 166 | } 167 | return true; 168 | } 169 | 170 | bool LibevThreadPool::RQItemFree(RQ_ITEM* rq_item) { 171 | MutexLockGuard lock(rqi_freelist_mutex_); 172 | rq_item->next = rqi_freelist_; 173 | rqi_freelist_ = rq_item; 174 | return true; 175 | } 176 | 177 | bool LibevThreadPool::Start(int32_t num_threads) { 178 | return LibevThreadInitialization(num_threads); 179 | } 180 | 181 | bool LibevThreadPool::Wait() { 182 | for (int32_t i = 0; i < num_threads_; ++i) { 183 | pthread_t tid = (libev_threads_ + i)->thread_id; 184 | pthread_join(tid, 0); 185 | } 186 | } 187 | 188 | bool LibevThreadPool::RestartThread(pthread_t thread_id, long running_version) { 189 | /* 190 | * notify the one thread exit 191 | */ 192 | int32_t index = 0; 193 | for (int32_t i = 0; i < num_threads_; ++i) { 194 | pthread_t tid = (libev_threads_ + i)->thread_id; 195 | if (thread_id == tid) { 196 | /* 197 | * get the index of thread need to exit 198 | */ 199 | index = i; 200 | break; 201 | } 202 | } 203 | LIBEV_THREAD* cur_thread = libev_threads_ + index; 204 | { 205 | MutexLockGuard guard(cur_thread->version_mutex); 206 | if (cur_thread->running_version > running_version) { 207 | return true; 208 | } 209 | ev_break(cur_thread->epoller); 210 | pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); 211 | pthread_cancel(thread_id); 212 | } 213 | pthread_create(&(cur_thread->thread_id), NULL, LibevThreadPool::LibevWorker, cur_thread); 214 | 215 | return true; 216 | } 217 | 218 | bool LibevThreadPool::Destroy() { 219 | /* 220 | * notify all thread exit 221 | */ 222 | char buf[1] = {'q'}; 223 | for (int32_t i = 0; i < num_threads_; ++i) { 224 | if (write((libev_threads_ + i)->notify_send_fd, buf, 1) != 1) { 225 | PrintErrorInfo("Destroy, Write to thread notify pipe failed!"); 226 | } 227 | } 228 | /* 229 | * release all ptr 230 | */ 231 | Wait(); 232 | for (int32_t i = 0; i < num_threads_; ++i) { 233 | LIBEV_THREAD* lt = libev_threads_ + i; 234 | delete lt->new_request_queue; 235 | } 236 | for (RQ_ITEM* cur_rqi = rqi_freelist_; cur_rqi != rqi_freelist_;) { 237 | RQ_ITEM* next_rqi = cur_rqi->next; 238 | free(cur_rqi); 239 | cur_rqi = next_rqi; 240 | } 241 | return true; 242 | 243 | } 244 | 245 | bool LibevThreadPool::DispatchRpcCall(void *(*rpc_call) (void *arg), void *arg) { 246 | if (NULL == libev_threads_) { 247 | PrintErrorInfo("Dispatch rpc call failed! libev_threads ptr is null."); 248 | return false; 249 | } 250 | 251 | RQ_ITEM* rq_item = RQItemNew(); 252 | if (NULL == rq_item) { 253 | PrintErrorInfo("New RQ Item failed!"); 254 | return false; 255 | } 256 | 257 | int32_t cur_tid = (current_thread_ + 1) % num_threads_; 258 | LIBEV_THREAD* cur_thread = libev_threads_ + cur_tid; 259 | current_thread_ = cur_tid; 260 | 261 | /* 262 | * set req item data 263 | */ 264 | rq_item->processor = rpc_call; 265 | rq_item->param = arg; 266 | if (!RQItemPush(cur_thread->new_request_queue, rq_item)) { 267 | PrintErrorInfo("Push RQ Item failed!"); 268 | return false; 269 | } 270 | 271 | char buf[1] = {'c'}; 272 | if (write(cur_thread->notify_send_fd, buf, 1) != 1) { 273 | PrintErrorInfo("Write to thread notify pipe failed!"); 274 | } 275 | return true; 276 | } 277 | 278 | void LibevThreadPool::LibevProcessor(struct ev_loop *loop, struct ev_io *watcher, int revents) { 279 | LIBEV_THREAD *me = (LIBEV_THREAD*)(watcher->data); 280 | if (NULL == me) { 281 | PrintErrorInfo("LIBEV_THREAD data is NULL!"); 282 | exit(-1); 283 | return; 284 | } 285 | 286 | char buf[1]; 287 | if (read(watcher->fd, buf, 1) != 1) { 288 | PrintErrorInfo("Can't read from libevent pipe!"); 289 | } 290 | LibevThreadPool* ltp = me->lt_pool; 291 | switch (buf[0]) { 292 | case 'c': { 293 | RQ_ITEM* item = ltp->RQItemPop(me->new_request_queue); 294 | struct RetrieveData rd = {ltp, item}; 295 | pthread_cleanup_push(LibevThreadPool::RetrieveDataAction, &rd); 296 | (*(item->processor))(item->param); 297 | { 298 | MutexLockGuard guard(me->version_mutex); 299 | ++me->running_version; 300 | } 301 | pthread_cleanup_pop(0); 302 | ltp->RQItemFree(item); 303 | break; 304 | } 305 | case 'q': { 306 | ev_io_stop(me->epoller, &(me->libev_watcher)); 307 | ev_break (me->epoller, EVBREAK_ALL); 308 | break; 309 | } 310 | } 311 | } 312 | 313 | /* 314 | * Note: for unit test 315 | */ 316 | LIBEV_THREAD* LibevThreadPool::GetTestThreadInfo() const { 317 | if (num_threads_ <= 0) { 318 | return NULL; 319 | } 320 | LIBEV_THREAD* lt = libev_threads_ + 0; 321 | return lt; 322 | } 323 | 324 | 325 | } // end of namespace 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | /* vim: set expandtab ts=4 sw=4 sts=4 tw=100: */ 337 | --------------------------------------------------------------------------------