2021SC@SDUSC
删除Upstream
int UpstreamManager::upstream_delete(const std::string& name)
{
WFNameService *ns = WFGlobal::get_name_service();
WFNSPolicy *policy = ns->del_policy(name.c_str());
if (policy)
{
delete policy;
return 0;
}
errno = ENOENT;
return -1;
}
WFNameService *ns = WFGlobal::get_name_service() 调用域名服务。
c_str是Borland封装的String类中的一个函数,返回当前字符串的首字符地址。当需要打开一个由用户自己输入文件名的文件时,可以这样写:ifstream in(st.c_str())
error是记录系统的最后一次错误代码。代码是一个int型的值,在errno.h中定义。查看错误代码errno是调试程序的一个重要方法。一般会将errno变量赋一个整数值,不同的值表示不同的含义,可以通过查看该值推测出错的原因。在实际编程中用这一招解决了不少原本看来莫名其妙的问题。
替换服务器
int UpstreamManager::upstream_replace_server(const std::string& name,
const std::string& address,
const struct AddressParams *address_params)
{
WFNameService *ns = WFGlobal::get_name_service();
UPSGroupPolicy *policy = dynamic_cast<UPSGroupPolicy *>(ns->get_policy(name.c_str()));
if (policy)
{
policy->replace_server(address, address_params);
return 0;
}
errno = ENOENT;
return -1;
}
address是被替换的服务器的地址,name是域名,const struct AddressParams *address_params携带新的服务器的详细地址参数,包括有连接参数、网络请求成功时的DNS生存时间、网络请求失败时的DNS生存时间、最大失败次数、以及若采用分组策略时是否为main。
获得组内main的地址
std::vector<std::string>
UpstreamManager::upstream_main_address_list(const std::string& name)
{
std::vector<std::string> address;
WFNameService *ns = WFGlobal::get_name_service();
UPSGroupPolicy *policy = dynamic_cast<UPSGroupPolicy *>(ns->get_policy(name.c_str()));
if (policy)
policy->get_main_address(address);
return address;
}
该接口在采用DNS分组选择策略时可能被调用,获取组内所有main的地址。
服务器熔断
int UpstreamManager::upstream_disable_server(const std::string& name,
const std::string& address)
{
WFNameService *ns = WFGlobal::get_name_service();
UPSGroupPolicy *policy = dynamic_cast<UPSGroupPolicy *>(ns->get_policy(name.c_str()));
if (policy)
{
policy->disable_server(address);
return 0;
}
errno = ENOENT;
return -1;
}
这里跟服务器的熔断有关,如下图的代码所示,max_fails参数为最大出错次数,如果选取目标连续出错达到max_fails则熔断,如果upstream的try_another属性(失败后是否选择另一个服务器)为false,则任务失败。
在workflow中,MTTR(Mean time to repair,MTTR),是描述产品由故障状态转为工作状态时修理时间的平均值。默认30s,暂时不可配置,后续会考虑开放给用户自行配置。当某一个Addrees连续失败次数达到设定上限(默认200次),这个Address会被熔断MTTR=30秒 。Address在熔断期间,一旦被策略选中,Upstream会根据具体配置决定是否尝试其他Address以及如何尝试 。
void WFServiceGovernance::disable_server(const std::string& address)
{
this->rwlock.wlock();
const auto map_it = this->server_map.find(address);
if (map_it != this->server_map.cend())
{
for (EndpointAddress *addr : map_it->second)
{
addr->fail_count = addr->params->max_fails;
this->fuse_server_to_breaker(addr);
}
}
this->rwlock.unlock();
}
熔断恢复
int UpstreamManager::upstream_enable_server(const std::string& name,
const std::string& address)
{
WFNameService *ns = WFGlobal::get_name_service();
UPSGroupPolicy *policy = dynamic_cast<UPSGroupPolicy *>(ns->get_policy(name.c_str()));
if (policy)
{
policy->enable_server(address);
return 0;
}
errno = ENOENT;
return -1;
}
跟上面的upstream_disable_server十分类似,是一个相反的过程。当程序检测到服务器恢复正常之后,熔断恢复,当有请求到来时,仍可选择该服务器。熔断机制可有效阻止雪崩效应:起初只是一个很小的服务or模块异常/超时,引起下游其他依赖的服务随之异常/超时,产生连锁反应,最终导致绝大多数甚至全部的服务陷入瘫痪 。
void WFServiceGovernance::enable_server(const std::string& address)
{
this->rwlock.wlock();
const auto map_it = this->server_map.find(address);
if (map_it != this->server_map.cend())
{
for (EndpointAddress *addr : map_it->second)
this->recover_server_from_breaker(addr);
}
this->rwlock.unlock();
}
参考资料: