Muchikamu chino, tichatarisa ins uye kunze kweI / O reactor uye kuti inoshanda sei, nyora kushandiswa mune isingasviki mitsara ye200 yekodhi, uye ita nyore HTTP server process pamusoro pemamiriyoni makumi mana ekukumbira / min.
Foreword
Chinyorwa chakanyorwa kuti chibatsire kunzwisisa kushanda kweI / O reactor, uye saka kunzwisisa njodzi kana uchiishandisa.
Kuvharisa I/O mashandiro kumisa mushandisi kuyerera kusvikirakusvikira OS yakwana defragments inouya IP mapaketi kuenda kurwizi (TCP, kugamuchira data) kana hakuzove nenzvimbo yakakwana inowanikwa mukati mekunyora mabuffers kuti utumire unotevera kuburikidza NIC (kutumira data).
Sistimu yekusarudza kupfuuridza nguva inozivisa chirongwa icho OS kare defragmented IP packets (TCP, reception data) kana nzvimbo yakakwana mumabhafa ekunyora emukati kare iripo (kutumira data).
typedef struct reactor Reactor;
/*
* Указатель на функцию, которая будет вызываться I/O реактором при поступлении
* события от системного селектора.
*/
typedef void (*Callback)(void *arg, int fd, uint32_t events);
/*
* Возвращает `NULL` в случае ошибки, не-`NULL` указатель на `Reactor` в
* противном случае.
*/
Reactor *reactor_new(void);
/*
* Освобождает системный селектор, все зарегистрированные сокеты в данный момент
* времени и сам I/O реактор.
*
* Следующие функции возвращают -1 в случае ошибки, 0 в случае успеха.
*/
int reactor_destroy(Reactor *reactor);
int reactor_register(const Reactor *reactor, int fd, uint32_t interest,
Callback callback, void *callback_arg);
int reactor_deregister(const Reactor *reactor, int fd);
int reactor_reregister(const Reactor *reactor, int fd, uint32_t interest,
Callback callback, void *callback_arg);
/*
* Запускает цикл событий с тайм-аутом `timeout`.
*
* Эта функция передаст управление вызывающему коду если отведённое время вышло
* или/и при отсутствии зарегистрированных сокетов.
*/
int reactor_run(const Reactor *reactor, time_t timeout);
<ДАННЫЕ> - data yakakumbirwa nemushandisi. Muchiitiko chedu, iyi ndiyo nzira inoenda kumufananidzo mukati HTML.
faira http_server.c (single threaded server) inosanganisira faira common.h, iyo ine zvinotevera basa prototypes:
Ratidza basa prototypes zvakafanana.h
/*
* Обработчик событий, который вызовется после того, как сокет будет
* готов принять новое соединение.
*/
static void on_accept(void *arg, int fd, uint32_t events);
/*
* Обработчик событий, который вызовется после того, как сокет будет
* готов отправить HTTP ответ.
*/
static void on_send(void *arg, int fd, uint32_t events);
/*
* Обработчик событий, который вызовется после того, как сокет будет
* готов принять часть HTTP запроса.
*/
static void on_recv(void *arg, int fd, uint32_t events);
/*
* Переводит входящее соединение в неблокирующий режим.
*/
static void set_nonblocking(int fd);
/*
* Печатает переданные аргументы в stderr и выходит из процесса с
* кодом `EXIT_FAILURE`.
*/
static noreturn void fail(const char *format, ...);
/*
* Возвращает файловый дескриптор сокета, способного принимать новые
* TCP соединения.
*/
static int new_server(bool reuse_port);
Iyo inoshanda macro inotsanangurwa zvakare SAFE_CALL() uye basa racho rinotsanangurwa fail(). Iyo macro inofananidza kukosha kwekutaura nekanganiso, uye kana mamiriro acho ari echokwadi, anodana basa fail():
#define SAFE_CALL(call, error)
do {
if ((call) == error) {
fail("%s", #call);
}
} while (false)
kana reuse_port yakaenzana true, ipapo basa iri richagadzirisa socket ine sarudzo SO_REUSEPORT kuburikidza setsockopt()kushandisa chiteshi chimwe chete munzvimbo ine tambo dzakawanda (ona chikamu "Multi-threaded server").
static void on_recv(void *arg, int fd, uint32_t events) {
RequestBuffer *buffer = arg;
// Принимаем входные данные до тех пор, что recv возвратит 0 или ошибку
ssize_t nread;
while ((nread = recv(fd, buffer->data + buffer->size,
REQUEST_BUFFER_CAPACITY - buffer->size, 0)) > 0)
buffer->size += nread;
// Клиент оборвал соединение
if (nread == 0) {
SAFE_CALL(reactor_deregister(reactor, fd), -1);
SAFE_CALL(close(fd), -1);
request_buffer_destroy(buffer);
return;
}
// read вернул ошибку, отличную от ошибки, при которой вызов заблокирует
// поток
if (errno != EAGAIN && errno != EWOULDBLOCK) {
request_buffer_destroy(buffer);
fail("read");
}
// Получен полный HTTP запрос от клиента. Теперь регистрируем обработчика
// событий для отправки данных
if (request_buffer_is_complete(buffer)) {
request_buffer_clear(buffer);
SAFE_CALL(reactor_reregister(reactor, fd, EPOLLOUT, on_send, buffer),
-1);
}
}
Chiitiko Handler on_send() inodanwa mushure mekunge OS yagadzira chiitiko EPOLLOUT, zvichireva kuti kubatana kwakanyoreswa on_recv(), yakagadzirira kutumira data. Iri basa rinotumira mhinduro yeHTTP ine HTML ine mufananidzo kune mutengi uyezve inoshandura chiitiko chibatiso kudzokera on_recv().
Sezvambotaurwa pamusoro, iyo I / O reactor inogona kugadzirwa mune dzakasiyana tambo, nekudaro uchishandisa ese CPU cores. Ngatishandise nzira iyi mukuita:
sei noted mune zvakataurwa, iyi bvunzo yekuita hairatidze maitiro eI / O reactor pasi pemitoro chaiyo, nekuti kanenge nguva dzese sevha inodyidzana nedatabase, inoburitsa matanda, inoshandisa cryptography ne. TLS nezvimwewo, semugumisiro wekuti mutoro unova usina kufanana (simba). Miedzo pamwe chete neyechitatu-bato zvikamu zvichaitwa muchinyorwa nezve I/O proactor.
Zvakaipa zveI/O reactor
Iwe unofanirwa kunzwisisa kuti iyo I / O reactor haina zvipingamupinyi zvayo, zvinoti:
Kushandisa I/O reactor munzvimbo ine tambo dzakawanda kwakatooma, nekuti iwe uchafanirwa kugadzirisa nemaoko kuyerera.
Kudzidzira kunoratidza kuti muzviitiko zvizhinji mutoro wacho hauna kufanana, izvo zvinogona kutungamirira kune imwe tambo yekutema apo imwe iri kubatikana nebasa.
Kana mumwe mugadziri wechiitiko akavhara tambo, ipapo iyo system yekusarudza pachayo inovharisa, izvo zvinogona kutungamirira kune zvakaoma-ku-kuwana-zvipembenene.
Anogadzirisa matambudziko aya Ini/O mutambi, iyo inowanzove ine scheduler inogovera zvakaenzana mutoro kune dziva reshinda, uye ine zvakare iri nyore API. Tichazotaura nezvazvo gare gare, mune chimwe chinyorwa changu.
mhedziso
Apa ndipo pakasvika rwendo rwedu kubva padzidziso yakananga kuprofiler exhaust.
Iwe haufanirwe kugara pane izvi, nekuti kune dzimwe dzakawanda dzakaenzana dzinonakidza nzira dzekunyora network software ine mazinga akasiyana ekureruka uye kumhanya. Zvinonakidza, mumaonero angu, zvinongedzo zvinopihwa pazasi.