在Workflow的说明文件中,对upstream有简单的介绍:
upstream名相当于程序内部的域名,但相比一般的域名,upstream拥有更多的功能,包括:
* 域名通常只能指向一组ip地址,upstream名可以指向一组ip地址或域名。
* upstream指向的对象(域名或ip),可以包括端口信息。
* upstream有管理和选择目标的强大功能,每个目标可以包含大量属性。
* upstream的更新,是实时而且完全线程安全的,而域名的DNS信息,并不能实时更新。
实现上,如果无需访问外网,用upstream可以完全代替域名和DNS。
在UpstreamManager.h文件中有几个upstream创建接口,依次为一致性hash,权重随机和用户手动选择三种类型。
static int upstream_create_consistent_hash(const std::string& name,
upstream_route_t consitent_hash);
static int upstream_create_weighted_random(const std::string& name,
bool try_another);
static int upstream_create_manual(const std::string& name,
upstream_route_t select,
bool try_another,
upstream_route_t consitent_hash);
参数name为upstream名,创建之后和域名一样的使用,用于在数据传输时标识计算机的电子方位。
consistent_hash和select参数,都是一个类型为upstream_route_t的std::function,用于指定路由方式。下面声明中的std:function是一个模板类,C++11中的新特性,包含在#include <functional> 中,可以方便地定义一个回调函数。回调函数在之前的博客中好像有介绍,是通过函数指针调用的函数。 把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。
using upstream_route_t = std::function<unsigned int (const char *, const char *, const char *)>;
upstream_route_t接收的3个参数分别是url里的path, query和fragment部分。例如URL为:http://abc.com/home/index.html?a=1#bottom,则这三个参数分别为"/home/index.html"、 "a=1"、"bottom"。用户可以根据这三个部分,选择目标服务器,或者进行一致性hash。 注意,以上接口中,consistent_hash参数都可以传nullptr,将使用默认的一致性哈希算法。
boolean类型参数try_another表示,如果选取到的目标不可用(熔断),是否继续尝试找到一个可用目标 。简要介绍一下熔断:当某一个目标的错误或异常达到预先设定的阈值条件时,暂时认为这个目标不可用,剔除目标,即熔断开启。
WFNameService头文件里定义了四个类分别是WFRouterTask、WFNSTracing、WFNSPolicy、WFnameService,他们之间存在包含关系,需要按顺序来理解。
class WFRouterTask : public WFGenericTask
{
public:
RouteManager::RouteResult *get_result() { return &this->result; }
protected:
RouteManager::RouteResult result;
std::function<void (WFRouterTask *)> callback;
protected:
virtual SubTask *done()
{
SeriesWork *series = series_of(this);
if (this->callback)
this->callback(this);
delete this;
return series->pop();
}
public:
WFRouterTask(std::function<void (WFRouterTask *)>&& cb) :
callback(std::move(cb))
{
}
};
WFRouterTask是 src\factory\WFGericTask 的子类,而后者又继承自src\kernel_win\SubTask,表示寻找路由的一个子任务。
class WFNSTracing
{
public:
void *data;
void (*deleter)(void *);
public:
WFNSTracing()
{
this->data = NULL;
this->deleter = NULL;
}
~WFNSTracing()
{
if (this->deleter)
this->deleter(this->data);
}
};
WFNSTracing中有两个指针,一个指向数据,还有一个deleter来处理数据的释放。
struct WFNSParams
{
TransportType type;
ParsedURI& uri;
const char *info;
bool fixed_addr;
int retry_times;
WFNSTracing *tracing;
};
这个结构体保存一些nameService的参数,TransportType是一个枚举类,都是网络通信的一些协议。UDP:简单的、不可靠的、无连接的、提供消息边界的数据报协议;TCP:复杂的、可靠的、面向连接的、无消息边界的字节流协议;SCTP:可靠的、面向连接的,流控制传输协议,提供消息边界、传输级别多宿支持以及线头阻塞减少到最小的一种方法。
enum TransportType
{
TT_TCP,
TT_UDP,
TT_SCTP,
TT_TCP_SSL,
TT_SCTP_SSL,
};
剩下的参数意义比较好理解,ParsedURI& uri表示需要转换的uri地址,fixed_addr表示地址是否可变,retry_time重试次数,WDNSTracing类的对象tracing指向包括data和deleter。
参考资料:
C++11 之 std::function - gavinhe - 博客园 (cnblogs.com)