вторник, 27 октября 2009 г.

Кластер AOL Server с единой точкой входа под управлением HAProxy

При построении кластера с единой точкой входа возникает необходимость определенной настройки узлов кластера. Например, редирект должен отправлять пользователя не на хост, заданный в конфиг-файле AOL Server, а на тот хост, который указан в хидерах клиента. Имя точки входа и соответствующие веб-сервера определяются на уровне балансировщика, например, в HAProxy, таким образом, в конфиге AOL Server вовсе не должно быть имени точки входа; кроме того, точек входа может быть более одной.

Задача решается с помощью приведенных ниже врапперов для встроенных функций.


# Copyright 2009, Mobile Business Group
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see http://www.gnu.org/licenses/.

# создает враппер для функции редиректа, так, чтобы можно было использовать DNS алиасы
# также обеспечивает возможность работы по IP, если DNS не доступен или есть причины его не использовать
# TODO: сделать опеределение протокола, по которому работает пользователь
puts "Creating wrappers for \[ns_returnredirect url\],\[ns_info server\], \[ns_conn location\]."

# reverse-proxy must add header "X-Forwarded-Proto: https" for SSL mode
# HAProxy: reqadd X-Forwarded-Proto:\ https
# Pound: AddHeader "X-Forwarded-Proto: https"

ns_ictl oncreate {
if {[info commands _ns_returnredirect] eq {}} {
rename ns_returnredirect _ns_returnredirect
proc ns_returnredirect {url} {
if {[ns_conn port] ne {}} {
_ns_returnredirect [ns_conn protocol]://[ns_conn host]:[ns_conn port]$url
} else {
_ns_returnredirect [ns_conn protocol]://[ns_conn host]$url
}
}
}
if {[info commands _ns_conn] eq {}} {
rename ns_conn _ns_conn
proc ns_conn {args} {
if {[string match [lindex $args 0] "host"]} {
set host [string tolower [ns_set get [ns_conn headers] Host]]
set port_index [string first : $host]
if { $port_index > 0 } {
set host [string range $host 0 [expr {$port_index-1}]]
}
return $host
} elseif {[string match [lindex $args 0] "port"]} {
set host [string tolower [ns_set get [ns_conn headers] Host]]
set port_index [string first : $host]
if { $port_index > 0 } {
return [string range $host $port_index+1 end]
}
return
} elseif {[string match [lindex $args 0] "protocol"]} {
if {[string equal [ns_set get [ns_conn headers] "X-Forwarded-Proto"] "https"]} {
return https
} else {
return http
}
} elseif {[string match [lindex $args 0] "location"]} {
# is needed the host+port specification
set host [string tolower [ns_set get [ns_conn headers] Host]]
return [ns_conn protocol]://$host
} else {
return [_ns_conn {*}$args]
}
}
}
# we don't need virtual server name and replace this
if {[info commands _ns_info] eq {}} {
rename ns_info _ns_info
proc ns_info {args} {
if {[string match [lindex $args 0] "server"]} {
return [ns_config "ns/parameters" servername]
} else {
return [_ns_info {*}$args]
}
}
}
# if {[info commands _ns_info] eq {}} {
# rename ns_info _ns_info
# proc ns_info {args} {
# if {[string match [lindex $args 0] "server"]} {
# return [ns_conn host]
# } else {
# return [_ns_info {*}$args]
# }
# }
# }
}


HAProxy, помимо прочих своих талантов, умеет выполнять cookie-based балансировку. Пусть при отсутствии куки запрос отправляется на сервер-балансировщик, устанавливающий нужные куки, а при наличии требуемых куки непосредственно на целевой узел кластера. Привожу пример конфигурации с двумя целевыми узлами кластера и одним узлом балансировки.


frontend FRONTEND1
bind 127.0.0.1:80

acl site1 hdr_sub(host) site1.ru 127.0.0.1

acl backend1 hdr_sub(cookie) serverid=backend1
acl backend2 hdr_sub(cookie) serverid=backend2

use_backend site1_backend1 if site1 backend1
use_backend site1_backend2 if site1 backend2

use_backend site1_main if site1

backend site1_backend1
server backend1 127.0.0.1:1001

backend site1_backend2
server backend2 127.0.0.1:1002

backend site1_main
server main 127.0.0.1:1000


Алгоритм балансировки может быть произвольный, например, по географическому местоположению клиента.

Комментариев нет:


(C) Alexey Pechnikov aka MBG, mobigroup.ru