nlsCppSdk/vipServerClient/vipclient_helper.hpp (140 lines of code) (raw):

#ifndef MIDDLEWARE_VIPCLIENT_CPP_HELPER_H_ #define MIDDLEWARE_VIPCLIENT_CPP_HELPER_H_ #include <errno.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <iostream> #include <sstream> #include <string> #include <vector> #include "error_code.h" #include "iphost.h" #include "option.h" #include "vipclient.h" namespace middleware { namespace vipclient { namespace helper { static std::string ToString(const IPHost& host) { std::ostringstream osstm; osstm << "ip:" << host.ip() << " " << "port:" << host.port() << " " << "weight:" << host.weight() << " " << "valid:" << host.valid() << " " << "unit:" << host.unit() << " " << "host_name:" << host.host_name() << " " << "app_use_type:" << host.app_use_type() << " " << "site:" << host.site() << " "; return osstm.str(); } static std::string ToString(const IPHostArray& hosts) { std::ostringstream osstm; osstm << "iphosts size:" << hosts.size() << std::endl; for (unsigned int i = 0; i < hosts.size(); ++i) { osstm << "iphosts[" << i << "] " << ToString(hosts.get(i)) << std::endl; } return osstm.str(); } #if 0 /* unused */ static pthread_mutex_t g_vipclient_init_mutex = PTHREAD_MUTEX_INITIALIZER; /** * @brief 全局执行一次的初始化函数,线程安全, * !!!注意:内部会拉取线程,如果有FORK需要在FORK后执行 * * Init()本身不支持线程安全,使用全局锁来达到线程安全的目的 * @param[in] jmenv_dom Defaults to "jmenv.tbsite.net". vipserver服务器集群域名 * @return bool 成功返回 true 失败返回 false */ static bool GlobalInit(const char* jmenv_dom = "jmenv.tbsite.net") { bool result = false; pthread_mutex_lock(&g_vipclient_init_mutex); middleware::vipclient::VipClientApi::CreateApi(); middleware::vipclient::Option option; // option.set_cache_path("./"); // option.set_log_path("./"); if (!middleware::vipclient::VipClientApi::Init(jmenv_dom, option)) { fprintf(stderr, "global init failed jmenv_dom:%s error:%s\n", jmenv_dom, strerror(errno)); middleware::vipclient::VipClientApi::DestoryApi(); result = false; } else { result = true; } pthread_mutex_unlock(&g_vipclient_init_mutex); return result; } /** * @brief 全局执行一次反初始化函数,线程安全 * * UnInit()和DestoryApi()本身不支持线程安全 * 这里使用了一个全局锁g_vipclient_init_mutex来达到线程安全的目的 */ static void GlobalUnInit() { pthread_mutex_lock(&g_vipclient_init_mutex); middleware::vipclient::VipClientApi::UnInit(); middleware::vipclient::VipClientApi::DestoryApi(); pthread_mutex_unlock(&g_vipclient_init_mutex); } /** * @brief 获取所有可用的IP * * 如果没有IP都不可用,进行降级处理,返回所有的IP * @param[in] domain 请求域名 * @param[out] ip_list 存放IP的指针 * @return bool true 成功 false 失败 */ static bool QueryAllValidIp(const char* domain, std::vector<std::string>* ip_list) { middleware::vipclient::IPHostArray iphosts; if (!middleware::vipclient::VipClientApi::QueryAllIp(domain, &iphosts, 5 * 1000)) { fprintf(stderr, "query all ip failed %s %s\n", VipClientApi::Errstr(), strerror(errno)); return false; } ip_list->clear(); for (unsigned int i = 0; i < iphosts.size(); ++i) { const middleware::vipclient::IPHost& iphost = iphosts.get(i); if (iphost.valid()) { ip_list->push_back(iphost.ip()); } } /* if (ip_list->empty()) { //一个合法的IP也没有,则进行降级保护,返回所有IP fprintf(stderr, "no valid ip downgrading %s", domain); for (unsigned int i =0; i < iphosts.size(); ++i) { const middleware::vipclient::IPHost& iphost = iphosts.get(i); ip_list->push_back(iphost.ip()); } }*/ return true; } /** * @brief 获取可用的IP,线程安全 * * 如果所有IP都不可用,那么会进行降级保护,返回任意一个IP * @param[in] domain 请求的域名 * @param[out] ip 获取到的一个合法IP * @return bool true 成功 false 失败 */ static bool QueryValidIp(const char* domain, std::string* ip) { middleware::vipclient::IPHost iphost; if (middleware::vipclient::VipClientApi::QueryIp(domain, &iphost, 5 * 1000)) { *ip = iphost.ip(); return true; } /* //获取合法的IP失败,进行降级处理,返回任意一个IP fprintf(stderr, "query ip failed %s %s downgrading\n", VipClientApi::Errstr(), strerror(errno)); std::vector<std::string> ip_list; if(QueryAllValidIp(domain, &ip_list)){ if (ip_list.size() > 0) { *ip = ip_list[rand()%ip_list.size()]; return true; } } fprintf(stderr, "query ip failed %s %s\n", VipClientApi::Errstr(), strerror(errno)); */ return false; } /** * @brief 跨过缓存去服务器实时获取可用IP,线程安全 * * 这个函数会跨越缓存去服务器获取数据,不能频繁调用 * 并没有提供全部的实现,需要用户自己实现用于同步的信号量 * @param[in] domain 请求的域名 * @param[out] ip 获取到的IP信息 * @return bool true 成功 false 失败 */ static bool RealQueryIp(const char* domain, std::string* ip) { class MySemaphore { public: void Post() { // TODO 用户自己实现等待信号量 throw "user not implement semaphore"; } void Wait() { // TODO 用户自己实现唤醒等待线程 throw "user not implement semaphore"; } }; class QueryAdapter : public middleware::vipclient::QueryHandler { public: QueryAdapter(const char* domain, std::string* result) : domain_(domain), result_(result), ok_(false) {} virtual ~QueryAdapter() {} virtual void OnError(ErrorCode error_code) { fprintf(stderr, "OnError %d %s %s\n", error_code, middleware::vipclient::VipClientApi::StrErrno(error_code), strerror(errno)); semaphore_.Post(); } virtual void OnResult(const IPHostArray& iphosts) { if (iphosts.size() >= 1) { *result_ = iphosts.get(0).ip(); ok_ = true; } else { fprintf(stderr, "OnResult %s no iphost\n", domain_.c_str()); ok_ = false; } semaphore_.Post(); } void Wait() { semaphore_.Wait(); } bool ok() const { return ok_; } private: std::string domain_; std::string* result_; bool ok_; MySemaphore semaphore_; } adapter(domain, ip); if (!middleware::vipclient::VipClientApi::AsyncQueryIp(domain, &adapter, 5 * 1000)) { fprintf(stderr, "async query failed %s %s %s\n", domain, middleware::vipclient::VipClientApi::Errstr(), strerror(errno)); } else { adapter.Wait(); } return adapter.ok(); } #endif } // namespace helper } // namespace vipclient } // namespace middleware #endif // MIDDLEWARE_VIPCLIENT_CPP_HELPER_H_