portaldacalheta.pt
  • Основен
  • Инженерно Управление
  • Мобилен Дизайн
  • Разпределени Екипи
  • Пъргав
Back-End

Опростено балансиране на натоварването NGINX с Loadcat



Уеб приложенията, които са проектирани да бъдат хоризонтално мащабируеми, често изискват един или повече възли за балансиране на натоварването. Основната им цел е да разпределят входящия трафик между наличните уеб сървъри по справедлив начин. Възможността за увеличаване на общия капацитет на уеб приложението просто чрез увеличаване на броя на възлите и настройването на балансиращите натоварвания към тази промяна може да се окаже изключително полезна в производството.

NGINX е уеб сървър, който предлага високоефективни функции за балансиране на натоварването, сред много от другите си възможности. Някои от тези функции са достъпни само като част от техния абонаментен модел, но безплатната версия с отворен код все още е много богата на функции и идва с най-важните функции за балансиране на натоварването.



Опростено балансиране на натоварването NGINX с Loadcat



Опростено балансиране на натоварването NGINX с Loadcat Tweet

В този урок ще изследваме вътрешната механика на експериментален инструмент което ви позволява да конфигурирате своя екземпляр NGINX в движение, за да действа като балансиращ товар, абстрахирайки всички подробности за конфигурацията на NGINX, като предоставя изискан уеб базиран потребителски интерфейс. Целта на тази статия е да покаже колко лесно е да започнете да изграждате такъв инструмент. Струва си да се спомене, че проектът Loadcat е силно вдъхновен от Linode’s NodeBalancers .



NGINX, Сървъри и Upstreams

Едно от най-популярните приложения на NGINX е обратното проксиране на заявки от клиенти към уеб сървърни приложения. Въпреки че уеб приложенията, разработени на езици за програмиране като Node.js и Go, могат да бъдат самодостатъчни уеб сървъри, наличието на обратен прокси пред действителното сървърно приложение предоставя множество предимства. 'Сървър' блок за прост случай на употреба като този в NGINX конфигурационен файл може да изглежда по следния начин:

server { listen 80; server_name example.com; location / { proxy_pass http://192.168.0.51:5000; } }

Това би накарало NGINX да слуша на порт 80 за всички заявки, които са насочени към example.com и да предаде всяка от тях на някакво приложение на уеб сървър, работещо на 192.168.0.51:5000. Тук бихме могли да използваме и обратния IP адрес 127.0.0.1, ако сървърът на уеб приложения се изпълнява локално. Моля, обърнете внимание, че в горния фрагмент липсват някои очевидни ощипвания, които често се използват в конфигурацията с обратен прокси, но се поддържат по този начин за краткост.



Но какво, ако искахме да балансираме всички входящи заявки между два екземпляра на един и същ сървър на уеб приложения? Тук директивата „нагоре“ става полезна. В NGINX, с директивата „нагоре“, е възможно да се дефинират множество възли от задния край, между които NGINX ще балансира всички входящи заявки. Например:



upstream nodes { server 192.168.0.51:5000; server 192.168.0.52:5000; } server { listen 80; server_name example.com; location / { proxy_pass http://nodes; } }

Забележете как дефинирахме блок „нагоре“, наречен „възли“, състоящ се от два сървъра. Всеки сървър се идентифицира с IP адрес и номера на порта, който слуша. С това NGINX се превръща в балансиращ товар в най-простата си форма. По подразбиране NGINX ще разпространява входящите заявки по обиколен начин, където първият ще бъде прокси към първия сървър, вторият към втория сървър, третият към първия сървър и така нататък.

NGINX обаче може да предложи много повече, когато става въпрос за балансиране на натоварването. Тя ви позволява да дефинирате тегла за всеки сървър, да ги маркирате като временно недостъпни, да изберете различен алгоритъм за балансиране (например има такъв, който работи въз основа на IP хеш на клиента) и т.н. Всички тези функции и директиви за конфигуриране са всички добре документиран на nginx.org . Освен това NGINX позволява конфигурационните файлове да се променят и презареждат в движение, почти без прекъсване.



php-utf-8

Конфигурируемостта на NGINX и опростените конфигурационни файлове го правят много лесно да го адаптирате към много нужди. И множество уроци вече съществува в Интернет, които ви учат как точно да конфигурирате NGINX като балансиращ товар.

Loadcat: Инструмент за конфигуриране на NGINX

Има нещо завладяващо в програмите, които вместо да правят нещо сами, конфигурират други инструменти да го направят вместо тях. Всъщност те не правят много друго, освен може би да вземат потребителски данни и да генерират няколко файла. Повечето предимства, които получавате от тези инструменти, всъщност са характеристики на други инструменти. Но те със сигурност улесняват живота. Докато се опитвах да настроя балансиращ товар за един от собствените си проекти, се чудех: защо да не направя нещо подобно за NGINX и неговите възможности за балансиране на натоварването?



Loadcat е роден!

Loadcat, построен с Отивам , все още е в зародиш. В този момент инструментът ви позволява да конфигурирате NGINX само за балансиране на натоварването и прекратяване на SSL. Той осигурява проста уеб-базирана GUI за потребителя . Вместо да разглеждаме отделните характеристики на инструмента, нека надникнем какво има отдолу. Имайте предвид обаче, че ако някой се радва да работи с конфигурационни файлове на NGINX на ръка, той може да намери малка стойност в такъв инструмент.



Има няколко причини зад избора на Go като език за програмиране за това. Един от тях е, че Go създава компилирани двоични файлове. Това ни позволява да изграждаме и разпространяваме или разгръщаме Loadcat като компилиран двоичен файл към отдалечени сървъри, без да се притесняваме за разрешаването на зависимости. Нещо, което значително опростява процеса на настройка. Разбира се, двоичният файл приема, че NGINX вече е инсталиран и за него съществува файл на systemd единица.

В случай, че не сте Върви инженер , изобщо не се притеснявайте. Go е доста лесно и забавно за да започнете. Освен това самото внедряване е много лесно и трябва да можете лесно да го следвате.

Структура

Go build tools налагат няколко ограничения за това как можете да структурирате приложението си, а останалото да оставите на разработчика. В нашия случай разделихме нещата на няколко пакета Go въз основа на техните цели:

  • cfg: зарежда, анализира и предоставя конфигурационни стойности
  • cmd / loadcat: основен пакет, съдържа входната точка, компилира се в двоичен файл
  • данни: съдържа „модели“, използва вградено хранилище за ключ / стойност за постоянство
  • котешки: съдържа основна функционалност, напр. генериране на конфигурационни файлове, механизъм за презареждане и др.
  • ui: съдържа шаблони, манипулатори на URL адреси и т.н.

Ако разгледаме по-отблизо структурата на пакета, особено в рамките на котешкия пакет, ще забележим, че целият специфичен код на NGINX е съхраняван в подпакет feline / nginx. Това се прави, за да можем да запазим останалата част от логиката на приложението обща и да разширим поддръжката за други балансиращи натоварване (напр. HAProxy) в бъдеще.

Входна точка

Нека започнем от основния пакет за Loadcat, намиращ се в “cmd / loadcatd”. Основната функция, входна точка на приложението, прави три неща.

func main() { fconfig := flag.String('config', 'loadcat.conf', '') flag.Parse() cfg.LoadFile(*fconfig) feline.SetBase(filepath.Join(cfg.Current.Core.Dir, 'out')) data.OpenDB(filepath.Join(cfg.Current.Core.Dir, 'loadcat.db')) defer data.DB.Close() data.InitDB() http.Handle('/api', api.Router) http.Handle('/', ui.Router) go http.ListenAndServe(cfg.Current.Core.Address, nil) // Wait for an “interrupt“ signal (Ctrl+C in most terminals) }

За да се улеснят нещата и да се улесни четенето на кода, целият код за обработка на грешки е премахнат от горния фрагмент (а също и от фрагментите по-късно в тази статия).

Както можете да разберете от кода, ние зареждаме конфигурационния файл въз основа на знамето на командния ред “-config” (което по подразбиране е “loadcat.conf” в текущата директория). След това инициализираме няколко компонента, а именно основния котешки пакет и базата данни. И накрая, ние стартираме уеб сървър за уеб базиран GUI.

Конфигурация

Зареждането и анализирането на конфигурационния файл е може би най-лесната част тук. Използваме TOML за кодиране на информация за конфигурацията. Наличен е изчистен пакет за разбор на TOML за Go. Нуждаем се от много малко информация за конфигурацията от потребителя и в повечето случаи можем да определим нормални настройки по подразбиране за тези стойности. Следното структура представлява структурата на конфигурационния файл:

struct { Core struct { Address string Dir string Driver string } Nginx struct { Mode string Systemd struct { Service string } } }

И ето как може да изглежда типичен файл „loadcat.conf“:

[core] address=':26590' dir='/var/lib/loadcat' driver='nginx' [nginx] mode='systemd' [nginx.systemd] service='nginx.service'

Както виждаме, има сходство между структурата на TOML-кодирания конфигурационен файл и структура показан над него. Пакетът за конфигуриране започва чрез задаване на някои разумни настройки по подразбиране за определени полета на структура и след това анализира конфигурационния файл върху него. В случай че не успее да намери конфигурационен файл по посочения път, той създава такъв и първо изхвърля стойностите по подразбиране в него.

func LoadFile(name string) error { f, _ := os.Open(name) if os.IsNotExist(err) { f, _ = os.Create(name) toml.NewEncoder(f).Encode(Current) f.Close() return nil } toml.NewDecoder(f).Decode(&Current) return nil }

Данни и постоянство

Среща Болт . Вградено хранилище за ключ / стойност, написано в чисто Go. Той се предлага като пакет с много прост API, поддържа транзакции от кутията и е обезпокоително бърз.

лифт срещу бизнес модел на uber

В рамките на данните за пакета имаме структури представляващи всеки тип обект. Например имаме:

type Balancer struct { Id bson.ObjectId Label string Settings BalancerSettings } type Server struct { Id bson.ObjectId BalancerId bson.ObjectId Label string Settings ServerSettings }

... където екземпляр на Балансир представлява единичен балансьор на товара. Loadcat ефективно ви позволява да балансирате заявки за множество уеб приложения чрез един екземпляр на NGINX. След това всеки балансьор може да има един или повече сървъри зад себе си, където всеки сървър може да бъде отделен фонов възел.

Тъй като Bolt е хранилище ключ-стойност и не поддържа разширени заявки към база данни, имаме логика от страна на приложението, която прави това вместо нас. Loadcat не е предназначен за конфигуриране на хиляди балансьори с хиляди сървъри във всеки от тях, така че естествено този наивен подход работи добре. Също така, Bolt работи с ключове и стойности, които са байтови срезове и затова ние BSON кодираме структури преди да ги съхранява в Болт. Внедряването на функция, която извлича списък на Балансиращи структури от базата данни е показано по-долу:

func ListBalancers() ([]Balancer, error) { bals := []Balancer{} DB.View(func(tx *bolt.Tx) error { b := tx.Bucket([]byte('balancers')) c := b.Cursor() for k, v := c.First(); k != nil; k, v = c.Next() { bal := Balancer{} bson.Unmarshal(v, &bal) bals = append(bals, bal) } return nil }) return bals, nil }

ListBalancers функция стартира транзакция само за четене, итерира над всички ключове и стойности в групата „балансьори“, декодира всяка стойност в екземпляр на Балансираща структура и ги връща в масив.

Съхраняването на балансьор в кофата е почти еднакво просто:

func (l *Balancer) Put() error { if !l.Id.Valid() { l.Id = bson.NewObjectId() } if l.Label == '' { l.Label = 'Unlabelled' } if l.Settings.Protocol == 'https' { // Parse certificate details } else { // Clear fields relevant to HTTPS only, such as SSL options and certificate details } return DB.Update(func(tx *bolt.Tx) error { b := tx.Bucket([]byte('balancers')) p, err := bson.Marshal(l) if err != nil { return err } return b.Put([]byte(l.Id.Hex()), p) }) }

The Слагам функция присвоява някои стойности по подразбиране на определени полета, анализира прикачения SSL сертификат в настройката на HTTPS, започва транзакция, кодира структура екземпляр и го съхранява в кофата срещу идентификатора на балансьора.

Докато анализирате SSL сертификата, две части информация се извличат с помощта кодиране на стандартен пакет / pem и се съхранява в SSLOptions под Настройки поле: DNS имената и пръстовият отпечатък.

коя е най-точната дефиниция за визуализация?

Имаме и функция, която търси сървъри по балансиращ:

func ListServersByBalancer(bal *Balancer) ([]Server, error) { srvs := []Server{} DB.View(func(tx *bolt.Tx) error { b := tx.Bucket([]byte('servers')) c := b.Cursor() for k, v := c.First(); k != nil; k, v = c.Next() { srv := Server{} bson.Unmarshal(v, &srv) if srv.BalancerId.Hex() != bal.Id.Hex() { continue } srvs = append(srvs, srv) } return nil }) return srvs, nil }

Тази функция показва колко наивен е нашият подход всъщност. Тук ние ефективно четем цялата група „сървъри“ и филтрираме неподходящите обекти, преди да върнем масива. Но отново това работи добре и няма реална причина да го промените.

The Слагам функцията за сървъри е много по-проста от тази на Балансираща структура тъй като не изисква толкова много редове по подразбиране на кода и изчислени полета.

Контролиране на NGINX

Преди да използваме Loadcat, трябва да конфигурираме NGINX да зарежда генерираните конфигурационни файлове. Loadcat генерира файл „nginx.conf“ за всеки балансьор в директория чрез идентификатора на балансьора (кратък шестнадесетичен низ). Тези директории се създават в директорията “out” на cwd Следователно е важно да конфигурирате NGINX да зарежда тези генерирани конфигурационни файлове. Това може да се направи с помощта на директивата 'включва' в блока 'http':

Редактирайте /etc/nginx/nginx.conf и добавете следния ред в края на блока „http“:

http { include /path/to/out/*/nginx.conf; }

Това ще накара NGINX да сканира всички директории, намерени под „/ path / to / out /“, да потърси файлове с име „nginx.conf“ във всяка директория и да зареди всеки, който намери.

В нашия основен пакет, котешки, ние дефинираме интерфейс Шофьор . Всякакви структура което осигурява две функции, Генериране и Презаредете , с правилния подпис се квалифицира като драйвер.

type Driver interface { Generate(string, *data.Balancer) error Reload() error }

Например структурата Nginx под пакетите за котки / nginx:

type Nginx struct { sync.Mutex Systemd *dbus.Conn } func (n Nginx) Generate(dir string, bal *data.Balancer) error { // Acquire a lock on n.Mutex, and release before return f, _ := os.Create(filepath.Join(dir, 'nginx.conf')) TplNginxConf.Execute(f, /* template parameters */) f.Close() if bal.Settings.Protocol == 'https' { // Dump private key and certificate to the output directory (so that Nginx can find them) } return nil } func (n Nginx) Reload() error { // Acquire a lock on n.Mutex, and release before return switch cfg.Current.Nginx.Mode { case 'systemd': if n.Systemd == nil { c, err := dbus.NewSystemdConnection() n.Systemd = c } ch := make(chan string) n.Systemd.ReloadUnit(cfg.Current.Nginx.Systemd.Service, 'replace', ch) <-ch return nil default: return errors.New('unknown Nginx mode') } }

Генериране може да се извика със низ, съдържащ пътя към изходната директория и указател към Балансир екземпляр на struct. Go предоставя стандартен пакет за шаблониране на текст, който NGINX драйверът използва за генериране на окончателния NGINX конфигурационен файл. Шаблонът се състои от блок „нагоре“, последван от блок „сървър“, генериран въз основа на това как е конфигуриран балансьорът:

var TplNginxConf = template.Must(template.New('').Parse(` upstream {{.Balancer.Id.Hex}} { {{if eq .Balancer.Settings.Algorithm 'least-connections'}} least_conn; {{else if eq .Balancer.Settings.Algorithm 'source-ip'}} ip_hash; {{end}} {{range $srv := .Balancer.Servers}} server {{$srv.Settings.Address}} weight={{$srv.Settings.Weight}} {{if eq $srv.Settings.Availability 'available'}}{{else if eq $srv.Settings.Availability 'backup'}}backup{{else if eq $srv.Settings.Availability 'unavailable'}}down{{end}}; {{end}} } server { {{if eq .Balancer.Settings.Protocol 'http'}} listen {{.Balancer.Settings.Port}}; {{else if eq .Balancer.Settings.Protocol 'https'}} listen {{.Balancer.Settings.Port}} ssl; {{end}} server_name {{.Balancer.Settings.Hostname}}; {{if eq .Balancer.Settings.Protocol 'https'}} ssl on; ssl_certificate {{.Dir}}/server.crt; ssl_certificate_key {{.Dir}}/server.key; {{end}} location / { proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_pass http://{{.Balancer.Id.Hex}}; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; } } `))

Презаредете е другата функция на Структура на Nginx което кара NGINX да презареди конфигурационните файлове. Използваният механизъм се основава на това как е конфигуриран Loadcat. По подразбиране се приема, че NGINX е системна услуга, работеща като nginx.service, така че [sudo] systemd reload nginx.service бих работил. Въпреки това, вместо да изпълнява команда на черупката, тя установява връзка с systemd чрез D-Bus, използвайки пакет github.com/coreos/go-systemd/dbus .

Уеб базиран GUI

С всички тези компоненти на място, ние ще завършим всичко с обикновен потребителски интерфейс Bootstrap.

Функции за балансиране на натоварването NGINX, обвити в прост графичен интерфейс

най-добрият начин да научите c програмиране
Функции за балансиране на натоварването NGINX, обвити в прост графичен интерфейс Tweet

За тези основни функционалности са достатъчни няколко прости манипулатора на GET и POST маршрут:

GET /balancers GET /balancers/new POST /balancers/new GET /balancers/{id} GET /balancers/{id}/edit POST /balancers/{id}/edit GET /balancers/{id}/servers/new POST /balancers/{id}/servers/new GET /servers/{id} GET /servers/{id}/edit POST /servers/{id}/edit

Преминаването през всеки отделен маршрут може да не е най-интересното нещо за правене тук, тъй като това са почти страниците CRUD. Чувствайте се абсолютно свободни да надникнете в потребителски потребителски код на пакета за да видите как са приложени манипулаторите за всеки от тези маршрути.

Всяка функция на манипулатора е рутина, която:

  • Извлича данни от хранилището на данни и отговаря с изобразени шаблони (използвайки извлечените данни)
  • Анализира входящите данни от формуляра, прави необходимите промени в хранилището на данни и използва пакет котешки, за да регенерира конфигурационните файлове на NGINX

Например:

func ServeServerNewForm(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) bal, _ := data.GetBalancer(bson.ObjectIdHex(vars['id'])) TplServerNewForm.Execute(w, struct { Balancer *data.Balancer }{ Balancer: bal, }) } func HandleServerCreate(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) bal, _ := data.GetBalancer(bson.ObjectIdHex(vars['id'])) r.ParseForm() body := struct { Label string `schema:'label'` Settings struct { Address string `schema:'address'` } `schema:'settings'` }{} schema.NewDecoder().Decode(&body, r.PostForm) srv := data.Server{} srv.BalancerId = bal.Id srv.Label = body.Label srv.Settings.Address = body.Settings.Address srv.Put() feline.Commit(bal) http.Redirect(w, r, '/servers/'+srv.Id.Hex()+'/edit', http.StatusSeeOther) }

всичко ServeServerNewForm функцията прави, извлича балансьор от хранилището на данни и изобразява шаблон, TplServerList в този случай, който извлича списъка на съответните сървъри с помощта на Сървъри функция на балансьора.

HandleServerCreate функция, от друга страна, анализира входящия POST полезен товар от тялото в a структура и използва тези данни, за да създаде екземпляр и да запази нов Сървърна структура в хранилището за данни, преди да използвате пакет котешки за регенериране на NGINX конфигурационен файл за балансьора.

Всички шаблони на страници се съхраняват във файл „ui / templates.go“ и съответните HTML файлове на шаблони могат да бъдат намерени в директорията „ui / templates“.

Опитвам го

Разполагането на Loadcat на отдалечен сървър или дори във вашата локална среда е изключително лесно. Ако използвате Linux (64bit), можете да вземете архив с предварително изграден двоичен файл Loadcat от хранилището Раздел за издания . Ако се чувствате малко приключенски, можете да клонирате хранилището и да компилирате кода сами. Въпреки това опитът в този случай може да е малко разочароващо тъй като съставянето на Go програми всъщност не е предизвикателство. И в случай, че използвате Arch Linux, значи имате късмет! Изграден е пакет за разпространение за удобство. Просто изтегли го и го инсталирайте с помощта на вашия мениджър на пакети. Включените стъпки са описани по-подробно в проекта README.md файл .

След като конфигурирате и стартирате Loadcat, насочете уеб браузъра си към „http: // localhost: 26590“ (ако приемем, че се изпълнява локално и слуша на порт 26590). След това създайте балансьор, създайте няколко сървъра, уверете се, че нещо слуша на тези дефинирани портове и voila трябва да имате входящи заявки за баланс на натоварване NGINX между тези работещи сървъри.

Какво следва?

Този инструмент далеч не е перфектен и всъщност е доста експериментален проект. Инструментът дори не обхваща всички основни функционалности на NGINX. Например, ако искате да кеширате активи, обслужвани от задните възли на слой NGINX, пак ще трябва да модифицирате конфигурационните файлове на NGINX на ръка. И именно това прави нещата вълнуващи. Тук може да се направи много и точно това е следващото: покриване на още повече от функциите за балансиране на натоварването на NGINX - основните и вероятно дори тези, които NGINX Plus може да предложи.

Опитайте Loadcat. Вижте кода, разклонете го, променете го, играйте с него. Също така, уведомете ни, ако сте създали инструмент, който конфигурира друг софтуер или сте използвали такъв, който наистина ви харесва, в раздела за коментари по-долу.

Ефективният подход - Как да проектираме Lean UX MVP

Ux Дизайн

Ефективният подход - Как да проектираме Lean UX MVP
Зрелищни неуспехи при краудфъндинг и въздействието им върху предприемачеството

Зрелищни неуспехи при краудфъндинг и въздействието им върху предприемачеството

Управление На Проекти

Популярни Публикации
Плащане напред: Разбиране на изкупувания с ливъридж
Плащане напред: Разбиране на изкупувания с ливъридж
Индустриален анализ и Porter’s Five Force: По-задълбочен поглед върху силата на купувача
Индустриален анализ и Porter’s Five Force: По-задълбочен поглед върху силата на купувача
Разширена реалност vs. Виртуална реалност vs. Смесена реалност: Уводно ръководство
Разширена реалност vs. Виртуална реалност vs. Смесена реалност: Уводно ръководство
Ще отвори ли Spotify не-IPO пътя за технологичните компании?
Ще отвори ли Spotify не-IPO пътя за технологичните компании?
Прогнозиране на харесвания: Вътре в алгоритмите на прост механизъм за препоръки
Прогнозиране на харесвания: Вътре в алгоритмите на прост механизъм за препоръки
 
Ефективни стартови платки: какви са те и как да ги изградим
Ефективни стартови платки: какви са те и как да ги изградим
Ръководител на клиентския опит
Ръководител на клиентския опит
Игла в купа сено: чудесен урок за мащабен текстов алгоритъм за търсене
Игла в купа сено: чудесен урок за мащабен текстов алгоритъм за търсене
Структурата на данните Trie: Пренебрегван скъпоценен камък
Структурата на данните Trie: Пренебрегван скъпоценен камък
Краят на уеб формите
Краят на уеб формите
Популярни Публикации
  • седмичен шаблон за прогноза на паричния поток
  • дискорд бот c++
  • какво е ac corporation vs s corporation
  • какво прави финансовият директор в стартиране
  • компилира в c++
  • как да използвам twitter api в python
  • принципи на дефиниция на дизайнерското изкуство
Категории
  • Инженерно Управление
  • Мобилен Дизайн
  • Разпределени Екипи
  • Пъргав
  • © 2022 | Всички Права Запазени

    portaldacalheta.pt