Максимальное количество сокетов в Linux

Кажется, что сервер ограничен в ~32720 розетки... Я пробовал каждое известное изменение переменной, чтобы поднять этот предел. Но сервер остается ограниченным в 32720 открытом сокете, даже если есть еще 4Go свободной памяти и 80% бездействующего процессора...

вот конфигурация

~# ulimit -a
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 63931
max locked memory       (kbytes, -l) 64
max memory size         (kbytes, -m) unlimited
open files                      (-n) 798621
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 2048
cpu time               (seconds, -t) unlimited
max user processes              (-u) 63931
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

net.netfilter.nf_conntrack_max = 999999
net.ipv4.netfilter.ip_conntrack_max = 999999
net.nf_conntrack_max = 999999

какие мысли ?

8 ответов


Если вы имеете дело с openssl и потоками, проверьте /proc/sys/vm/max_map_count и попробуйте поднять его.


о каком сервере вы говорите ? Возможно, он имеет жестко закодированный max или работает в других пределах (max threads/out of address space и т. д.)

http://www.metabrew.com/article/a-million-user-comet-application-with-mochiweb-part-1 имеет некоторую настройку, необходимую для достижения большого количества соединений, но это не помогает, если серверное приложение ограничивает его тем или иным образом.


в IPV4 уровень TCP имеет 16 бит для порта назначения и 16 бит для порта источника.

см.http://en.wikipedia.org/wiki/Transmission_Control_Protocol

видя, что ваш предел 32K, я ожидал бы, что вы действительно видите предел исходящих TCP-соединений, которые вы можете сделать. Вы должны иметь возможность получить максимум 65K сокетов (это будет предел протокола). Это ограничение для общего числа именованных соединений. К счастью, привязка порта для входящих подключений использует только 1. Но если вы пытаетесь проверить количество соединений с одной машины, вы можете иметь только 65K общих исходящих соединений (для TCP). Для проверки количества входящих подключений потребуется несколько компьютеров.

Примечание: Вы можете вызвать сокет (AF_INET,...) до количества доступных файловых дескрипторов, но вы не можете связать их без увеличения числа доступных портов. Чтобы увеличить диапазон, сделайте это:

Эхо "1024 65535" > /proc/sys / net/ipv4/ip_local_port_range (cat, чтобы увидеть, что у вас есть в настоящее время-по умолчанию 32768 до 61000)

возможно, пришло время для нового протокола TCP, который позволит 32 бита для исходного и dest портов? Но сколько приложений действительно нужно более 65 тысяч исходящих подключений?

следующее позволит 100 000 входящих подключений на linux mint 16 (64 бит) (вы должны запустить его как root, чтобы установить пределы)

#include <stdio.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/ip.h>

void ShowLimit()
{
   rlimit lim;
   int err=getrlimit(RLIMIT_NOFILE,&lim);
   printf("%1d limit: %1ld,%1ld\n",err,lim.rlim_cur,lim.rlim_max);
}

main()
{
   ShowLimit();

   rlimit lim;
   lim.rlim_cur=100000;
   lim.rlim_max=100000;
   int err=setrlimit(RLIMIT_NOFILE,&lim);
   printf("set returned %1d\n",err);

   ShowLimit();

   int sock=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
   sockaddr_in maddr;
   maddr.sin_family=AF_INET;
   maddr.sin_port=htons(80);
   maddr.sin_addr.s_addr=INADDR_ANY;

   err=bind(sock,(sockaddr *) &maddr, sizeof(maddr));

   err=listen(sock,1024);

   int sockets=0;
   while(true)
   {
      sockaddr_in raddr;
      socklen_t rlen=sizeof(raddr);
      err=accept(sock,(sockaddr *) &raddr,&rlen);
      if(err>=0)
      {
        ++sockets;
        printf("%1d sockets accepted\n",sockets);
      }
   }
}

Если вы рассматриваете приложение, где вы считаете, что вам нужно открыть тысячи сокетов, вы обязательно захотите прочитать о Проблема C10k. На этой странице обсуждаются многие проблемы, с которыми вы столкнетесь при увеличении количества клиентских подключений к одному серверу.


в Gnu+Linux максимум-это то, что вы написали. Это число (вероятно) указано где-то в стандартах сети. Сомневаюсь, что тебе нужно так много розеток. Вы должны оптимизировать способ использования сокетов, а не создавать десятки все время.


чистая/сокет.c fd выделяется в sock_alloc_fd (), который вызывает get_unused_fd ().

глядя на linux/fs / файл.c, единственное ограничение на количество fd-это sysctl_nr_open, ограниченном

int sysctl_nr_open_max = 1024 * 1024; /* raised later */

/// later...
sysctl_nr_open_max = min((size_t)INT_MAX, ~(size_t)0/sizeof(void *)) &
                         -BITS_PER_LONG;

и может быть прочитано с помощью sysctl fs.nr_open что дает 1M по умолчанию здесь. Так что fd, вероятно, не ваша проблема.

редактировать вы, вероятно, также проверили это, но не могли бы вы поделиться выводом

#include <sys/time.h>
#include <sys/resource.h>
int main() {
    struct rlimit limit;
    getrlimit(RLIMIT_NOFILE,&limit);
    printf("cur: %d, max: %d\n",limit.rlim_cur,limit.rlim_max);
}

С нас?


вообще иметь слишком много живых соединений-это плохо. Однако все зависит от приложения и шаблонов, с которыми оно взаимодействует со своими клиентами.

Я полагаю, что существует шаблон, когда клиенты должны быть постоянно асинхронно подключены, и это единственный способ работы распределенного решения.

Assumimg нет узких мест в памяти / cpu / сети для текущей нагрузки, и имея в виду, что оставить простое открытое соединение-единственный способ распределенные приложения потребляют меньше ресурсов (например, время подключения и общая/Пиковая память), общая производительность сети ОС может быть выше, чем использование лучших практик, которые мы все знаем.

хороший вопрос, и он нуждается в решении. Проблема в том, что никто не может на это ответить. Я бы предложил использовать технику divide & conquer, и когда узкое место будет найдено, вернитесь к нам.

пожалуйста, разберите приложение на тестовом стенде, и вы найдете узкое место.


Проверьте реальные пределы запущенного процесса.

cat /proc/{pid}/limits

max для nofiles определяется ядром, следующее, поскольку root увеличит max до 100 000 "файлов", т. е. 100k CC

echo 100000 > /proc/sys/fs/file-max

чтобы сделать его постоянным edit/etc / sysctl.conf

fs.file-max = 100000

затем вам нужно, чтобы сервер запрашивал больше открытых файлов, это отличается от сервера. Например, в nginx вы устанавливаете

worker_rlimit_nofile 100000;

перезагрузите nginx и проверьте /proc / {pid} / limits

чтобы проверить это, вам нужно 100 000 сокетов в вашем клиенте, вы ограничены в тестировании количеством портов в TCP на IP-адрес.

для увеличения диапазона локальных портов до максимума...

echo "1024 65535" > /proc/sys/net/ipv4/ip_local_port_range

это дает вам ~64000 портов для тестирования.

если этого недостаточно, вам нужно больше IP-адресов. При тестировании на localhost вы можете привязать источник / клиент к IP, отличному от 127.0.0.1 / localhost.

например вы можете привязать тестовые клиенты к IPs, случайным образом выбранным от 127.0.0.1 до 127.0.0.5

используя apache-bench, вы установите

-B 127.0.0.x

сокеты Nodejs будут использовать

localAddress

/ etc / security / limits.conf настраивает PAM: обычно это не имеет значения для сервера.

если сервер проксирует запросы, используя TCP, например, upstream или mod_proxy, сервер ограничен ip_local_port_range. Это легко может быть предел 32,000.