Написание директора
Varnish уже предоставляет набор директоров общего назначения, а начиная с Varnish 4, он включён в встроенный модуль Директора VMOD — Модуль директоров Varnish. Написание директора сводится к написанию VMOD, используя соответствующие структуры данных и API. Вы можете написать собственного директора, если ни один из встроенных не подходит под ваши нужды, а начиная с Varnish 4.1, вы даже можете написать собственные бэкэнды.
Бэкэнды можно разделить на следующие категории:
- статические: встроенные бэкэнды, объявленные в VCL
- динамические: встроенные бэкэнды, созданные VMOD
- пользовательские: бэкэнды, созданные и полностью управляемые VMOD
Бэкэнды и директоры
Интуитивное разделение бэкенда и директора — это конечная точка для первого и балансировщик нагрузки для второго, но фактическая реализация несколько сложнее. VMOD может принимать аргументы бэкенда и возвращать бэкэнды в VCL (см. Типы данных VCL и C), но базовый тип C — struct director — то есть VCL_BACKEND typedef. Внутри директор — это обобщённое понятие, а бэкенд — это разновидность директора.
Граница между ними несколько размыта, давайте посмотрим на код:
// VRT interface from vrt.h
struct vdi_methods {
unsigned magic;
#define VDI_METHODS_MAGIC 0x4ec0c4bb
const char *type;
vdi_http1pipe_f *http1pipe;
vdi_healthy_f *healthy;
vdi_resolve_f *resolve;
vdi_gethdrs_f *gethdrs;
vdi_getip_f *getip;
vdi_finish_f *finish;
vdi_event_f *event;
vdi_release_f *release;
vdi_destroy_f *destroy;
vdi_panic_f *panic;
vdi_list_f *list;
};
struct director {
unsigned magic;
#define DIRECTOR_MAGIC 0x3336351d
void *priv;
char *vcl_name;
struct vcldir *vdir;
struct lock *mtx;
};
Директора можно сформулировать как:
- имеющий определённый
typeс набором операций, одинаковых для всех экземпляров этого конкретного типа - некоторые атрибуты, специфичные для экземпляра, такие как
vcl_nameиtype-специфичные данные
Разница между директором балансировки нагрузки и директором бэкенда заключается в основном в функциях, которые они будут реализовывать.
Основные шаги по реализации директора:
- реализовать необходимые функции
-
заполнить
struct vdi_methodsименем вашего типа директора и указателями на ваши функцииСуществование обратного вызова
healthyозначает, что у директора есть возможность динамически определять состояние его работоспособности. - в вашем конструкторе или другой процедуре инициализации выделить и инициализировать состояние конфигурации, специфичное для вашего директора (т.е. частные данные), и вызовите
VRT_AddDirector()с вашимstruct vdi_methods, указателем на ваше состояние и форматом printf для имени экземпляра вашего директора - реализовать методы или функции, возвращающие
VCL_BACKEND - в вашем деструкторе или другой процедуре завершения вызовите
VRT_DelDirector() - реализовать обратный вызов
destroyдля уничтожения фактического частного состояния директора. Он будет вызван, когда все ссылки на директора исчезнут, до тех пор, пока частное состояние должно оставаться неповреждённым и функцииvdi_methodsдоступны (но они могут возвращать ошибки).
Хотя vmod может реализовывать функции, возвращающие директоров, Объекты и методы обычно являются более естественным представлением, с экземплярами объекта vmod, являющимися или ссылающимися на частные данные директора.
Директора балансировки нагрузки
Как и в Директора VMOD — Модуль директоров Varnish, вы можете написать директоров, которые будут группировать бэкэнды, выполняющие одинаковые задачи, и выбирать их в соответствии со стратегией. Если вам нужны стратегии, отличные от встроенных (круговая очередь, хэш и т. д.), даже если их можно комбинировать, всегда можно написать свои собственные.
В этом случае вам просто нужно реализовать функцию resolve для директора. Директоры обрабатываются до тех пор, пока не будет найден листовой директор. Листовой директор не имеет функции resolve и используется для фактического запроса бэкенда, как и бэкэнды, которые вы объявляете в VCL.
Директоры балансировки нагрузки используют VRT_Assign_Backend() для получения ссылок на другие директоры. Они должны реализовать обратный вызов release, который должен освободить все ссылки на другие директоры и гарантировать, что после его возвращения ссылки не будут получены.
Статические директоры
В отличие от динамических бэкэндов, о которых говорится ниже, директоры, которые гарантированно имеют жизненный цикл VCL (то есть они не уничтожаются до того, как VCL становится холодным), могут вызвать VRT_StaticDirector() для избежания накладных расходов на подсчёт ссылок.
Динамические бэкэнды
Если вы хотите использовать HTTP/1 по TCP или UDS, но по какой-то причине VCL не подходит, вы можете вместо этого повторно использовать весь механизм бэкэндов. Это позволяет добавлять и удалять бэкэнды по требованию, без необходимости перезагрузки вашего VCL. Вы можете воспользоваться своей системой развертывания.
Рассмотрим следующий фрагмент:
backend default {
.host = "localhost";
}
Компилятор VCL преобразует это объявление в struct
vrt_backend. При загрузке VCL Varnish вызывает VRT_new_backend (или VRT_new_backend_clustered для повышения эффективности VSM) для создания директора. Varnish не предоставляет доступ к структуре данных для фактических бэкэндов, только абстракцию директора, и динамические бэкэнды создаются так же, как статические бэкэнды, по одному экземпляру struct за раз. Вы можете избавиться от struct vrt_backend как только у вас будет struct director.
Динамический бэкенд не может превышать срок жизни своего VCL, поскольку встроенные бэкэнды владеют VCL. Хотя динамический бэкенд не может пережить свой VCL, его можно удалить в любое время с помощью VRT_delete_backend. VCL удалит оставшиеся бэкэнды после отбрасывания, вам не нужно об этом беспокоиться.
Для обеспечения уничтожения бэкэндов, на которые больше нет ссылок, используется подсчёт ссылок.
Наконец, Varnish позаботится о распространении событий для всех встроенных бэкэндов, но динамические бэкэнды могут быть созданы только когда VCL тёплый. Если ваши бэкэнды создаются независимым потоком (в основном за пределами области VCL), вы должны подписаться на события VCL и отслеживать состояние VCL (см. Функции событий). Varnish будет выдавать ошибку, если вы попытаетесь создать бэкенд для холодного VCL, а VRT_new_backend вернёт NULL при охлаждении VCL. Также рекомендуется соблюдать Температуру VCL в целом.
Проверки состояния
В программе VCL можно запросить состояние работоспособности директора (см. BOOL healthy(BACKEND be)). Директор может сообщить о своём состоянии, если реализует функцию healthy, в противном случае он всегда считается работоспособным.
Если вы не создаёте динамический бэкенд, вам нужно самим позаботиться о проверках состояния работоспособности. Для директоров балансировки нагрузки работоспособность обычно означает наличие по крайней мере одного работоспособного подчинённого бэкенда или директора.
Для динамических бэкэндов это просто вопрос присвоения поля probe в struct vrt_backend. После создания директора определение проверки состояния уже не требуется. Затем Varnish позаботится о проверке состояния работоспособности и отключит функцию при холодном VCL (см. Функции событий).
Вместо инициализации собственного определения проверки состояния вы можете получить VCL_PROBE непосредственно из VCL (см. Типы данных VCL и C).
Пользовательские бэкэнды
Если вы хотите реализовать пользовательский бэкенд, обратите внимание на то, как Varnish реализует встроенные бэкэнды. Это каноническая реализация, и хотя она предоставляет другие сервисы, такие как кэширование соединений или статистику, по сути, это директор, состояние которого — struct
backend. Встроенные бэкэнды Varnish в настоящее время используют HTTP/1 по TCP или UDS, поэтому вам необходимо создать собственный пользовательский бэкенд, если вы хотите использовать Varnish для других соединений, например, по UDP или с другим протоколом.
Если вы хотите использовать объявления проверок состояния в VCL, у которых есть преимущество повторного использования, поскольку они представляют собой только спецификации, вы можете это сделать. Однако вам необходимо реализовать всю инфраструктуру проверки состояния с нуля.
Также следует рассмотреть возможность соблюдения соответствия вашего пользовательского бэкенда состоянию VCL (см. Функции событий).
Если вы реализуете метод gethdrs своего бэкенда (то есть ваш бэкенд может сгенерировать ответ бэкенда, который будет обработан в vcl_backend_response), вы захотите записывать код ответа, протокол и различные заголовки, которые он создаст, для более удобной отладки. Для этого вы можете обратиться к семейству функций VSL*, перечисленному в cache/cache.h.
Рассмотрение структуры данных
При создании пользовательского бэкенда вы можете захотеть предоставить семантику встроенных бэкэндов. В этом случае вместо повторения избыточных полей между структурами данных вы можете использовать макросы VRT_BACKEND_FIELDS и VRT_BACKEND_PROBE_FIELDS для объявления их всех сразу. Это то, что использует Varnish для копирования данных между struct vrt_backend и его внутренней структурой данных, например.
Копирование можно автоматизировать с помощью макросов VRT_BACKEND_HANDLE и VRT_BACKEND_PROBE_HANDLE. Вы можете посмотреть, как их использовать в кодовой базе Varnish.
Copyright © 2006 Verdens Gang AS
Copyright © 2006–2020 Varnish Software AS
Licensed under the BSD-2-Clause License.
https://varnish-cache.org/docs/7.4/reference/directors.html