| Алгоритм | Механизм отправки запросов к серверам | Когда использовать |
|---|---|---|
| Round Robin | В порядке очереди | В базовом варианте, если нет каких-то специальных требований |
| IP Hash, или Sticky sessions | На тот же сервер, откуда пришёл запрос, по хэшу IP-адреса пользователя | Чаще всего в stateful-приложениях |
| Least Connection | На наименее загруженный сервер | Микросервисная архитектура |
| Least Response Time | На сервер с наименьшим средним временем обработки ответа | Микросервисная архитектура |
| Least Bandwidth | На сервер с наименьшим трафиком | Микросервисная архитектура |
Round Robin. Эта стратегия последовательно распределяет запросы между доступными экземплярами.
upstream application{
least_conn; #алгоритм
server 195.2.2.11; # ip-адреса серверов
server 195.2.2.12;
server 195.2.2.13;
}
server {
listen 80; #порт nginx
location / {
# назначение трафика
proxy_pass http://application;
}
} #Возьмём официальный репозиторий APISIX
git clone https://github.com/apache/apisix-docker.git
#Перейти в папку example, нам не особо интересен дашборд сейчас
cd example consul:
image: consul:1.15.1
container_name: consul
restart: always
networks:
- apisix
ports:
- '8500:8500'
command: 'agent -server -bootstrap-expect=1 -node=agent-one -client 0.0.0.0 -log-level info -data-dir=/consul/data -enable-script-checks' version: "3"
services:
#api gateway
apisix:
image: apache/apisix:3.9.0-debian
restart: always
volumes:
- ./apisix_conf/config.yaml:/usr/local/apisix/conf/config.yaml:ro
depends_on:
- etcd
##network_mode: host
ports:
- "9180:9180/tcp"
- "9080:9080/tcp"
- "9091:9091/tcp"
- "9443:9443/tcp"
- "9092:9092/tcp"
networks:
apisix:
#база данных типа Key-value для APISIX
etcd:
image: bitnami/etcd:3.5.11
restart: always
volumes:
- etcd_data:/bitnami/etcd
environment:
ETCD_ENABLE_V2: "true"
ALLOW_NONE_AUTHENTICATION: "yes"
ETCD_ADVERTISE_CLIENT_URLS: "http://etcd:2379"
ETCD_LISTEN_CLIENT_URLS: "http://0.0.0.0:2379"
ports:
- "2379:2379/tcp"
networks:
apisix:
#сервис для проверки
web1:
image: nginx:1.19.0-alpine
restart: always
volumes:
- ./upstream/web1.conf:/etc/nginx/nginx.conf
ports:
- "9081:80/tcp"
environment:
- NGINX_PORT=80
networks:
apisix:
# сервис для проверки
web2:
image: nginx:1.19.0-alpine
restart: always
volumes:
- ./upstream/web2.conf:/etc/nginx/nginx.conf
ports:
- "9082:80/tcp"
environment:
- NGINX_PORT=80
networks:
apisix:
consul:
image: consul:1.15.1
container_name: consul
restart: always
networks:
- apisix
ports:
- '8500:8500'
command: 'agent -server -bootstrap-expect=1 -node=agent-one -client 0.0.0.0 -log-level info -data-dir=/consul/data -enable-script-checks'
networks:
apisix:
driver: bridge
volumes:
etcd_data:
driver: local
apisix:
node_listen: 9080 # APISIX listening port
enable_ipv6: false
enable_control: true
control:
ip: "0.0.0.0"
port: 9092
deployment:
admin:
allow_admin: # https://nginx.org/en/docs/http/ngx_http_access_module.html#allow
- 0.0.0.0/0 # We need to restrict ip access rules for security. 0.0.0.0/0 is for test.
admin_key:
- name: "admin"
key: edd1c9f034335f136f87ad84b625c8f1
role: admin # admin: manage all configuration data
- name: "viewer"
key: 4054f7cf07e344346cd3f287985e76a2
role: viewer
etcd:
host: # it's possible to define multiple etcd hosts addresses of the same etcd cluster.
- "http://etcd:2379" # multiple etcd address
prefix: "/apisix" # apisix configurations prefix
timeout: 30 # 30 seconds
plugin_attr:
prometheus:
export_addr:
ip: "0.0.0.0"
port: 9091
**discovery:
consul:
servers:
- "http://consul:8500"
dump:
path: "logs/consul.dump"
expire: 2592000**
docker-compose up -d docker inspect -f='{{.Name}} - {{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' $( docker ps -aq) | grep web curl "http://127.0.0.1:8500/v1/agent/service/register" -X PUT \
-H "Content-Type: application/json" \
-d '{
"ID": "svc-a1",
"Name": "svc-a",
"Tags": ["sample_web_svc", "v1"],
"Address": "'10.89.0.2'",
"Port": 80,
"Weights": {
"Passing": 10,
"Warning": 1
}
}'
curl "http://127.0.0.1:8500/v1/agent/service/register" -X PUT \
-H "Content-Type: application/json" \
-d '{
"ID": "svc-a2",
"Name": "svc-a",
"Tags": ["sample_web_svc", "v1"],
"Address": "'10.89.0.3'",
"Port": 80,
"Weights": {
"Passing": 10,
"Warning": 1
}
}' "truetrue%" curl "http://127.0.0.1:8500/v1/catalog/service/svc-a" | jq [
{
"ID": "1f42ff08-f451-5733-a62c-990011b0adf5",
"Node": "agent-one",
"Address": "10.89.0.5",
"Datacenter": "dc1",
"TaggedAddresses": {
"lan": "10.89.0.5",
"lan_ipv4": "10.89.0.5",
"wan": "10.89.0.5",
"wan_ipv4": "10.89.0.5"
},
"NodeMeta": {
"consul-network-segment": ""
},
"ServiceKind": "",
"ServiceID": "svc-a1",
"ServiceName": "svc-a",
"ServiceTags": [
"sample_web_svc",
"v1"
],
"ServiceAddress": "10.89.0.2",
"ServiceTaggedAddresses": {
"lan_ipv4": {
"Address": "10.89.0.2",
"Port": 80
},
"wan_ipv4": {
"Address": "10.89.0.2",
"Port": 80
}
},
"ServiceWeights": {
"Passing": 10,
"Warning": 1
},
"ServiceMeta": {},
"ServicePort": 80,
"ServiceSocketPath": "",
"ServiceEnableTagOverride": false,
"ServiceProxy": {
"Mode": "",
"MeshGateway": {},
"Expose": {}
},
"ServiceConnect": {},
"CreateIndex": 51,
"ModifyIndex": 51
},
{
"ID": "1f42ff08-f451-5733-a62c-990011b0adf5",
"Node": "agent-one",
"Address": "10.89.0.5",
"Datacenter": "dc1",
"TaggedAddresses": {
"lan": "10.89.0.5",
"lan_ipv4": "10.89.0.5",
"wan": "10.89.0.5",
"wan_ipv4": "10.89.0.5"
},
"NodeMeta": {
"consul-network-segment": ""
},
"ServiceKind": "",
"ServiceID": "svc-a2",
"ServiceName": "svc-a",
"ServiceTags": [
"sample_web_svc",
"v1"
],
"ServiceAddress": "10.89.0.3",
"ServiceTaggedAddresses": {
"lan_ipv4": {
"Address": "10.89.0.3",
"Port": 80
},
"wan_ipv4": {
"Address": "10.89.0.3",
"Port": 80
}
},
"ServiceWeights": {
"Passing": 10,
"Warning": 1
},
"ServiceMeta": {},
"ServicePort": 80,
"ServiceSocketPath": "",
"ServiceEnableTagOverride": false,
"ServiceProxy": {
"Mode": "",
"MeshGateway": {},
"Expose": {}
},
"ServiceConnect": {},
"CreateIndex": 52,
"ModifyIndex": 52
}
] edd1c9f034335f136f87ad84b625c8f1. curl http://127.0.0.1:9092/v1/discovery/consul/dump | jq
# результат
{
"services": {
"svc-a": [
{
"weight": 1,
"port": 80,
"host": "10.89.0.2"
},
{
"weight": 1,
"port": 80,
"host": "10.89.0.3"
}
]
},
"config": {
"keepalive": true,
"weight": 1,
"dump": {
"expire": 2592000,
"load_on_init": true,
"path": "logs/consul.dump"
},
"token": "",
"timeout": {
"connect": 2000,
"wait": 60,
"read": 2000
},
"fetch_interval": 3,
"sort_type": "origin",
"servers": [
"http://consul:8500"
]
}
} curl "http://127.0.0.1:9180/apisix/admin/routes" -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
{
"id": "consul-web-route",
"uri": "/consul/web/*",
"upstream": {
"service_name": "svc-a",
"discovery_type": "consul",
"type": "roundrobin"
}
}' | jq
#Получаем результат
{
"key": "/apisix/routes/consul-web-route",
"value": {
"status": 1,
"uri": "/consul/web/*",
"update_time": 1719606436,
"id": "consul-web-route",
"priority": 0,
"upstream": {
"scheme": "http",
"type": "roundrobin",
"pass_host": "pass",
"service_name": "svc-a",
"hash_on": "vars",
"discovery_type": "consul"
},
"create_time": 1719606436
}
} curl http://127.0.0.1:9180/apisix/admin/routes -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' | jq {
"list": [
{
"key": "/apisix/routes/consul-web-route",
"value": {
"upstream": {
"scheme": "http",
"discovery_type": "consul",
"pass_host": "pass",
"service_name": "svc-a",
"hash_on": "vars",
"type": "roundrobin"
},
"create_time": 1719606436,
"update_time": 1719606436,
"status": 1,
"priority": 0,
"uri": "/consul/web/*",
"id": "consul-web-route"
},
"modifiedIndex": 16,
"createdIndex": 16
}
],
"total": 1
} curl "http://127.0.0.1:9080/consul/web/" hello web2 hello web1