Речь в статье пойдет о том, как организовать возможность динамического переключения между сетевыми интерфейсами.
Корни вопроса начали расти из предыдущего проекта socmetr.ru, где понадобилось собирать большой объем информации из социальных сетей, и таким образом забивая единственный канал с интернетом. Анализ показал, что даже при наличии сжатия, объем поступающей информации так велик, что происходит его блокировка, при этом мощности CPU и Memory не задействованы и на 20%, а дисковая подсистема почти все время простаивает, то есть мы упёрлись в ширину канала, которую нам предоставляет провайдер.
Первая мысль была пойти экстенсивным путём и просто увеличить его возможности, немного остыв и призадумавшись, поняли, что перекладываем проблему на будущее. Само собой, возник вопрос: "Каким путём пойдем товарищи?". В результате реализовали следующую идею:
Настройка сервера
Поскольку конфигурация выглядит однообразно, имеет смысл ввести символьные обозначения, пусть:
A1 это первый сетевой интерфейс, A2 — второй… AN — поcледний
IP1 это IP-адрес связанный с сетевым интерфейсом A1, IP2 — адрес связанный с A2… IPN — адрес связанный c AN
GW1 это IP-адрес шлюза провайдера P1 (Provider 1), GW2 — адрес шлюза провайдера P2… GWN — адрес шлюза PN
GW1_NET это IP-адрес сети провайдера P1, GW2_NET IP-адрес сети провайдера P2… GWN_NET IP-адрес сети провайдера PN
Тогда настройку можно осуществить следующим образом:
Создаем N-таблиц маршрутизации (где N - это количество подведенных каналов с интернетом)
ip route add {GW1_NET} dev {A1} src {IP1} table T1
ip route add default via {GW1} table T1
...
ip route add {GWn_NET} dev {An} src {IPn} table Tn
ip route add default via {GWn} table Tn
Описываем маршруты в основной таблице маршрутизации:
ip route add {GW1_NET} dev {A1} src {IP1}
...
ip route add {GWn_NET} dev {An} src {IPn}
ip route add default via {GW1}
Описываем правила:
ip rule add from {IP1} table T1
...
ip rule add from {IPn} table Tn
И дело в шляпе, получаем конфигурацию, которая гарантирует что все запросы к конкретному интерфейсу получат от него ответ.
Использование
Для, того чтобы обратится к разным сетевым адаптерам, необходимо задействовать конструкции конкретного языка программирования, либо использовать сторонние библиотеки. В Java, это можно сделать через сокеты, например:
socket.bind(new InetSocketAddress(InetAddress.getByName("network-adapter"), port));
Реализовав указанную схему, была получена возможность управлять полосой интернет канала в зависимости от бизнес-процессов и логики, происходящих на серверах, на разных стадиях жизненного цикла информационных систем.
Плюсы:
- возможность гибкого масштабирования интернет-канала (мы получаем возможность в любой момент нарастить или уменьшить общий интернет канал, как за счёт подключения новых провайдеров, так и за счет увеличения полосы пропускания текущих, появляется возможность планировать и прогнозировать его мощность)
- возможность управления нагрузкой, каждого из них
- возможность использования любого канала или их последовательности в любой момент времени любой подсистемой
Минусы:
- изначальные траты на покупку соответствующего оборудования
- обязательное наличие множества провайдеров интернет услуг
Возможно, кто-то уже сталкивался с подобной проблемой, и мы построили велосипед, так что критика решения только приветствуется.
Комментарии (19)
yosemity
12.01.2017 21:20+1blutovi
12.01.2017 22:02Похоже в сообщество надо было обращаться значительно раньше, а то мы себе мозги над стандартными вещами съели) (вот оригинал указанной ссылки http://lartc.org/howto/lartc.rpdb.multiple-links.html)
yosemity
12.01.2017 23:44Ну если честно, вы тут абзац из «букваря» описали. Особенно забавляют плюсы и минусы. Например, минус работы через нескольких провайдеров — необходимость нескольких провайдеров.
blutovi
13.01.2017 07:34Например, минус работы через нескольких провайдеров — необходимость нескольких провайдеров.
Возможно так будет не много понятнее:
“Под минусами данного решения по динамическому перенаправлению сетевого трафика можно выделить необходимость наличия нескольких провайдеров”
Возможно требуется пояснение:
“Чтобы в принципе иметь возможность реализовать данную схему, необходимо наличие нескольких независимых провайдеров, а поскольку это не везде достижимо, то и не везде применимо”.
sergeysakirkin
13.01.2017 03:06Вопрос, зачем, есть стандартные решения балансировки трафика в BGP например:
http://www.cisco.com/c/en/us/support/docs/ip/border-gateway-protocol-bgp/13762-40.html
YourChief
13.01.2017 14:10Я решал подобную задачу для офисного интернета: https://habrahabr.ru/post/279777/
В вашем случае вы можете использовать
--hmark-tuple src,sport
и тогда никаких действий со стороны приложения не потребуется для того, чтобы попасть в разные каналы.blutovi
13.01.2017 16:38Ключевое слово здесь балансировка, а необходимо управление трафиком (то есть, в зависимости от бизнес-процессов и состояния информационных систем, необходимо иметь возможность менять правила использования каналов с интернетом для любой из подсистем)
xcore78
13.01.2017 15:30Что только не делают люди, чтобы не брать на работу сетевиков.
YourChief
13.01.2017 16:12А толку их брать? У них на все один ответ: давай циску/джун за много-много денег, чтобы в итоге выкатить такое же решение, которое делается средствами iproute/netfilter.
xcore78
13.01.2017 18:13А толку брать программистов на работу? Или дизайнеров? Или вообще любых специалистов?
Для:
* соответствия лучшим практикам, сиречь технологичности,
* стабильности и воспроизводимости результата,
* прозрачной модели обслуживания решения в дальнейшем,
* отсутствие необходимости чинить свою повозку на ходу/на полной скорости.
Понимаете, для динамического перенаправления сетевого траффика что-то своё придумывают те, кому катастрофически не хватает возможностей BGP, MP-BGP и всего стандартизованного поля TE.
Но чаще проблема в пробелах в профильных знаниях.blutovi
13.01.2017 18:36Но чаще проблема в пробелах в профильных знаниях.
Тут я вас подержу, похоже мне придется идти и восполнять их.
sergeysakirkin
13.01.2017 16:45Чтобы быть незаменимым?
Ибо только великий гуру знает как работает чудо приложение.
rijk
13.01.2017 16:38Я первоначально использовал FreeBSD PF, но это без балансировки нагрузки
pass in log on $int_if route-to {($ext_if1 $gw1), ($ext_if2 $gw2), ($ext_if3 $gw3)} round-robin from $int_lan to any
В конце концов оставил только прокси сервер SQUID с балансировкой для веб трафика, остальной пустил по одному каналу
zoonman
В вашем решении отсутствует балансировка и обработка отказов провайдеров.
blutovi
Что есть то есть, как сделать балансировку подсказал yosemity
А с обработкой отказов — мы держим один канал всегда свободным, на тот случай если один из провайдеров откажет, это конечно не спасет если резервный канал тоже будет не доступным, но вероятность события значительно меньше.