клиент серверное приложение через интернет
ИТ База знаний
Полезно
— Онлайн генератор устойчивых паролей
— Онлайн калькулятор подсетей
— Руководство администратора FreePBX на русском языке
— Руководство администратора Cisco UCM/CME на русском языке
— Руководство администратора по Linux/Unix
Навигация
Серверные решения
Телефония
FreePBX и Asterisk
Настройка программных телефонов
Корпоративные сети
Протоколы и стандарты
Как работает WEB. Клиент-серверная модель и архитектура веб-приложения
В предыдущем материале мы рассмотрели, как работает Интернет на базовом уровне, включая взаимодействие между клиентом (вашим компьютером) и сервером (другим компьютером, который отвечает на запросы клиента о веб-сайтах).
В этой же части рассмотрим, как устроены клиент, сервер и веб-приложение, что мы можем удобно серфить в Интернете.
Модель клиент-сервер
Эта идея взаимодействия клиента и сервера по сети называется моделью «клиент-сервер». Это делает возможным просмотр веб-сайтов (например, сайт wiki.merionet.ru) и взаимодействие с веб-приложением (как Gmail).
Базовая конфигурация веб-приложения
Существует сотни способов настройки веб-приложения. При этом большинство из них следуют одной и той же базовой структуре: клиент, сервер, база данных.
Клиент
Структура: Макет и содержимое веб-страницы определяются с помощью HTML (обычно HTML 5, если речь идет о современных веб-приложениях, но это другая история.)
HTML означает язык гипертекстовой разметки (Hypertext Markup Language). Он позволяет описать основную физическую структуру документа с помощью HTML-тэгов. Каждый HTML-тэг описывает определенный элемент документа.
Веб-браузер использует эти HTML-тэги для определения способа отображения документа.
Стили для указанной выше HTML-страницы можно задать следующим образом:
Взаимодействие с пользователем: Наконец, для реализации механизма взаимодействия с пользователем, на сцену выходит JavaScript.
Например, если вы хотите что-то сделать, когда пользователь нажимает кнопку, вы можете сделать что-то подобное:
Например, если пользователь публикует комментарий в потоке, может потребоваться сохранить этот комментарий в базе данных, чтобы весь материал был структурирован и собран в одном месте. Таким образом, вы отправляете запрос на сервер с новым комментарием и идентификатором пользователя, а сервер прослушивает эти запросы и обрабатывает их соответствующим образом.
Сервер
Сервер в веб-приложении прослушивает запросы, поступающие от клиента. При настройке HTTP-сервера он должен прослушивать конкретный номер порта. Номер порта всегда связан с IP-адресом компьютера.
Вы можете рассматривать порты как отдельные каналы на каждом компьютере, которые можно использовать для выполнения различных задач: один порт может быть использован для серфинга на wiki.merionet.ru, в то время как через другой получаете электронную почту. Это возможно, поскольку каждое из приложений (веб-браузер и клиент электронной почты) использует разные номера портов.
После настройки HTTP-сервера для прослушивания определенного порта сервер ожидает клиентские запросов, поступающие на этот порт, выполняет все действия, указанные в запросе, и отправляет все запрошенные данные через HTTP-ответ.
База данных
Например, при создании сайта в социальных сетях можно использовать базу данных для хранения сведений о пользователях, публикациях и комментариях. Когда посетитель запрашивает страницу, данные, вставленные на страницу, поступают из базы данных сайта, что позволяет нам воспринимать взаимодействие пользователей в реальном времени как должное на таких сайтах, как Facebook или в таких приложениях, как Gmail.
Как масштабировать простое веб-приложение
Чтобы выполнить масштабирование в соответствии с этими большими объемами, можно распределить входящий трафик между группой внутренних серверов.
Здесь все становится интересно. Имеется несколько серверов, каждый из которых имеет собственный IP-адрес. Итак, как сервер доменных имен (DNS) определяет, на какой экземпляр вашего приложения отправить трафик?
Подсистема балансировки нагрузки действует как гаишник, который маршрутизирует клиентские запросы по серверам как можно быстрее и эффективнее, насколько это возможно.
Поскольку вы не можете транслировать IP-адреса всех экземпляров сервера, вы создаете виртуальный IP-адрес, который транслируется клиентам. Этот виртуальный IP-адрес указывает на подсистему балансировки нагрузки. Таким образом, когда DNS ищет ваш сайт, он указывает на балансировщик нагрузки. Затем подсистема балансировки нагрузки перескакивает для распределения трафика на различные внутренние серверы в реальном времени.
Возможно, вам интересно, как подсистема балансировки нагрузки узнаёт, на какой сервер следует отправлять трафик. Ответ: алгоритмы.
Один популярный алгоритм, Round Robin, включает равномерное распределение входящих запросов по ферме серверов (все доступные серверы). Вы обычно выбираете такой подход, если все ваши серверы имеют одинаковую скорость обработки и память.
С помощью другого алгоритма, Least Connections, следующий запрос отправляется на сервер с наименьшим количеством активных соединений.
Существует гораздо больше алгоритмов, которые вы можете реализовать, в зависимости от ваших потребностей.
Теперь поток трафика выглядит следующим образом:
Службы
Итак, мы решили проблему трафика, создав пулы серверов и балансировщик нагрузки для управления ими.
Но одной репликация серверов может быть недостаточно для обслуживания приложения по мере его роста. По мере добавления дополнительных функциональных возможностей в приложение необходимо поддерживать тот же монолитный сервер, пока он продолжает расти. Для решения этой проблемы нам нужен способ разобщить функциональные возможности сервера.
Здесь и появляется идея служб. Служба является просто другим сервером, за исключением того, что она взаимодействует только с другими серверами, в отличие от традиционного веб-сервера, который взаимодействует с клиентами.
Каждая служба имеет автономную единицу функциональности, такую как авторизация пользователей или предоставление функции поиска. Службы позволяют разбить один веб-сервер на несколько служб, каждая из которых выполняет отдельные функции.
Основное преимущество разделения одного сервера на множество сервисов заключается в том, что он позволяет масштабировать сервисы полностью независимо.
Другое преимущество здесь заключается в том, что он позволяет командам внутри компании работать независимо над конкретной услугой, а не иметь 10, 100 или даже 1000 инженеров, работающих на одном монолитном сервере, который быстро становится кошмаром для менеджера проекта.
Краткое примечание: эта концепция балансировщиков нагрузки и пулов внутренних серверов и служб становится очень сложной, поскольку вы масштабируете все больше и больше серверов в вашем приложении. Это особенно сложно с такими вещами, как, например, сохранение сеанса, обработка отправки нескольких запросов от клиента на один и тот же сервер в течение сеанса, развертывания решения для балансировки нагрузки. Такие продвинутые темы не будет затрагивать в данном материале.
Сети доставки контента (Conten Delivery Network – CDN)
Компании с большим объемом распределенного трафика могут платить CDN-компаниям за доставку контента конечным пользователям с помощью серверов CDN. CDN имеет тысячи серверов, расположенных в стратегических географических точках по всему миру.
Давайте сравним, как веб-сайт работает с CDN и без него.
Как мы уже говорили в разделе 1, для типичного веб-сайта доменное имя URL преобразуется в IP-адрес сервера хоста.
Однако если клиент использует CDN, доменное имя URL преобразуется в IP-адрес пограничного сервера, принадлежащего CDN. Затем CDN доставляет веб-контент пользователям клиента, не затрагивая серверы клиента.
CDN может сделать это, сохраняя копии часто используемых элементов, таких как HTML, CSS, загрузки программного обеспечения и медиаобъектов с серверов клиентов.
Простой клиент-сервер на Android (интернет-мессенджер)
Важно. Все написанное ниже не представляет собой какой либо ценности для профессионалов, но может служит полезным примером для начинающих Android разработчиков! В коде старался все действия комментировать и логировать.
Поехали. Многие мобильные приложения (и не только) используют архитектуру клиент-сервер. Общая схема, думаю, понятна.
Уделим внимание каждому элементу и отметим:
Клиент, установленный на устройстве А, посылает сообщение для клиента, установленного на устройстве Б. И наоборот. Сервер играет роль связующего звена между устройством А и Б… С, Д… и т.д. Также он играет роль «накопителя» сообщений, для их восстановления, на случай удаления на одном из клиентских устройств.
Для хранения сообщений используем SQL БД как на сервере, так и на устройствах-клиентах (в принципе, вся работа клиентов интернет-мессенджеров и сводится к постоянной синхронизации локальной и удаленной БД с сообщениями). Дополнительно, наш интернет-чат будет уметь стартовать вместе с запуском устройства и работать в фоне. Взаимодействие будет происходить путем HTTP запросов и JSON ответов.
Более логично, если синхронизация происходит через порт/сокет, это с одной стороны упрощает задачу (не нужно циклично слать HTTP запросы на проверку новых сообщений, достаточно проверять состояние прослушиваемого сокета), но с другой стороны, это усложняет создание серверной части приложения.
Делаем сервер
Для реализации «сервера», нам нужно зарегистрироваться на любом хостинге, который дает возможность работы с SQL и PHP.
Создаем пустую SQL БД, в ней создаем таблицу.
Структура запросов к api:
Клиентская часть
Теперь структура Android приложения:
В фоне работает FoneService.java, который, в отдельном потоке, каждые 15 секунд делает запрос на сервер. Если ответ сервера содержит новые сообщения, FoneService.java записывает их в локальную БД и отправляет сообщение ChatActivity.java о необходимости обновить ListView, с сообщениями. ChatActivity.java (если она в этот момент открыта) получает сообщение и обновляет содержимое ListView из локальной БД.
Отправка нового сообщения из ChatActivity.java происходит сразу на сервер, минуя FoneService.java. При этом наше сообщение НЕ записывается в локальную БД! Там оно появится только после получения его назад в виде ответа сервера. Такую реализацию я использовал в связи с важным нюансом работы любого интернет-чата — обязательной группировкой сообщений по времени. Если не использовать группировку по времени, будет нарушена последовательность сообщений. Учитывая, что клиентские приложения просто физически не могут быть синхронизированы с точностью до миллисекунд, а возможно будут работать даже в разных часовых поясах, логичнее всего будет использовать время сервера. Так мы и делаем.
Создавая новое сообщение, мы передаем запросом на сервер: имя автора сообщения, имя получателя сообщения, текст сообщения. Получая эту запись назад, в виде ответа сервера, мы получаем то, что отправляли + четвертый параметр: время получения сообщения сервером.
Клиент-серверная архитектура в картинках
Знакомая картинка? А вы ведь постоянно сталкиваетесь с этой архитектурой — когда покупаете билет в кино онлайн, бронируете путевку на море или записываетесь к врачу.
На клиент-серверной архитектуре построены все сайты и интернет-сервисы. Также ее используют десктоп-программы, которые передают данные по интернету. Поэтому ИТ-специалисту нужно понимать, что это такое и как работает.
Об этом я и расскажу в статье. Объясню на пальцах, с примерами и забавными картинками =) Если вы больше любите видео-формат, можно посмотреть мой ролик на youtube на ту же тему.
Содержание
Что это и как работает
Вот есть у нас некий Вася, который решил купить машину. Такую, как в рекламе — быструю, мощную, красивую! Только стоит она как хвост самолета, у Васи таких денег нет.
Конечно, Вася может подкопить несколько лет, а потом уже покупать машину. Но ведь хочется здесь и сейчас! Да и средство передвижения нужно…
А еще Вася не умеет копить — получил зарплату, закупился основным, оплатил жилье, всё! Остальное можно потратить. Для таких людей есть банки, куда можно прийти и взять деньги в кредит.
Конечно, потом вы будете переплачивать, возвращая их назад. Проценты-то конские. Но зато уже сейчас можете позволить купить себе что-то дорогое.
Вася подумал, прикинул и сказал:
— Да, хочу именно так! 100 рублей с зарплаты платить в банк могу, а откладывать — нет. Потрачу.
Поэтому Вася идет в банк и говорит:
— Я Василий Иванов, хочу автокредит на 1000р.
У Кати есть специальная программа для проверки данных по клиентам. Эта программа может быть как web, так и desktop:
Катя вбивает в программу «Василий Иванов» и получает информацию по клиенту — есть ли он в черных списках? Была ли кредитная история раньше? И так далее. Но что происходит в потрохах приложения?
Катя ввела данные на клиенте. Но когда она нажала «проверить», клиент отправил запрос на сервер:
— Дай мне информацию по Васе Иванову!
Сервер отправил запрос в БД, базу данных:
— Select * from clients where fio = ‘Василий Иванов’. (Дай мне всю информацию по ФИО ‘Василий Иванов’)
— Вот тебе все, что нашла.
Сервер вернул эту информацию клиенту:
А клиент уже отрисовал ее для Кати:
— Ага, кредитная история хорошая.
И делает предложение Васе:
— Пожалуйста, если хотите взять кредит, то мы готовы выделить 1000р на 12 лет под 80% годовых. Устроит?
— Да, меня всё устраивает, давайте скорее деньги, и я побежал за машиной!
Все счастливы, все довольны.
Катя даже не догадывается, какой путь проделали данные в программе, когда она вбила туда ФИО своего клиента. Но мы с вами должны узнать, что же это за путь такой? И к чему все эти сложности? Почему именно такая структура? Почему есть клиент, почему есть сервер?
Зачем нужен клиент
Тут все просто — с клиентом работает пользователь. Он нужен, чтобы превратить байтики программного кода в красивую и понятную картинку. Пользователь — не программист, он не понимает язык программирования или sql. Он понимает формочки и кнопочки. Их в клиенте и рисуем.
Зачем нужен сервер
Клиентов может быть много. В примере с банком у нас может быть по 10 отделений в 10 городах России, а в каждом отделении по 10 операционисток. Тысяча Катек, и у каждой отдельный компьютер.
А мы ведь хотим, чтобы приложение работало быстро. Чтобы оно не тупило и не зависало, нервируя операциониста и заставляя клиента ждать. Значит, машина нужна мощная. Но если делать мощным каждый компьютер операциониста, денег придется вложить очень много!
Поэтому мы выносим всю основную логику на сервер. И вот его уже делаем мощным! А клиентские машины могут быть дешевыми, потому что на них остается лишь логика в стиле «запросить информацию и красиво отрисовать».
Нет дублирования кода
Если бы у нас были только клиентские машины, на каждой из них хранился бы одинаковый код по обработке логики, лежала вся база данных, все справочники террористов и прочая. Но так как сервер и БД вынесены в отдельные звенья, с клиентской машины освобождается куча места… И кода.
Не надо дублировать код, ведь вся основная логика вынесена на более мощный сервер.
На сервере и в базе хранится информация, недоступная простому операционисту. Это:
Есть операционисты, готовые за денюшку слить информацию о клиентах. Есть нечистые на руку люди, готовые невзначай заглянуть через плечо. А, может, клиент сам такой человек. Представляете, отпихивает Вася хрупкую Катю, садится за ее компьютер, и переводит себе на счет миллионы, пока его не повяжет охрана.
Зачем нужна база
При чем же тут БД? Вот у нас есть наш сервер, пусть он и хранит всю информацию. Бывает и так, иногда база просто не нужна и у нас остается двузвенная архитектура клиент-сервер.
В таком случае все данных сервер хранит в памяти. Вот только если сервер упадет, или просто перезагрузится — вся информация будет потеряна. Все, что было в памяти, стирается при выключении системы.
БД (база данных) — отдельный программный продукт, который позволяет:
Да, базы может не быть. Но когда она есть, мы уверены в сохранности данных и легко можем по ним поискать.
Плюсы архитектуры
Резюмируем плюсы архитектуры:
Минусы архитектуры
Упало одно звено — все отдыхают
Если упал сервер или отвалилась база, то есть испортилось 1 звено — всё, все в ступоре, все отдыхают. Сотни, тысячи, да хоть миллионы клиентов если есть — никто не может работать. Все операционистки грустно смотрят на окно «Простите, что-то пошло не так» и разводят руками перед клиентом.
Именно поэтому в бизнес-критичном ПО архитектуру усложняют и даже дублируют. Банк с тысячами операционистов не может позволить себе простой. Поэтому они используют кластер серверов — один упал, остальные работают.
Как в таком случае клиент понимает, куда ему отправлять запрос?
Перед серверами ставят балансировщик, и клиент шлет запрос туда. Сколько бы серверов не поставили в кластер, клиенту это не интересно. У него есть один URL — адрес балансировщика.
И вот с клиента поступает запрос:
— Дай мне всю информацию по Васе Иванову.
— Ребята, новый запрос! Кто меньше загружен?
— У меня 5 запросов в очереди стоит.
Балансировщик отправляет запрос второму серверу.
Такая схема используется для высоконагруженного приложения — когда запросов поступает так много, что один сервер с ними просто не справляется.
Facebook, amazon, google — туда заходят миллионы пользователей. Один сервер с ними не справится. Поэтому ставят кластер, а балансировщик делит между ними нагрузку. И в таком случае в кластере может быть не 2 сервера, а 10, 15, сколько нужно, столько и ставим.
При этом мы можем точно также балансировать базу данных. У нас может быть несколько копий баз данных на самых разных машинах, и балансировщик отправляет запросы то к одной, то ко второй.
Такая схема называется горячий резерв — когда у нас есть несколько серверов, работающих в параллель, и балансировщик распределяет нагрузку между ними.
При этом может быть и схема холодного резерва — когда у нас второй сервер является резервной копией «на всякий случай». Все запросы идут на первый сервер, второй отдыхает.
Но если с первым сервером что-то случится и он помрет, балансировщик перенаправит нагрузку на второй сервер:
В это время у администраторов будет время разобраться с проблемой на сервере 1.
Схема холодного резерва используется тогда, когда один сервер способен выдержать нагрузку и выдавать хорошую скорость работы. Но приложение при этом бизнес-критичное и простой неприемлем.
Простой может быть не только потому, что случилось что-то плохое. Есть еще штатное обновление приложения. Обе схемы резервирования позволяют обновляться безболезненно. Если в кластере два сервера, обновление будет выглядеть так:
Таким образом, схемы резервирования помогают нам устранить проблему «упало 1 звено — все отдыхают». Клиент никогда не узнает, что один или несколько серверов в кластере сдохли, у него всё как работало, так и работает.
Высокая стоимость оборудования
Сервера стоят дорого. Туда нельзя поставить обычный SSD как для домашнего компьютера. Почему? Потому что к железу для серверов совсем другие требования по надежности + есть поддержка специфичных функций:
— у HDD это специальная микропрограмма контроллера, которая оптимизирована для работы диска в RAID, дома это не нужно.
— у SSD это наличие группы конденсаторов, которые хранят энергию на случай отключения питания, чтобы хватило времени скинуть из DDR кэша данные в энергонезависимую память и данные не побились.
SSD — быстро работающий диск, HDD — обычный. RAID — когда мы N дисков вместе соединили, а DDR кэш — это оперативная память
Плюс у серверных решений гарантия обычно гораздо дольше: 5 лет, а не год.
По цене отличаются в 2 раза. Например, SSD:
Вроде не сильно отличается, да? Но смысл в том, что для дома 1 тб хватает за глаза — и фоточки все влезут, и кино, и куча приложений… А для базы данных иногда и 10 тб будет мало. А если делать кластер, то умножаем стоимость на 2, если не больше. Поэтому и разница в цене кажется огромная, но при пересчете на гигабайт небольшая выходит.
Не забывайте, что дома вам просто надо свои фоточки держать, да и те обычно в облаке. А на сервере бизнес-критичный функционал, который жрет дофига ресурсов и который надо дублировать на случай «вдруг первый сдохнет».
Нужно нанять сисадмина ツ
Нам нужно нанять сисадмина, который будет следить за всеми нашеми серверами приложения и БД. Добавляем его зарплату к стоимости оборудования!
Что тестировать
Чтобы понимать, что тестировать, надо понимать, с чем имеет дело человек.
Пользователь работает с клиентом. Это может быть web или desktop приложение, не суть. Операционистке Кате дали рабочее место, показали какую программу запускать и как с ней работать. Она знать не знает о наличии серверов и БД, она работает только с клиентом.
Поэтому тестировщик в первую очередь проверяет клиент! Потому что сервер может работать идеально, вы можете даже написать тесты на уровне API и они все будут зелененькие, и кажется, что все зашибись! А пользователь загрузит отчет и увидит ошибку. Ой.
Сервер работает, на клиенте ошибка. И плевать на сотни «зеленых» автотестов. У пользователя все равно ошибка. И наша задача — посмотреть с его точки зрения.
Однако, если у вас есть доступ к серверу приложения и его базе данных — стоит проверять и их тоже! Так мы можем увидеть «будущий баг». Например:
— Ну, наверное, их и не заполняли.
А их заполняли! Просто сохранение криво сработало. Поэтому, если у нас только черный ящик, то нужно проверять, «а реально ли сохранились данные?». Сохранили? Откройте карточку в новом окне или вызовете информацию через API-метод.
Если доступ к базе есть — просто проверьте по ней, что все хорошо. Если есть доступ к серверным логам — проверьте их на наличие ошибок.
Помимо простых пользователей бывают злые люди, которые пытаются встрять в наше приложение и своровать деньги / данные. Они используют не клиент или сервер — туда у них доступа нет. Они пытаются перехватить данные в пути от клиента к серверу, или от сервера к БД.
Ну а раз нехорошие люди могут это сделать, то тестировщик тоже должен это уметь! Потому что тестировщик предоставляет информацию о нашем продукте.
Тестировщик изучает уязвимости и потом рассказывает команде:
— Ребята, вот я проверил, у нас есть такие-то и такие-то потенциальные дыры. Давайте подумаем, надо нам их как-то закрывать или нет.
То есть не факт, что исправлять проблему будут. Может, у вас некритичное приложение — данные не утекут, деньги вы не храните. Тогда и заморачиваться лишний раз никто не будет, потому что тестировать на защищенность — дорого, специалистов мало.
Но какие-то базовые проверки типа sql-иньекций или XSS-атак стоит изучить и проверить на своем приложении. Хотя бы чтобы понять их критичность. Ведь если атака сломает клиент — ну и пусть, сам себе буратино. А если атака положит сервер, это уже не очень хорошо. И надо хотя бы знать, от чего это бывает.
Итого
Клиент — та программа, с которой работает пользователь. Он знать не знает, это у него на компьютере программа целиком, или где-то за ней прячутся сервер с базой, а то и целый RAID. Он работает в браузере или с desktop-приложением. И всё, что ему нужно знать — это «куда тут тыкать».
Клиенту не нужно много памяти, места на диске и других ресурсов. Поэтому рабочие места относительно дешево стоят. А это именно то, что нам нужно, особенно если нужно закупить оборудование для тысяч операционисток банка.
Сервер — компьютер, на котором хранится само приложение. Весь код, вся логика, все дополнительные материалы и справочники. Например, справочник адресов ФИАС или справочник юр лиц ЕГРЮЛ — они тоже занимают место, как сами по себе, так и в памяти приложения.
Иногда говорят «сервер приложения» и «сервер БД». Это нормально, ведь фактически сервер — это просто машина, компьютер. А базу и сервер приложения обычно хранят на разных машинах, ради безопасности. В таком случае, если говорят «сервер приложения» — речь о втором звене нашей схемы.
Приложения бывают самые разные. Есть ресурсоемкие, им нужно много памяти и места на диске. Есть «легкие», которые можно развернуть даже на домашнем компьютере.
БД (база данных) — хранилище данных. Тут вы можете легко поискать информацию + уверены в том, что она сохранится, даже если в приложении что-то сломается. Подробнее о ней — в статье «Что такое База Данных (БД)»
Сколько места нужно под базу, зависит от количества данных. Есть огромные базы в банках, где и 1тб будет мало. А есть совсем небольшие, которые вы можете установить на своей машине. Например, XAMPP можно поставить. И врядли вы напихаете туда столько данных, что у вас не останется под них место.
Отдельной базы может не быть, тогда структура станет двузвенной: клиент-сервер. И все!
Схема условная, в реальной жизни у нас как минимум будет больше клиентов. А если приложение высоконагруженное, то будет несколько серверов и несколько баз данных:
PS — больше полезных статей ищите в моем блоге по метке «полезное». А полезные видео — на моем youtube-канале