Nginx неравномерное распределение нагрузки в контейнерах - PullRequest
0 голосов
/ 27 марта 2019

Балансировка нагрузки Nginx (циклический перебор) выполняется неравномерно при запуске внутри контейнера, где она одинакова, когда nginx запускается непосредственно внутри виртуальной машины.

Я пробую пример приложения потоковой передачи gRPC на https://github.com/grpc/grpc/tree/v1.19.0/examples/python/route_guide.

Я изменил сервер, чтобы запустить 4 серверных процесса grpc, и, соответственно, изменил клиент так, чтобы он вызывал 4 разных процесса для попадания на сервер. Я только вызываю RouteChat из клиента, закомментировал оставшиеся функции. Клиент и сервер работают на разных виртуальных машинах в облаке Google.

route_guide_client.py

...
def run():
    # NOTE(gRPC Python Team): .close() is possible on a channel and should be
    # used in circumstances in which the with statement does not fit the needs
    # of the code.
    with grpc.insecure_channel('10.128.15.199:9999') as channel:
        stub = route_guide_pb2_grpc.RouteGuideStub(channel)
        #print("-------------- GetFeature --------------")
        #guide_get_feature(stub)
        #print("-------------- ListFeatures --------------")
        #guide_list_features(stub)
        #print("-------------- RecordRoute --------------")
        #guide_record_route(stub)
        print("-------------- RouteChat --------------")
        guide_route_chat(stub)


if __name__ == '__main__':
    logging.basicConfig()
    procs = 4
    for i in range(procs):
        p = multiprocessing.Process(target=run)
        p.start()
....

route_guide_server.py

   ........
    def serve(port,i):
        server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
        route_guide_pb2_grpc.add_RouteGuideServicer_to_server(
            RouteGuideServicer(), server)
        procs=4
        os.system("taskset -p -c %d %d" % (i % procs, os.getpid()))
        server.add_insecure_port('[::]:%d' % port)
        print("Server starting in port "+str(port)+" with cpu "+ str(i%procs))
        server.start()
        try:
            while True:
                time.sleep(_ONE_DAY_IN_SECONDS)
        except KeyboardInterrupt:
            server.stop(0)

    if __name__ == '__main__':
        logging.basicConfig()
        ports = []
        for i in range(9000,9004):
            ports.append(str(i))
        port_pool = cycle(ports)
        procs = 4
        for i in range(procs):


    p = multiprocessing.Process(target=serve,args=(int(next(port_pool)),i))
        p.start()
.........

nginx.conf

user www-data;
worker_processes 1;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;

events {
worker_connections 768;
# multi_accept on;
}

http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent"';

map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
upstream backend{
server localhost:9000 weight=1;
server localhost:9001 weight=1;
server localhost:9002 weight=1;
server localhost:9003 weight=1;
}

server {
listen 6666 http2; <<<<<<<<< On container I have set it to 9999

access_log /tmp/access.log main;
error_log /tmp/error.log error;

proxy_buffering off;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Scheme $scheme;
proxy_set_header Host $http_host;

location / {
grpc_pass grpc://backend;
}

}
} 

Сценарий 1: сервер работает на ВМ

$ python route_guide_server.py
pid 14287's current affinity list: 0-5
pid 14287's new affinity list: 2
pid 14288's current affinity list: 0-5
pid 14288's new affinity list: 3
pid 14286's current affinity list: 0-5
pid 14286's new affinity list: 1
pid 14285's current affinity list: 0-5
pid 14285's new affinity list: 0
Server starting in port 9003 with cpu 3
Server starting in port 9002 with cpu 2
Server starting in port 9001 with cpu 1
Server starting in port 9000 with cpu 0

Теперь я запускаю клиент на другой виртуальной машине.

$ python3 route_guide_client.py
...........
.......

На сервере мы видим, что запросы равномерно распределены между всеми 4 процессами сервера, работающими на разных портах. Например, на сервере для вышеуказанного вызова клиента выводится

Serving route chat request using 14285 << These are PIDs of processes that are bound to different server ports.
Serving route chat request using 14286
Serving route chat request using 14287
Serving route chat request using 14288

Сценарий 2: сервер работает в контейнере

Теперь я запускаю контейнер на виртуальной машине сервера, устанавливаю и настраиваю nginx таким же образом внутри контейнера и использую тот же файл конфигурации nginx за исключением того, что затем прослушивает порт nginx сервера.

$ sudo docker run -p 9999:9999 --cpus=4 grpcnginx:latest
...............

root@b81bb72fcab2:/# python3 route_guide_server.py
pid 71's current affinity list: 0-5
pid 71's new affinity list: 0
Server starting in port 9000 with cpu 0
pid 74's current affinity list: 0-5
pid 74's new affinity list: 3
Server starting in port 9003 with cpu 3
pid 72's current affinity list: 0-5
pid 72's new affinity list: 1
pid 73's current affinity list: 0-5
pid 73's new affinity list: 2
Server starting in port 9001 with cpu 1
Server starting in port 9002 with cpu 2

На клиентской ВМ

$ python3 route_guide_client.py
............
..............

Теперь на сервере мы видим, что запросы обслуживаются только 2 портами / процессами.

Serving route chat request using 71
Serving route chat request using 72
Serving route chat request using 71
Serving route chat request using 72

Запрос справки для решения проблемы распределения нагрузки внутри контейнера.

...