フタなしカンヅメ

徒然なるままに @happytar0

LighttpdのFD_SETSIZE【続】

以前の記事で以下のようなエラーがでるということを書きましたが、ちょっと嘘ついてたみたいというか、適当すぎたのでよく調べてみました。

2009-08-31 14:05:37: (server.c.1337) [note] sockets enabled again
2009-08-31 14:07:16: (server.c.1383) [note] sockets disabled, connection limit reached

FD_SETSIZEを変更してビルドし直したのですが、またエラーが出るようになりました。色々調べていると、server.max-connectionsなるものがあるらしい。こいつにはまったく手をつけていませんでした。以下のように設定を変更。

# max-fdsは、max-connectionsの2倍以上の値が必要
server.max-fds = 8192
server.max-connections = 4096

max-connectionsは、未設定の場合、(max-fds / 3)の値が適用されるようです。ということは1365くらいになってたってことか。

それでよくよくソースコードを見てみると、今回の場合は、そもそもがFD_SETSIZEを変更してビルドする必要はなかったようです。
event-handlerという設定があるのですが、こちらはデフォルトで「0」が設定されているようなので、以下の条件に一致します。

        if (srv->srvconf.event_handler->used == 0) {
                /* choose a good default
                 *
                 * the event_handler list is sorted by 'goodness'
                 * taking the first available should be the best solution
                 */
                srv->event_handler = event_handlers[0].et;

                if (FDEVENT_HANDLER_UNSET == srv->event_handler) {
                        log_error_write(srv, __FILE__, __LINE__, "s",
                                        "sorry, there is no event handler for this system");

                        return -1;
                }
        } else {

event_handlersの最初の値が使われるようです。

        struct ev_map { fdevent_handler_t et; const char *name; } event_handlers[] =
        {
                /* - poll is most reliable
                 * - select works everywhere
                 * - linux-* are experimental
                 */
#ifdef USE_POLL
                { FDEVENT_HANDLER_POLL,           "poll" },
#endif          
#ifdef USE_SELECT
                { FDEVENT_HANDLER_SELECT,         "select" },
#endif          
#ifdef USE_LINUX_EPOLL
                { FDEVENT_HANDLER_LINUX_SYSEPOLL, "linux-sysepoll" },
#endif          
#ifdef USE_LINUX_SIGIO
                { FDEVENT_HANDLER_LINUX_RTSIG,    "linux-rtsig" },
#endif          
#ifdef USE_SOLARIS_DEVPOLL
                { FDEVENT_HANDLER_SOLARIS_DEVPOLL,"solaris-devpoll" },
#endif          
#ifdef USE_FREEBSD_KQUEUE
                { FDEVENT_HANDLER_FREEBSD_KQUEUE, "freebsd-kqueue" },
                { FDEVENT_HANDLER_FREEBSD_KQUEUE, "kqueue" },
#endif          
                { FDEVENT_HANDLER_UNSET,          NULL }
        }; 

Linux環境だったので、poll、select、linux-sysepoll、linux-rtsigから選択できる感じなのでしょうか?デフォルトでは、pollが使用されるようですが、カーネルが2.6以上の場合は、epollを使うと効率的らしいです。
Server.event-handlerDetails - Lighttpd - lighty labs
ということは、デフォルトでpollを使っているならば、初期値は以下の4096が適用される感じになるはず。

        if (srv->event_handler == FDEVENT_HANDLER_SELECT) {
                /* select limits itself
                 *
                 * as it is a hard limit and will lead to a segfault we add some safety
                 * */
                srv->max_fds = FD_SETSIZE - 200;
        } else {
                srv->max_fds = 4096;
        }

さらに、max-fdsを設定しているならば、以下のように設定された値がそのまま使われるようです。

                if (use_rlimit && srv->srvconf.max_fds) {
                        /* set rlimits */

                        rlim.rlim_cur = srv->srvconf.max_fds;
                        rlim.rlim_max = srv->srvconf.max_fds;
                        
                        if (0 != setrlimit(RLIMIT_NOFILE, &rlim)) {
                                log_error_write(srv, __FILE__, __LINE__,
                                                "ss", "couldn't set 'max filedescriptors'",
                                                strerror(errno));
                                return -1;
                        }
                }
                
                if (srv->event_handler == FDEVENT_HANDLER_SELECT) { 
                        srv->max_fds = rlim.rlim_cur < FD_SETSIZE - 200 ? rlim.rlim_cur : FD_SETSIZE - 200;
                } else {
                        srv->max_fds = rlim.rlim_cur;
                }

ということなので、event-handlerを特に設定していない状態で、selectを指定していないのであれば、FD_SETSIZEを変更して、ビルドし直す必要はなかった・・・でした。
あとは、max-workerなるものもあるようで、負荷が増えてきたらこいつも設定してあげるといいのじゃろか。