In nginx, Upstream represents the load balancing configuration of the reverse proxy. Here, we expand the meaning of Upstream so that it has the following characteristics:
Both Upstream and domain name DNS resolution can configure a group of ip to a host, but
This is a local reverse proxy module, and the proxy configuration is effective for both server and client.
Support dynamic configuration and available for any service discovery system. Currently, workflow-k8s can be used to acquire Pods information from the API server of Kubernetes.
Upstream name does not include port, but upstream request supports specified port. (However, for non-built-in protocols, Upstream name temporarily needs to be added with the port to ensure parsing during construction).
Each Upstream is configured with its own independent name UpstreamName, and a set of Addresses is added and set. These Addresses can be:
Supports http/https protocol only
Needs to build a nginx service, start the start process occupies socket and other resources
The request is sent to nginx first, and nginx forwards the request to remote end, which will increase one more network communication overhead
Protocol irrelevant, you can even access mysql, redis, mongodb, etc. through upstream
You can directly simulate the function of reverse proxy in the process, no need to start other processes or ports
The selection process is basic calculation and table lookup, no additional network communication overhead
class UpstreamManager
{
public:
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);
static int upstream_delete(const std::string& name);
public:
static int upstream_add_server(const std::string& name,
const std::string& address);
static int upstream_add_server(const std::string& name,
const std::string& address,
const struct AddressParams *address_params);
static int upstream_remove_server(const std::string& name,
const std::string& address);
...
}
Configure a local reverse proxy to evenly send all the local requests for my_proxy.name to 6 target servers
UpstreamManager::upstream_create_weighted_random(
"my_proxy.name",
true); // In case of fusing, retry till the available is found or all fuses are blown
UpstreamManager::upstream_add_server("my_proxy.name", "192.168.2.100:8081");
UpstreamManager::upstream_add_server("my_proxy.name", "192.168.2.100:8082");
UpstreamManager::upstream_add_server("my_proxy.name", "192.168.10.10");
UpstreamManager::upstream_add_server("my_proxy.name", "test.sogou.com:8080");
UpstreamManager::upstream_add_server("my_proxy.name", "abc.sogou.com");
UpstreamManager::upstream_add_server("my_proxy.name", "abc.sogou.com");
UpstreamManager::upstream_add_server("my_proxy.name", "/dev/unix_domain_scoket_sample");
auto *http_task = WFTaskFactory::create_http_task("http://my_proxy.name/somepath?a=10", 0, 0, nullptr);
http_task->start();
Basic principles
Configure a local reverse proxy, send all weighted.random requests to the 3 target servers based on the weight distribution of 5/20/1
UpstreamManager::upstream_create_weighted_random(
"weighted.random",
false); // If you don’t retry in case of fusing, the request will surely fail
AddressParams address_params = ADDRESS_PARAMS_DEFAULT;
address_params.weight = 5; //weight is 5
UpstreamManager::upstream_add_server("weighted.random", "192.168.2.100:8081", &address_params); // weight is 5
address_params.weight = 20; // weight is 20
UpstreamManager::upstream_add_server("weighted.random", "192.168.2.100:8082", &address_params); // weight is 20
UpstreamManager::upstream_add_server("weighted.random", "abc.sogou.com"); // weight is 1
auto *http_task = WFTaskFactory::create_http_task("http://weighted.random:9090", 0, 0, nullptr);
http_task->start();
Basic principles
UpstreamManager::upstream_create_consistent_hash(
"abc.local",
nullptr); // nullptr represents using the default consistent hash function of the framework
UpstreamManager::upstream_add_server("abc.local", "192.168.2.100:8081");
UpstreamManager::upstream_add_server("abc.local", "192.168.2.100:8082");
UpstreamManager::upstream_add_server("abc.local", "192.168.10.10");
UpstreamManager::upstream_add_server("abc.local", "test.sogou.com:8080");
UpstreamManager::upstream_add_server("abc.local", "abc.sogou.com");
auto *http_task = WFTaskFactory::create_http_task("http://abc.local/service/method", 0, 0, nullptr);
http_task->start();
Basic principles
UpstreamManager::upstream_create_consistent_hash(
"abc.local",
[](const char *path, const char *query, const char *fragment) -> unsigned int {
unsigned int hash = 0;
while (*path)
hash = (hash * 131) + (*path++);
while (*query)
hash = (hash * 131) + (*query++);
while (*fragment)
hash = (hash * 131) + (*fragment++);
return hash;
});
UpstreamManager::upstream_add_server("abc.local", "192.168.2.100:8081");
UpstreamManager::upstream_add_server("abc.local", "192.168.2.100:8082");
UpstreamManager::upstream_add_server("abc.local", "192.168.10.10");
UpstreamManager::upstream_add_server("abc.local", "test.sogou.com:8080");
UpstreamManager::upstream_add_server("abc.local", "abc.sogou.com");
auto *http_task = WFTaskFactory::create_http_task("http://abc.local/sompath?a=1#flag100", 0, 0, nullptr);
http_task->start();
Basic principles
UpstreamManager::upstream_create_manual(
"xyz.cdn",
[](const char *path, const char *query, const char *fragment) -> unsigned int {
return atoi(fragment);
},
true, // If a blown target is selected, a second selection will be made
nullptr); // nullptr represents using the default consistent hash function of the framework in the second selection
UpstreamManager::upstream_add_server("xyz.cdn", "192.168.2.100:8081");
UpstreamManager::upstream_add_server("xyz.cdn", "192.168.2.100:8082");
UpstreamManager::upstream_add_server("xyz.cdn", "192.168.10.10");
UpstreamManager::upstream_add_server("xyz.cdn", "test.sogou.com:8080");
UpstreamManager::upstream_add_server("xyz.cdn", "abc.sogou.com");
auto *http_task = WFTaskFactory::create_http_task("http://xyz.cdn/sompath?key=somename#3", 0, 0, nullptr);
http_task->start();
Basic principles
UpstreamManager::upstream_create_weighted_random(
"simple.name",
true);//One main, one backup, nothing is different in this item
AddressParams address_params = ADDRESS_PARAMS_DEFAULT;
address_params.server_type = 0; /* 1 for main server */
UpstreamManager::upstream_add_server("simple.name", "main01.test.ted.bj.sogou", &address_params); // main
address_params.server_type = 1; /* 0 for backup server */
UpstreamManager::upstream_add_server("simple.name", "backup01.test.ted.gd.sogou", &address_params); //backup
auto *http_task = WFTaskFactory::create_http_task("http://simple.name/request", 0, 0, nullptr);
auto *redis_task = WFTaskFactory::create_redis_task("redis://simple.name/2", 0, nullptr);
redis_task->get_req()->set_query("MGET", {"key1", "key2", "key3", "key4"});
(*http_task * redis_task).start();
Basic principles
UpstreamManager::upstream_create_consistent_hash(
"abc.local",
nullptr);//nullptr represents using the default consistent hash function of the framework
AddressParams address_params = ADDRESS_PARAMS_DEFAULT;
address_params.server_type = 0;
address_params.group_id = 1001;
UpstreamManager::upstream_add_server("abc.local", "192.168.2.100:8081", &address_params);//main in group 1001
address_params.server_type = 1;
address_params.group_id = 1001;
UpstreamManager::upstream_add_server("abc.local", "192.168.2.100:8082", &address_params);//backup for group 1001
address_params.server_type = 0;
address_params.group_id = 1002;
UpstreamManager::upstream_add_server("abc.local", "backup01.test.ted.bj.sogou", &address_params);//main in group 1002
address_params.server_type = 1;
address_params.group_id = 1002;
UpstreamManager::upstream_add_server("abc.local", "backup01.test.ted.gd.sogou", &address_params);//backup for group 1002
address_params.server_type = 1;
address_params.group_id = -1;
UpstreamManager::upstream_add_server("abc.local", "test.sogou.com:8080", &address_params);//backup with no group mean backup for all groups and no group
UpstreamManager::upstream_add_server("abc.local", "abc.sogou.com");//main, no group
auto *http_task = WFTaskFactory::create_http_task("http://abc.local/service/method", 0, 0, nullptr);
http_task->start();
Basic principles
UpstreamManager::upstream_create_vnswrr("nvswrr.random");
AddressParams address_params = ADDRESS_PARAMS_DEFAULT;
address_params.weight = 3;//weight is 3
UpstreamManager::upstream_add_server("nvswrr.random", "192.168.2.100:8081", &address_params);//weight is 3
address_params.weight = 2;//weight is 2
UpstreamManager::upstream_add_server("nvswrr.random", "192.168.2.100:8082", &address_params);//weight is 2
UpstreamManager::upstream_add_server("nvswrr.random", "abc.sogou.com");//weight is 1
auto *http_task = WFTaskFactory::create_http_task("http://nvswrr.random:9090", 0, 0, nullptr);
http_task->start();
When the URIHost of the url that initiates the request is filled with UpstreamName, it is regarded as a request to the Upstream corresponding to the name, and then it will be selected from the set of Addresses recorded by the Upstream:
Round-robin/weighted-round-robin: regarded as equivalent to [1], not available for now
The framework recommends common users to use strategy [2], which can ensure that the cluster has good fault tolerance and scalability
For complex scenarios, advanced users can use strategy [3] to customize complex selection logic
struct EndpointParams
{
size_t max_connections;
int connect_timeout;
int response_timeout;
int ssl_connect_timeout;
bool use_tls_sni;
};
static constexpr struct EndpointParams ENDPOINT_PARAMS_DEFAULT =
{
.max_connections = 200,
.connect_timeout = 10 * 1000,
.response_timeout = 10 * 1000,
.ssl_connect_timeout = 10 * 1000,
.use_tls_sni = false,
};
struct AddressParams
{
struct EndpointParams endpoint_params;
unsigned int dns_ttl_default;
unsigned int dns_ttl_min;
unsigned int max_fails;
unsigned short weight;
int server_type; /* 0 for main and 1 for backup. */
int group_id;
};
static constexpr struct AddressParams ADDRESS_PARAMS_DEFAULT =
{
.endpoint_params = ENDPOINT_PARAMS_DEFAULT,
.dns_ttl_default = 12 * 3600,
.dns_ttl_min = 180,
.max_fails = 200,
.weight = 1, // only for main of UPSTREAM_WEIGHTED_RANDOM
.server_type = 0,
.group_id = -1,
};
Each address can be configured with custom parameters:
Mean time to repair (MTTR) is the average value of the repair time when the product changes from a fault state to a working state.
Service avalanche effect is a phenomenon in which "service caller failure" (result) is caused by "service provider's failure" (cause), and the unavailability is amplified gradually/level by level
If it is not controlled effectively, the effect will not converge, but will be amplified geometrically, just like an avalanche, that’s why it is called avalanche effect
Description of the phenomenon: at first it is just a small service or module abnormality/timeout, causing abnormality/timeout of other downstream dependent services, then causing a chain reaction, eventually leading to paralysis of most or all services
As the fault is repaired, the effect will disappear, so the duration of the effect is usually equal to MTTR
When the error or abnormal touch of a certain target meets the preset threshold condition, the target is temporarily considered unavailable, and the target is removed, namely fuse is started and enters the fuse period
After the fuse duration reaches MTTR duration, turn into half-open status, (attempt to) restore the target
If all targets are found fused whenever recovering one target, all targets will be restored at the same time
Fuse mechanism strategy can effectively prevent avalanche effect
MTTR=30 seconds, which is temporarily not configurable, but we will consider opening it to be configured by users in the future.
When the number of consecutive failures of a certain Address reaches the set upper limit (200 times by default), this Address will be blown, MTTR=30 seconds.
During the fusing period, once the Address is selected by the strategy, Upstream will decide whether to try other Addresses and how to try according to the specific configuration
Please note that if one of the following 1-4 scenarios is met, the communication task will get an error of WFT_ERR_UPSTREAM_UNAVAILABLE = 1004:
Weight random strategy, all targets are in the fusing period
Consistent hash strategy, all targets are in the fusing period
Manual strategy and try_another==true, all targets are in the fusing period
Manual strategy and try_another==false, and all the following three conditions shall meet at the same time:
1). The main selected by the select function is in the fusing period, and all free devices are in the fusing period
2). The main is a free main, or other targets in the group where the main is located are all in the fusing period
3). All free devices are in the fusing period
Priority is given to the port number explicitly configured on the Upstream Address
If not, select the port number explicitly configured in the request url
If none, use the default port number of the protocol
Configure UpstreamManager::upstream_add_server("my_proxy.name", "192.168.2.100:8081");
Request http://my_proxy.name:456/test.html => http://192.168.2.100:8081/test.html
Request http://my_proxy.name/test.html => http://192.168.2.100:8081/test.html
Configure UpstreamManager::upstream_add_server("my_proxy.name", "192.168.10.10");
Request http://my_proxy.name:456/test.html => http://192.168.10.10:456/test.html
Request http://my_proxy.name/test.html => http://192.168.10.10:80/test.html
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Опубликовать ( 0 )