Технология клиент-сервер. Таким образом, все вышеперечисленные недостатки файл-серверной схемы устраняются в архитектуре клиент-сервер

Рассказывает Владимир, веб-разработчик Noveo

Большинству разработчиков сайтов, веб-сервисов и мобильных приложений рано или поздно приходится иметь дело с клиент-серверной архитектурой, а именно разрабатывать web API или интегрироваться с ним. Чтобы не изобретать каждый раз что-то новое, важно выработать относительно универсальный подход к проектированию web API, основываясь на опыте разработки подобных систем. Предлагаем вашему вниманию объединенный цикл статей, посвящённых этому вопросу.

Приближение первое: Действующие лица

В один прекрасный момент, в процессе создания очередного веб-сервиса, я решил собрать все свои знания и размышления на тему проектирования web API для обслуживания нужд клиентских приложений и оформить их в виде статьи или серии статей. Разумеется, мой опыт не претендует на абсолют, и конструктивная критика и дополнения более чем приветствуются.

Чтиво получилось больше философское, нежели техническое, но и для любителей технической части здесь будет над чем поразмыслить. Сомневаюсь, что скажу в этой статье что-то принципиально новое, то, о чем вы никогда не слышали, не читали и о чем не думали сами. Просто попытаюсь уложить все в единую систему, в первую очередь в своей собственной голове, а это уже дорогого стоит. Тем не менее, буду рад, если мои измышления будут вам полезны в вашей практике. Итак, поехали.

Клиент и сервер

Сервером в данном случае мы считаем абстрактную машину в сети, способную получить HTTP-запрос, обработать его и вернуть корректный ответ. В контексте данной статьи совершенно не важны его физическая суть и внутренняя архитектура, будь то студенческий ноутбук или огромный кластер из промышленных серверов, разбросанных по всему миру. Нам в той же мере совершенно неважно, что у него под капотом, кто встречает запрос у дверей, Apache или Nginx, какой неведомый зверь, PHP, Python или Ruby выполняет его обработку и формирует ответ, какое хранилище данных используется: Postgresql, MySQL или MongoDB. Главное, чтобы сервер отвечал главному правилу - услышать, понять и простить ответить.

Клиентом тоже может быть все, что угодно, что способно сформировать и отправить HTTP-запрос. До определенного момента в этой статье нам также не особо будут интересны цели, которые ставит перед собой клиент, отправляя этот запрос, как и то, что он будет делать с ответом. Клиентом может быть JavaScript-сценарий, работающий в браузере, мобильное приложение, злой (или не очень) демон, запущенный на сервере, или слишком поумневший холодильник (уже есть и такие).

По большей части мы будем говорить о способе общения между выше перечисленными двумя, таком способе, чтобы они друг друга понимали, и ни у одного не оставалось вопросов.

Философия REST

REST (Representational state transfer) изначально был задуман как простой и однозначный интерфейс для управления данными, предполагавший всего несколько базовых операций с непосредственным сетевым хранилищем (сервером): извлечение данных (GET), сохранение (POST), изменение (PUT/PATCH) и удаление (DELETE). Разумеется, этот перечень всегда сопровождался такими опциями, как обработка ошибок в запросе (корректно ли составлен запрос), разграничение доступа к данным (вдруг этого вам знать не следует) и валидация входящих данных (вдруг вы написали ерунду), в общем, всеми возможными проверками, которые сервер выполняет перед тем, как выполнить желание клиента .

Помимо этого REST имеет ряд архитектурных принципов, перечень которых можно найти в любой другой статье о REST. Пробежимся по ним кратко, чтобы они были под рукой, и не пришлось никуда уходить:

Независимость сервера от клиента - серверы и клиенты могут быть мгновенно заменены другими независимо друг от друга, так как интерфейс между ними не меняется. Сервер не хранит состояний клиента.
Уникальность адресов ресурсов - каждая единица данных (любой степени вложенности) имеет свой собственный уникальный URL, который, по сути, целиком является однозначным идентификатором ресурса.

Пример: GET /api/v1/users/25/name

Независимость формата хранения данных от формата их передачи - сервер может поддерживать несколько различных форматов для передачи одних и тех же данных (JSON, XML и т.д.), но хранит данные в своем внутреннем формате, независимо от поддерживаемых.

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

Чего нам не хватает

Классический REST подразумевает работу клиента с сервером как с плоским хранилищем данных, при этом ничего не говорится о связанности и взаимозависимости данных между собой. Все это по умолчанию целиком ложится на плечи клиентского приложения. Однако современные предметные области, для которых разрабатываются системы управления данными, будь то социальные сервисы или системы интернет-маркетинга, подразумевают сложную взаимосвязь между сущностями, хранящимися в базе данных. Поддержка этих связей, т.е. целостности данных, находится в зоне ответственности серверной стороны, в то время, как клиент является только интерфейсом для доступа к этим данным. Так чего же нам не хватает в REST?

Вызовы функций

Чтобы не менять данные и связи между ними вручную, мы просто вызываем у ресурса функцию и «скармливаем» ей в качестве аргумента необходимые данные. Эта операция не подходит под стандарты REST, для нее не существует особого глагола, что заставляет нас, разработчиков, выкручиваться кто во что горазд.

Самый простой пример – авторизация пользователя. Мы вызываем функцию login, передаем ей в качестве аргумента объект, содержащий учетные данные, и в ответ получаем ключ доступа. Что творится с данными на серверной стороне – нас не волнует.

Еще вариант – создание и разрыв связей между данными. Например, добавление пользователя в группу. Вызываем у сущности группа функцию addUser, в качестве параметра передаем объект пользователь , получаем результат.

А еще бывают операции, которые вообще не связаны напрямую с сохранением данных как таковых, например, рассылка уведомлений, подтверждение или отклонение каких-либо операций (завершение отчетного периода etc).

Множественные операции

Часто бывает так, и разработчики клиентов поймут, о чем я, что клиентскому приложению удобнее создавать/изменять/удалять/ сразу несколько однородных объектов одним запросом, и по каждому объекту возможен свой вердикт серверной стороны. Тут есть как минимум несколько вариантов: либо все изменения выполнены, либо они выполнены частично (для части объектов), либо произошла ошибка. Ну и стратегий тоже несколько: применять изменения только в случае успеха для всех, либо применять частично, либо откатываться в случае любой ошибки, а это уже тянет на полноценный механизм транзакций.

Для web API, стремящегося к идеалу, тоже хотелось бы как-то привести подобные операции в систему. Постараюсь сделать это в одном из продолжений.

Статистические запросы, агрегаторы, форматирование данных

Частенько бывает так, что на основе хранимых на сервере данных нам нужно получить статистическую выжимку или данные, отформатированные особым образом: например, для построения графика на стороне клиента. По сути это данные, генерируемые по требованию, в той или иной мере на лету, и доступные только для чтения, так что имеет смысл вынести их в отдельную категорию. Одной из отличительных особенностей статистических данных, на мой взгляд, является то, что они не имеют уникального ID.

Уверен, что это далеко не все, с чем можно столкнуться при разработке реальных приложений, и буду рад вашим дополнениям и коррективам.

Разновидности данных

Объекты

Ключевым типом данных в общении между клиентом и сервером выступает объект. По сути, объект – это перечень свойств и соответствующих им значений. Мы можем отправить объект на сервер в запросе и получить в результат запроса в виде объекта. При этом объект не обязательно будет реальной сущностью, хранящейся в базе данных, по крайней мере, в том виде, в котором он отправлен или получен. Например, учетные данные для авторизации передаются в виде объекта, но не являются самостоятельной сущностью. Даже хранимые в БД объекты склонны обрастать дополнительными свойствами внутрисистемного характера, например, датами создания и редактирования, различными системными метками и флагами. Свойства объектов могут быть как собственными скалярными значениями, так и содержать связанные объекты и коллекции объектов , которые не являются частью объекта. Часть свойств объектов может быть редактируемой, часть системной, доступной только для чтения, а часть может носить статистический характер и вычисляться на лету (например, количество лайков). Некоторые свойства объекта могут быть скрыты, в зависимости от прав пользователя.

Коллекции объектов

Говоря о коллекциях, мы подразумеваем разновидность серверного ресурса, позволяющую работать с перечнем однородных объектов, т.е. добавлять, удалять, изменять объекты и осуществлять выборку из них. Помимо этого коллекция теоретически может обладать собственными свойствами (например, максимальное число элементов на страницу) и функциями (тут я в замешательстве, но такое тоже было).

Скалярные значения

В чистом виде скалярные значения как отдельная сущность на моей памяти встречались крайне редко. Обычно они фигурировали как свойства объектов или коллекций, и в этом качестве они могут быть доступны как для чтения, так и для записи. Например, имя пользователя может быть получено и изменено в индивидуальном порядке GET /users/1/name . На практике эта возможность пригождается редко, но в случае необходимости хотелось бы, чтобы она была под рукой. Особенно это касается свойств коллекции, например числа записей (с фильтрацией или без нее): GET /news/count .

В одной из следующих статей я постараюсь классифицировать эти операции и предложить варианты возможных запросов и ответов, основываясь на том, с какими из них мне приходилось сталкиваться на практике.

Приближение второе: Правильный путь

В этом приближении я хотел бы отдельно поговорить о подходах к построению уникальных путей к ресурсам и методам вашего web API и о тех архитектурных особенностях приложения, которые влияют на внешний вид этого пути и его компоненты.

О чем стоит подумать, стоя на берегу

Версионность

Рано или поздно любая действующая система начинает эволюционировать: развиваться, усложняться, масштабироваться, усовремениваться. Для разработчиков REST API это чревато в первую очередь тем, что необходимо запускать новые версии API при работающих старых. Здесь я говорю больше не об архитектурных изменениях под капотом вашей системы, а о том, что изменяется сам формат данных и набор операций с ними. В любом случае версионность нужно предусмотреть как в изначальной организации исходного кода, так и в принципе построения URL. Что касается URL, здесь существует два наиболее популярных способа указания версии API, которой адресован запрос. Префиксация пути example-api.com/v1/ и разведение версий на уровне субдомена v1.example-api.com . Использовать можно любой из них, в зависимости от потребности и необходимости.

Автономность компонентов

Web API сложных систем, поддерживающих несколько пользовательских ролей, зачастую требует разделения на части, каждая из которых обслуживает свой спектр задач. По сути, каждая часть может быть самостоятельным приложением, работать на разных физических машинах и платформах. В контексте описания API нам совершенно не важно, как сервер обрабатывает запрос и какие силы и технологии в этом замешаны. Для клиента API – система инкапсулированная. Тем не менее разные части системы могут обладать совершенно разной функциональностью, например, административная и пользовательская часть. И методология работы с одними и теми же, казалось бы, ресурсами может существенно отличаться. Поэтому такие части необходимо разделять на уровне домена admin.v1.example-api.com или префикса пути example-api.com/v1/admin/ . Это требование не является обязательным, и многое зависит от сложности системы и её назначения.

Формат обмена данными

Самым удобным и функциональным, на мой взгляд, форматом обмена данными является JSON, но никто не запрещает использовать XML, YAML или любой другой формат, позволяющий хранить сериализованные объекты без потери типа данных. При желании можно сделать в API поддержку нескольких форматов ввода/вывода. Достаточно задействовать HTTP заголовок запроса для указания желаемого формата ответа Accept и Content-Type для указания формата переданных в запросе данных. Другим популярным способом является добавление расширения к URL ресурса, например, GET /users.xml , но такой способ кажется менее гибким и красивым, хотя бы потому, что утяжеляет URL и верен скорее для GET-запросов, нежели для всех возможных операций.

Локализация и многоязычность

На практике многоязычность API чаще всего сводится к переводу сервисных сообщений и сообщений об ошибках на требуемый язык для прямого отображения конечному пользователю. Многоязычный контент тоже имеет место быть, но сохранение и выдача контента на разных языках, на мой взгляд, должна разграничиваться более явно, например, если у вас одна и та же статья существует на разных языках, то по факту это две разных сущности, сгруппированные по признаку единства содержания. Для идентификации ожидаемого языка можно использовать разные способы. Самым простым можно считать стандартный HTTP-заголовок Accept-Language . Я встречал и другие способы, такие, как добавление GET-параметра language="en" , использование префикса пути example-api.com/en/ или даже на уровне доменного имени en.example-api.com . Мне кажется, что выбор способа указания локали зависит от конкретного приложения и задач, стоящих перед ним.

Внутренняя маршрутизация

Итак, мы добрались до корневого узла нашего API (или одного из его компонентов). Все дальнейшие маршруты будут проходить уже непосредственно внутри вашего серверного приложения, в соответствии с поддерживаемым им набором ресурсов.

Пути к коллекциям

Для указания пути к коллекции мы просто используем название соответствующей сущности, например, если это список пользователей, то путь будет таким /users . К коллекции как таковой применимы два метода: GET (получение лимитированного списка сущностей) и POST (создание нового элемента). В запросах на получение списков мы можем использовать множество дополнительных GET параметров, применяемых для постраничного вывода, сортировки, фильтрации, поиска etc, но они должны быть опциональными, т.е. эти параметры не должны передаваться как часть пути!

Элементы коллекции

Для обращения к конкретному элементу коллекции мы используем в маршруте его уникальный идентификатор /users/25 . Это и есть уникальный путь к нему. Для работы с объектом применимы методы GET (получение объекта), PUT/PATCH (изменение) и DELETE (удаление).

Уникальные объекты

Во множестве сервисов существуют уникальные для текущего пользователя объекты, например профиль текущего пользователя /profile , или персональные настройки /settings . Разумеется, с одной стороны, это элементы одной из коллекций, но они являются отправной точкой в использовании нашего Web API клиентским приложением, и к тому же позволяют намного более широкий спектр операций над данными. При этом коллекция, хранящая пользовательские настройки может быть вообще недоступна из соображений безопасности и конфиденциальности данных.

Свойства объектов и коллекций

Для того, чтобы добраться до любого из свойств объекта напрямую, достаточно добавить к пути до объекта имя свойства, например получить имя пользователя /users/25/name . К свойству применимы методы GET (получение значения) и PUT/PATCH (изменение значения). Метод DELETE не применим, т.к. свойство является структурной частью объекта, как формализованной единицы данных.

В предыдущей части мы говорили о том, что у коллекций, как и у объектов, могут быть собственные свойства. На моей памяти мне пригодилось только свойство count, но ваше приложение может быть более сложным и специфичным. Пути к свойствам коллекций строятся по тому же принципу, что и к свойствам их элементов: /users/count . Для свойств коллекций применим только метод GET (получение свойства), т.к. коллекция – это только интерфейс для доступа к списку.

Коллекции связанных объектов

Одной из разновидностей свойств объектов могут быть связанные объекты или коллекции связанных объектов. Такие сущности, как правило, не являются собственным свойством объекта, а лишь отсылками к его связям с другими сущностями. Например, перечень ролей, которые были присвоены пользователю /users/25/roles . По поводу работы с вложенными объектами и коллекциями мы подробно поговорим в одной из следующих частей, а на данном этапе нам достаточно того, что мы имеем возможность обращаться к ним напрямую, как к любому другому свойству объекта.

Функции объектов и коллекций

Для построения пути к интерфейсу вызова функции у коллекции или объекта мы используем тот же самый подход, что и для обращения к свойству. Например, для объекта /users/25/sendPasswordReminder или коллекции /users/disableUnconfirmed . Для вызовов функций мы в любом случае используем метод POST. Почему? Напомню, что в классическом REST не существует специального глагола для вызова функций, а потому нам придется использовать один из существующих. На мой взгляд, для этого больше всего подходит метод POST т.к. он позволяет передавать на сервер необходимые аргументы, не является идемпотентным (возвращающим один и тот же результат при многократном обращении) и наиболее абстрактен по семантике.

Надеюсь, что все более-менее уложилось в систему 🙂 В следующей части мы поговорим подробнее о запросах и ответах, их форматах, кодах статусов.

Приближение третье: Запросы и ответы

В предыдущих приближениях я рассказал о том, как пришла идея собрать и обобщить имеющийся опыт разработки web API. В первой части я постарался описать, с какими видами ресурсов и операций над ними мы имеем дело при проектировании web API. Во второй части были затронуты вопросы построения уникальных URL для обращения к этим ресурсам. А в этом приближении я попробую описать возможные варианты запросов и ответов.

Универсальный ответ

Мы уже проговаривали, что конкретный формат общения сервера с клиентом может быть любым на усмотрение разработчика. Для меня наиболее удобным и наглядным кажется формат JSON, хотя в реальном приложении может быть реализована поддержка нескольких форматов. Сейчас же сосредоточимся на структуре и необходимых атрибутах объекта ответа. Да, все данные, возвращаемые сервером, мы будем оборачивать в специальный контейнер - универсальный объект ответа , который будет содержать всю необходимую сервисную информацию для его дальнейшей обработки. Итак, что это за информация:

Success - маркер успешности выполнения запроса

Для того, чтобы при получении ответа от сервера сразу понять, увенчался ли запрос успехом, и передать его соответствующему обработчику, достаточно использовать маркер успешности «success». Самый простой ответ сервера, не содержащий никаких данных, будет выглядеть так:

POST /api/v1/articles/22/publish { "success": true }

Error - сведения об ошибке

В случае, если выполнение запроса завершилось неудачей - о причинах и разновидностях отрицательных ответов сервера поговорим чуть позже, - к ответу добавляется атрибут «error», содержащий в себе HTTP-код статуса и текст сообщения об ошибке. Прошу не путать с сообщениями об ошибках валидации данных для конкретных полей. Правильнее всего, на мой взгляд, возвращать код статуса и в заголовке ответа, но я встречал и другой подход - в заголовке всегда возвращать статус 200 (успех), а детали и возможные данные об ошибках передавать в теле ответа.

GET /api/v1/user { "success": false, "error": { "code" : 401, "message" : "Authorization failed" } }

Data - данные, возвращаемые сервером

Большинство ответов сервера призваны возвращать данные. В зависимости от типа запроса и его успеха ожидаемый набор данных будет разным, тем не менее атрибут«data» будет присутствовать в подавляющем большинстве ответов.

Пример возвращаемых данных в случае успеха. В данном случае ответ содержит запрашиваемый объект user.

GET /api/v1/user { "success": true, "data": { "id" : 125, "email" : "[email protected]", "name" : "John", "surname" : "Smith", } }

Пример возвращаемых данных в случае ошибки. В данном случае содержит имена полей и сообщения об ошибках валидации.

PUT /api/v1/user { "success": false, "error": { "code" : 422, "message" : "Validation failed" } "data": { "email" : "Email could not be blank.", } }

Pagination - сведения, необходимые для организации постраничной навигации

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

Минимальный набор значений для пагинации состоит из:

  • общего числа записей;
  • числа страниц;
  • номера текущей страницы;
  • числа записей на странице;
  • максимального числа записей на странице, поддерживаемого серверной стороной.

Некоторые разработчики web API также включают в пагинацию набор готовых ссылок на соседние страницы, а также первую, последнюю и текущую.

GET /api/v1/articles Response: { "success": true, "data": [ { "id" : 1, "title" : "Interesting thing", }, { "id" : 2, "title" : "Boring text", } ], "pagination": { "totalRecords" : 2, "totalPages" : 1, "currentPage" : 1, "perPage" : 20, "maxPerPage" : 100, } }

Работа над ошибками

Как уже упоминалось выше, не все запросы к web API завершаются успехом, но это тоже часть игры. Система информирования об ошибках является мощным инструментом, облегчающим работу клиента и направляющим клиентское приложение по правильному пути. Слово «ошибка» в этом контексте не совсем уместно. Здесь больше подойдёт слово исключение , так как на самом деле запрос успешно получен, проанализирован, и на него возвращается адекватный ответ, объясняющий, почему запрос не может быть выполнен.

Каковы же потенциальные причины получаемых исключений?

500 Internal server error - всё сломалось, но мы скоро починим

Это как раз тот случай, когда проблема произошла на стороне самого сервера, и клиентскому приложению остаётся только вздохнуть и уведомить пользователя о том, что сервер устал и прилёг отдохнуть. Например, утеряно соединение с базой данных или в коде завелся баг.

400 Bad request - а теперь у вас всё сломалось

Ответ прямо противоположный предыдущему. Возвращается в тех случаях, когда клиентское приложение отправляет запрос, который в принципе не может быть корректно обработан, не содержит обязательных параметров или имеет синтаксические ошибки. Обычно это лечится повторным прочтением документации к web API.

401 Unauthorized - незнакомец, назови себя

Для доступа к этому ресурсу требуется авторизация. Разумеется, наличие авторизации не гарантирует того, что ресурс станет доступным, но не авторизовавшись, вы точно этого не узнаете. Возникает, например, при попытке обратиться к закрытой части API или при истечении срока действия текущего токена.

403 Forbidden - вам сюда нельзя

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

404 Not found - по этому адресу никто не живёт

Такой ответ возвращается, как правило, в трёх случаях: путь к ресурсу неверен (ошибочен), запрашиваемый ресурс был удалён и перестал существовать, права текущего пользователя не позволяют ему знать о существовании запрашиваемого ресурса. Например, пока просматривали список товаров, один из них внезапно вышел из моды и был удалён.

405 Method not allowed - нельзя такое делать

Эта разновидность исключения напрямую связана с использованным при запросе глаголом (GET, PUT, POST, DELETE), который, в свою очередь, свидетельствует о действии, которое мы пытаемся совершить с ресурсом. Если запрошенный ресурс не поддерживает указанное действие, сервер говорит об этом прямо.

422 Unprocessable entity - исправьте и пришлите снова

Одно из самых полезных исключений. Возвращается каждый раз, когда в данных запроса существуют логические ошибки. Под данными запроса мы подразумеваем либо набор параметров и соответствующих им значений, переданных методом GET, либо поля объекта, передаваемого в теле запроса методами POST, PUT и DELETE. Если данные не прошли валидацию, сервер в секции «data» возвращает отчет о том, какие именно параметры невалидны и почему.

Протокол HTTP поддерживает намного большее число различных статус-кодов на все случаи жизни, но на практике они используются редко и в контексте web API не несут практической пользы. На моей памяти мне не приходилось выходить за пределы вышеперечисленного списка исключений.

Запросы

Получение элементов коллекции

Одним из наиболее частотных запросов является запрос на получение элементов коллекции. Информационные ленты, списки товаров, различные информационные и статистические таблицы и многое другое клиентское приложение отображает посредством обращения к коллекционным ресурсам. Для осуществления этого запроса мы обращаемся к коллекции, используя метод GET и передавая в строке запроса дополнительные параметры. Как мы уже обозначили выше, в качестве ответа мы ожидаем получить массив однородных элементов коллекции и информацию, необходимую для пагинации - подгрузки продолжения списка или же конкретной его страницы. Содержимое выборки может быть особым способом ограничено и отсортировано с помощью передачи дополнительных параметров. О них и пойдёт речь далее.

Постраничная навигация

page - параметр указывает на то, какая страница должна быть отображена. Если этот параметр не передан, то отображается первая страница. Из первого же успешного ответа сервера будет ясно, сколько страниц имеет коллекция при текущих параметрах фильтрации. Если значение превышает максимальное число страниц, то разумнее всего вернуть ошибку 404 Not found .

GET /api/v1/news?page=1

perPage - указывает на желаемое число элементов на странице. Как правило, API имеет собственное значение по умолчанию, которое возвращает в качестве поля perPage в секции pagination, но в ряде случаев позволяет увеличивать это значение до разумных пределов, предоставив максимальное значение maxPerPage:

GET /api/v1/news?perPage=100

Сортировка результатов

Зачастую результаты выборки требуется упорядочить по возрастанию или убыванию значений определенных полей, которые поддерживают сравнительную (для числовых полей) или алфавитную (для строковых полей) сортировку. Например, нам нужно упорядочить список пользователей по имени или товары по цене. Помимо этого мы можем задать направление сортировки от A до Я или в обратном направлении, причём разное для разных полей.

sortBy - существует несколько подходов к передаче данных о сложной сортировке в GET параметрах. Здесь необходимо четко указать порядок сортировки и направление.

В некоторых API это предлагается сделать в виде строки:

GET /api/v1/products?sortBy=name.desc,price.asc

В других вариантах предлагается использовать массив:

GET /api/v1/products? sortBy=name& sortBy=desc& sortBy=price& sortBy=asc

В целом оба варианта равносильны, так как передают одни и те же инструкции. На мой взгляд, вариант с массивом более универсален, но тут, как говорится, на вкус и цвет…

Простая фильтрация по значению

Для того, чтобы отфильтровать выборку по значению какого либо поля, в большинстве случаев достаточно передать в качестве фильтрующего параметра имя поля и требуемое значение. Например, мы хотим отфильтровать статьи по ID автора:

GET /api/v1/articles?authorId=25

Усложнённые варианты фильтрации

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

Фильтрация по верхней и нижней границе с использованием операторов сравнения from (больше или равно), higher (больше), to (меньше или равно), lower (меньше). Применяется к полям, значения которых поддаются ранжированию.

GET /api/v1/products?price=500&price=1000

Фильтрация по нескольким возможным значениям из списка. Применяется к полям, набор возможных значений которых ограничен, например, фильтр по нескольким статусам:

GET /api/v1/products?status=1&status=2

Фильтрация по частичному совпадению строки. Применяется к полям, содержащим текстовые данные или данные, которые могут быть приравнены к текстовым, например, числовые артикулы товаров, номера телефонов и т. д.

GET /api/v1/users?name=John GET /api/v1/products?code=123

Именованные фильтры

В некоторых случаях, когда определенные наборы фильтрационных параметров часто употребимы и подразумеваются системой как нечто целостное, особенно если затрагивают внутреннюю, зачастую сложную механику формирования выборки, целесообразно сгруппировать их в так называемые именованные фильтры. Достаточно передать в запросе имя фильтра, и система построит выборку автоматически.

GET /api/v1/products?filters=recommended

Именованные фильтры могут также иметь свои параметры.

GET /api/v1/products?filters=kidds

В этом подразделе я постарался рассказать о наиболее популярных вариантах и способах получения требуемой выборки. Скорее всего, в вашей практике наберется намного больше примеров и нюансов касаемо этой темы. Если у вас есть, чем дополнить мой материал, я буду только рад. Тем временем пост уже разросся до солидных масштабов, так что другие виды запросов мы разберём в следующем приближении.

Независимо от того, как определяется понятие архитектуры «клиент-сервер» (а таких определений в литературе много), в основе этого понятия лежит распределенная модель вычислений. В самом общем случае под клиентом и сервером понимаются два взаимодействующих процесса, из которых один является поставщиком некоторого сервиса для другого.

Термин «клиент-сервер» означает такую архитектуру программного комплекса, в которой его функциональные части взаимодействуют по схеме «запрос-ответ». Если рассмотреть две взаимодействующие части этого комплекса, то одна из них (клиент) выполняет активную функцию, т. е. инициирует запросы, а другая (сервер) пассивно на них отвечает. По мере развития системы роли могут меняться, например некоторый программный блок будет одновременно выполнять функции сервера по отношению к одному блоку и клиента по отношению к другому.

Сервер — один или несколько многопользовательских процессоров с единым полем памяти, который в соответствии с потребностями пользователя обеспечивает им функции вычисления, коммуникации и доступа к базам данных. Сервер можно назвать программу, представляющая какие-то услуги другим программам. Примеры серверов - вебсервер Apache, серверы баз данных - MySQL, ORACLE, сетевые файловые системы и принтера Windows.

Клиент — рабочая станция для одного пользователя, обеспечивающая режим регистрации и др. необходимые на его рабочем месте функции вычисления, коммуникацию, доступ к базам данных и др. Клиентом можно назвать это программа, использующая услугу, представляемую программой сервера. Примеры клиентов - MSIE (MS Internet Explorer), клиент ICQ.

Часто люди клиентом или сервером просто называют компьютер, на котором работает какая-то из этих программ.

В сущности клиент и сервер - это роли, исполняемые программами. Клиенты и сервера физически могут находиться на одном компьютере. Одна и та же программа может быть и клиентом, и сервером одновременно, и т.д… это только роли.

Если проводить аналогию с обществом - банк или магазин - «сервера». Они представляют какие-то услуги своим клиентам. Но банк может в то же время быть клиентом какой-то другой фирмы и т. д…

Обработка Клиент — Сервер — среда, в которой обработка приложений распределена между клиентом и сервером. Нередко в обработке участвуют машины разных типов, причем клиент и сервер общаются между собой с помощью фиксированного множества стандартных протоколов обмена и процедур обращения к удаленным платформам.

СУБД с персональных ЭВМ (такие, как Clipper, DBase, FoxPro, Paradox, Clarion имеют сетевые версии, которые просто совместно используют файлы баз данных тех же форматов для ПК, осуществляя при этом сетевые блокировки для разграничения доступа к таблицам и записям. При этом вся работа осуществляется на ПК. Сервер используется просто как общий удаленный диск большой емкости. Такой способ работы приводит к риску потери данных при аппаратных сбоях.

По сравнению с такими системами системы, построенные в архитектуре Клиент — Сервер, имеют следующие преимущества:

    позволяют увеличить размер и сложность программ, выполняемых на рабочей станции;

    обеспечивает перенесение наиболее трудоемких опе-раций на сервер, являющийся машиной большей вычислительной мощности;

    уменьшает до минимума возможность потери содержащейся в БД информации за счет применения имеющихся на сервере внутренних механизмов защиты данных, таких, как, например системы трассировки транзакций, откат после сбоя, средства обеспечения целостности данных;

    в несколько раз уменьшает объем информации, передаваемый по сети.

    В архитектуре «клиент-сервер» сервер базы данных не только обеспечивает доступ к общим данным, но и берет на себя всю обработку этих данных. Клиент посылает на сервер запросы на чтение или изменение данных, которые формулируются на языке SQL. Сервер сам выполняет все необходимые изменения или выборки, контролируя при этом целостность и согласованность данных, и результаты в виде набора записей или кода возврата посылает на компьютер клиента.

    Она позволяет оптимальным образом распределить вычислительную нагрузку между клиентом и сервером, что также влияет на многие характеристики системы: стоимость, производительность, поддержку.

    1.2. История…

    Архитектура и термин «клиент-сервер» впервые использовались в начале 80-тых годов. Первые приложения с архитектурой «клиент-сервер» были базы данных.

    До этого не было ясного разделения - программа обычно всё делала сама - в том числе работала с данными в файловой системе, представлением данных пользователю и др. Со временем рос объем и критичность данных для бизнеса, и это со временем начало породить проблемы (быстродействия, безопасности и другие).

    Тогда придумали, что удобно поставить базу данных на мощном отдельном компьютере (сервере) и разрешить эту базу данных использовать многим пользователям малого компьютера (клиентам) через сеть, что и было сделано.

    По существу «взрыв» популярности технологии «клиент-сервер» был вызван изобретением фирмой IBM простого языка запросов к реляционным базам данных SQL. Сегодня SQL всеобщий стандарт работы с базами данных. В последнее время этот «взрыв» продолжает изобретение Интернета, в котором буквально каждое взаимодействие происходит по архитектуре «клиент-сервер».

    1.3. Протоколы

    Сервер и клиент в сети между собой «разговаривает» на «языке» (в широком смысле слов), понятном обеим сторонам. Этот «язык» называют протоколом.

    В случае банка, протоколом можно назвать бланки, которые заполняет клиент.

    В нашем же случае, примеры протоколов:

    FTP (File Transfer Protocol)

    HTTP (Hyper Text Transfer Protocol)

    SMTP (Simple Mail Transfer Protocol)

    IP (Internet Protocol)

    MySQL Client/Server Protocol

    Заметим, что протоколы может быть разных уровней. Классификационные системы уровней может быть разные, но одна из самых известных линеек - OSI (Open Systems Interconnection), в котором 7 уровней.

    Например, HTTP - протокол прикладного (седьмого - самого высокого) уровня, а IP - протокол сетевого (третьего) уровня.

    1.4. Распределение функций в архитектуре «клиент-сервер»

    В классической архитектуре клиент-сервер приходится распределять три основные части приложения по двум физическим модулям. Обычно ПО хранения данных располагается на сервере (например, сервере базы данных), интерфейс с пользователем — на стороне клиента, а вот обработку данных приходится распределять между клиентской и серверной частями. В этом-то и заключается основной недостаток двухуровневой архитектуры, из которого следуют несколько неприятных особенностей, сильно усложняющих разработку клиент-серверных систем.

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

    Основная задача, которую решает клиентское приложение, - это обеспечение интерфейса с пользователем, т. е. ввод данных и представление результатов в удобном для пользователя виде, и управление сценариями работы приложения.

    Основные функции серверной СУБД - обеспечение надежности, согласованности и защищенности данных, управление запросами клиентов, быстрая обработка SQL-запросов.

    Вся логика работы приложения - прикладные задачи, бизнес-правила - в двух-звенной архитектуре распределяются разработчиком между двумя процессами: клиентом и сервером (рис. 1).

    Сначала большая часть функций приложения решалась клиентом, сервер занимался только обработкой SQL-запросов. Такая архитектура получила название «толстый клиент - тонкий сервер».

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

    Такое решение имеет очевидные преимущества, например его легче поддерживать, т. к. все изменения нужно вносить только в одном месте - на сервере.

    рассмотренные выше модели имеют следующие недостатки.

    1. «Толстый» клиент:

    – сложность администрирования;

    – усложняется обновление ПО, поскольку его замену нужно производить одновременно по всей системе;

    – усложняется распределение полномочий, так как разграничение доступа происходит не по действиям, а по таблицам;

    – перегружается сеть вследствие передачи по ней необработанных данных;

    – слабая защита данных, поскольку сложно правильно распределить полномочия.

    2. «Толстый» сервер:

    – усложняется реализация, так как языки типа PL/SQL не приспособлены для разработки подобного ПО и нет хороших средств отладки;

    – производительность программ, написанных на языках типа PL/SQL, значительно ниже, чем созданных на других языках, что имеет важное значение для сложных систем;

    – программы, написанные на СУБД-языках, обычно работают недостаточно надежно; ошибка в них может привести к выходу из строя всего сервера баз данных;

    – получившиеся таким образом программы полностью непереносимы на другие системы и платформы.

    Для решения перечисленных проблем используются многоуровневые (три и более уровней) архитектуры клиент-сервер. многоуровневая архитектура клиент-сервер позволяет существенно упростить распределенные вычисления, делая их не только более надежными, но и более доступными.

    Однако язык, на котором пишутся хранимые процедуры, не является достаточно мощным и гибким, чтобы на нем было удобно реализовывать сложную логику приложения.

    Тогда возникла тенденция поручить выполнение прикладных задач и бизнес-правил отдельному компоненту приложения (или нескольким компонентам), которые могут работать как на специально выделенном компьютере - сервере приложений, так и на том же компьютере, где работает сервер базы данных. Так возникли трехзвенные и многозвенные архитектуры «клиент-сервер».


    Рис. 1. Распределение функций между клиентом и сервером

    Появилось специальное программное обеспечение (ПО) промежуточного слоя, которое должно обеспечить совместное функционирование множества компонентов такого многокомпонентного приложения. Такие приложения являются гибкими, масштабируемыми, но сложными в разработке.


    СПИСОК ИСПОЛЬЗУЕМОЙ ЛИТЕРАТУРЫ

  1. Информатика / Под ред. Н.В. Макаровой.–М.: Финансы и статистика, 1998.

    Евдокимов В.В. и др. Экономическая информатика. СПб.: Питер, 2004.

    Казаков С.И. Основы сетевых технологий – М.: Радио и связь, 2004.

    Когаловский М.Р., Технология баз данных на персональных ЭВМ, – М.: Финансы и статистика, 2003.

    Попов В.В. Основы компьютерных технологий. –М.: Финансы и статистика, 2001.

    Фигурнов В.Э. IBM PC для пользователя. М., 2000.

ОПЕРАЦИОННАЯ СИСТЕМА MS-DOS . ОСНОВНЫЕ ПОНЯТИЯ И КОМАНДЫ ОСНОВНЫЕ ПОНЯТИЯ: БАЗА ДАННЫХ, СУБД, СУЩНОСТЬ, АТРИБУТ, СВЯЗЬ (ОДИН-К-ОДНОМУ, ОДИН-КО-МНОГИМ, МНОГИМ-КО-МНОГИМ), ОТНОШЕНИЕ, ПЕРВИЧНЫЙ КЛЮЧ

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

Серверами называются процессы, отвечающие за поддержку и файловой системы, а клиентами - процессы, которые посылают запрос и ожидают ответ от сервера.

Модель клиент-сервер используется при построении системы на основе СУБД, а также почтовые системы. Существует еще так называемая файл-серверная архитектура, которая существенно отличается от клиент-серверной.

Данные в файл-серверной системе сохраняются на файловом сервере (Novell NetWare или WindowsNT Server), а обрабатываются они на рабочих станциях посредством функционирования "настольных СУБД", таких как Access, Paradox, FoxPro и т.п.

СУБД располагается на рабочей станции, а манипулирование данными производится несколькими независимыми и несогласованными между собой процессами. Все данные при этом передаются с сервера по сети на рабочую станцию, что замедляет скорость обработки информации.

Технология клиент-сервер реализована функционированием двух (как минимум) приложений - клиентов и сервера, которые делят функции между собой. За хранение и непосредственное манипулирование данных отвечает сервер, примером которого может быть SQLServer, Oracle, Sybase и другие.

Пользовательский интерфейс формирует клиент, в основе построения которого используются специальные инструменты или настольные СУБД. Логическая обработка данных выполняется частично на клиенте, и частично на сервере. Посылка запросов на сервер выполняется клиентом, обычно на языке SQL. Полученные запросы обрабатываются сервером, и клиенту (клиентам) возвращается результат.

При этом данные обрабатываются там же, где они хранятся - на сервере, поэтому большой объем их не передается по сети.

Преимущества архитектуры клиент-сервер

Технология клиент-сервер привносит в информационную систему такие качества:

  • Надежность

Модификация данных осуществляется сервером баз данных при помощи механизма транзакций, придающего совокупности операций такие свойства, как: 1) атомарность, которая обеспечивает целостность данных при любом завершении транзакции; 2) независимость транзакций разных пользователей; 3) устойчивость к сбоям - сохранение результатов завершения транзакции.

  • Масштабируемость, т.е. способность системы не зависеть от количества пользователей и объемов информации без замены используемого программного обеспечения.

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

  • Безопасность, т.е. надежная защита информации от
  • Гибкость. В приложениях, работающих с данными, выделяют логических слои: пользовательский интерфейс; правила логической обработки; управление данными.

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

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

Трехуровневое приложение допускает промежуточный уровень, который реализует бизнес-правила, являющиеся наиболее изменяемыми компонентами.

Несколько уровней позволяют гибко и с наименьшими затратами адаптировать имеющееся приложение к постоянно модифицируемым требованиям бизнеса.

Архитектура клиент-сервер предназначена для разрешения проблем файл-серверных приложений путем разделения компонентов приложения и размещения их там, где они будут функционировать наиболее эффективно. Особенностью архитектуры клиент-сервер является использование выделенных серверов баз данных, понимающих запросы на языке структурированных запросов SQL (Structured Query Language) и выполняющих поиск, сортировку и агрегирование информации.

Отличительная черта серверов БД - наличие справочника данных, в котором записана структура БД, ограничения целостности данных, форматы и даже серверные процедуры обработки данных по вызову или по событиям в программе.

Объектами разработки в таких приложениях помимо диалога и логики обработки являются, прежде всего, реляционная модель данных и связанный с ней набор SQL-операторов для типовых запросов к базе данных.

Большинство конфигураций клиент-сервер использует двухуровневую модель, в которой клиент обращается к услугам сервера. Предполагается, что диалоговые компоненты PS и PL размещаются на клиенте, что позволяет обеспечить графический интерфейс. Компоненты управления данными DS и FS размещаются на сервере, а диалог (PS, PL), логика BL и DL - на клиенте. Двухуровневое определение архитектуры клиент-сервер использует именно этот вариант: приложение работает у клиента, СУБД - на сервере (рис. 1.4.).

Рис. 6 . Классический вариант клиент-серверной информационной системы

Поскольку эта схема предъявляет наименьшие требования к серверу, она обладает наилучшей масштабируемостью. Однако сложные приложения, вызывающие большое взаимодействие с БД, могут жестко загрузить как клиента, так и сеть. Результаты SQL-запроса должны вернуться клиенту для обработки, потому что там находится логика принятия решения. Такая схема приводит к дополнительному усложнению администрирования приложений, разбросанных по различным клиентским узлам. Для сокращения нагрузки на сеть и упрощения администрирования приложений компонент BL можно разместить на сервере. При этом вся логика принятия решений оформляется в виде хранимых процедур и выполняется на сервере БД.

Хранимая процедура - процедура с операторами SQL для доступа к БД, вызываемая по имени с передачей требуемых параметров и выполняемая на сервере БД.

Хранимые процедуры могут компилироваться, что повышает скорость их выполнения и сокращает нагрузку на сервер. Хранимые процедуры улучшают целостность приложений и БД, гарантируют актуальность коллективно используемых операций и вычислений. Улучшается сопровождение таких процедур, а также безопасность (нет прямого доступа к данным).

ПРИМЕЧАНИЕ

Следует помнить, что перегрузка хранимых процедур прикладной логикой может перегрузить сервер, что приведет к потере производительности. Эта проблема особенно актуальна при разработке крупных информационных систем, в которых к серверу может одновременно обращаться большое количество клиентов. Поэтому в большинстве случаев следует принимать компромиссные решения: часть логики приложения размещать на стороне сервера, часть - на стороне клиента. Такие клиент-серверные системы называются системами с разделенной логикой. Данная схема при удачном разделении логики позволяет получить более сбалансированную загрузку клиентов и сервера, но при этом затрудняется сопровождение приложений.

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

В настоящее время архитектура клиент-сервер получила признание и широкое распространение как способ организации приложений для рабочих групп и информационных систем корпоративного уровня. Подобная организация работы повышает эффективность выполнения приложений за счет использования возможностей сервера БД, разгрузки сети и обеспечения контроля целостности данных.

Двухуровневые схемы архитектуры клиент-сервер могут привести к некоторым проблемам в сложных информационных приложениях с множеством пользователей и запутанной логикой. Решением этих проблем может стать использование многоуровневой архитектуры.

Многоуровневая архитектура

Многоуровневая архитектура стала развитием архитектуры клиент-сервер и в своей классической форме состоит из трех уровней:

· нижний уровень представляет собой приложения клиентов, выделенные для выполнения функций и логики представлений PS и PL и имеющие программный интерфейс для вызова приложения на среднем уровне;

· средний уровень представляет собой сервер приложений, на котором выполняется прикладная логика BL и с которого логика обработки данных DL вызывает операции с базой данных DS;

· верхний уровень представляет собой удаленный специализированный сервер базы данных, выделенный для услуг обработки данных DS и файловых операций FS (без риска использования хранимых процедур).

Подобную концепцию обработки данных пропагандируют, в частности, фирмы Oracle, Sun, Borland и др.

Трехуровневая архитектура позволяет еще больше сбалансировать нагрузку на разные узлы и сеть, а также способствует специализации инструментов для разработки приложений и устраняет недостатки двухуровневой модели клиент-сервер.

Централизация логики приложения упрощает администрирование и сопровождение. Четко разделяются платформы и инструменты для реализации интерфейса и прикладной логики, что позволяет с наибольшей отдачей реализовывать их специалистам узкого профиля. Наконец, изменения прикладной логики не затрагивают интерфейса, и наоборот. Но поскольку границы между компонентами PL, BL и DL размыты, прикладная логика может появиться на всех трех уровнях. Сервер приложений с помощью монитора транзакций обеспечивает интерфейс с клиентами и другими серверами, может управлять транзакциями и гарантировать целостность распределенной базы данных. Средства удаленного вызова процедур наиболее соответствуют идее распределенных вычислений: они обеспечивают из любого узла сети вызов прикладной процедуры, расположенной на другом узле, передачу параметров, удаленную обработку и возврат результатов.

С ростом систем клиент-сервер необходимость трех уровней становится все более очевидной. Продукты для трехзвенной архитектуры, так называемые мониторы транзакций, являются относительно новыми. Эти инструменты в основном ориентированы на среду UNIX, однако прикладные серверы можно строить на базе Мicrosoft Windows NT с использованием вызова удаленных процедур для организации связи клиентов с сервером приложений. На практике в локальной сети могут использоваться смешанные архитектуры (двухуровневые и трехуровневые) с одним и тем же сервером базы данных. С учетом глобальных связей архитектура может иметь больше трех звеньев. В настоящее время появились новые инструментальные средства для гибкой сегментации приложений клиент-сервер по различным узлам сети.

Таким образом, многоуровневая архитектура распределенных приложений позволяет повысить эффективность работы корпоративной информационной системы и оптимизировать распределение ее программно-аппаратных ресурсов. Но пока на российском рынке по-прежнему доминирует архитектура клиент- сервер.

Интернет/интранет-технологии

В развитии технологии Интернет/интранет основной акцент пока что делается на разработке инструментальных программных средств. В то же время наблюдается отсутствие развитых средств разработки приложений, работающих с базами данных.

Компромиссным решением для создания удобных и простых в использовании и сопровождении информационных систем, эффективно работающих с базами данных, стало объединение Интернет/интранет-технологии с многоуровневой архитектурой. При этом структура информационного приложения приобретает следующий вид: браузер - сервер приложений - сервер баз данных - сервер динамических страниц - web-сервер. Благодаря интеграции Интернет/интранет-технологии и архитектуры клиент-сервер процесс внедрения и сопровождения корпоративной информационной системы существенно упрощается при сохранении достаточно высокой эффективности и простоты совместного использования информации.

Области применения и примеры реализации информационных систем

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

Благодаря стремительному развитию информационных технологий наблюдается расширение области их применения. Если раньше чуть ли не единственной областью, в которой применялись информационные системы, была автоматизация бухгалтерского учета, то сейчас наблюдается внедрение информационных технологий во множество других областей. Эффективное использование корпоративных информационных систем позволяет делать более точные прогнозы и избегать возможных ошибок в управлении. Из любых данных и отчетов о работе предприятия можно извлечь массу полезных сведений. И информационные системы как раз и позволяют извлекать максимум пользы из всей имеющейся в компании информации. Именно этим фактом и объясняются жизнеспособность и бурное развитие информационных технологий - современный бизнес крайне чувствителен к ошибкам в управлении, и для принятия грамотного управленческого решения в условиях неопределенности и риска необходимо постоянно держать под контролем различные аспекты финансово-хозяйственной деятельности предприятия (независимо от профиля его деятельности).

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

Рассмотрим наиболее важные задачи, решаемые с помощью специальных программных средств.

Каждый человек, работавший с компьютером, слышал о технологии клиент-сервер. В основе этой технологии лежат два основных понятия: клиент и сервер. Клиент - компьютер, осуществляющий запрос к серверу на выполнение каких-либо действий или предоставление какой-либо информации. Сервер - компьютер, обычно более мощный, чем компьютер-клиент. Модель функционирования такой системы заключается в следующем: клиент делает запрос серверу, сервер (серверная часть) получает запрос, выполняет его и отсылает результат клиенту (клиентская часть).

Сервер может обслуживать нескольких клиентов одновременно. В этом случае говорят о многопользовательском режиме. Только не стоит понимать слово "одновременно" в буквальном смысле. Запросы выполняются сервером последовательно. Если одновременно приходит более одного запроса, то запросы устанавливаются в очередь. В данном случае очередь - это список невыполненных клиентских запросов. Иногда запросы могут иметь приоритеты. Приоритет - это уровень "важности" выполнения запроса. Запросы с более высокими приоритетами должны выполняться раньше.

Существует маленькое исключение по поводу последовательной обработки. Операционная система Windows является многозадачной и многопоточной. Многозадачность - это свойство операционной системы исполнять несколько пользовательских приложений (программ).

Это означает, что на сервере может быть запущено несколько задач, каждая из которых может исполнять свой отдельный запрос. Многопоточность дает возможность исполнять несколько запросов в пределах одной задачи. Что это дает? - Происходит увеличение производительности сервера.

Цикл выполнения запроса состоит из пересылки запроса и ответа между клиентом и сервером и непосредственным выполнением этого запроса на сервере.

Как правило, выполнение запроса (сложного запроса) происходит дольше, чем время, затрачиваемое на пересылку запроса и результата. Поэтому в серверах применяются системы распределения транзакций (запросов) между доменами (частями) сервера. Транзакция - это набор команд, которые либо выполняются все или не выполняется ни одна. Домен - это элемент сервера. Нередко сервер на физическом уровне представляет собой не один, а группу компьютеров, объединенных в одну систему для обеспечения каких-либо операций. В этом случае домен - это компьютер, входящий в архитектуру сервера.

Существует концепции построения системы клиент-сервер:

1) Слабый клиент - мощный сервер - вся обработка информации осуществляется целиком сервером. Сервер посылает готовый результат, не требующий дополнительной обработки. Клиент только ведет диалог с пользователем: составляет запрос, отсылает запрос, принимает запрос и выводит информацию на экран (на принтер, в файл).

2) Сильный клиент - часть обработки информации перепоручается клиенту.

Простой пример: пользователю требуется список сотрудников фирмы, отсортированный по фамилиям. В первом случае, сервер по клиентскому запросу извлекает фамилии (например, из базы данных) и сортирует их сам. Готовый отсортированный список отсылается клиенту. Клиенту необходимо только осуществить вывод на экран. Во втором случае, сервер только извлекает фамилии и отсылает данные клиенту. Клиент сортирует список и выводит его на экран.

Но это далеко не все. Допустим, пользователь захотел отсортировать полученный список по уровню зарплаты. В первом случае клиент формирует новый запрос к серверу, сервер его выполняет и посылает готовый ответ клиенту, который только выводит его на экран. Во втором случае клиент сортирует список сам без обращения к серверу. Естественно, во втором случае сервер будет менее загружен.

Существует еще одно важное понятие "время ожидания". "Время ожидания" - это время, через которое пользователь, послав запрос серверу, получит от него ответ. Время ожидания наиболее важный показатель производительности системы, реализующей концепцию клиент-сервер.

При частичной обработке данных на клиенте "время ожидания" меньше. Меньше оно за счет упрощения запроса и времени его выполнения. Отсюда меньше ожидание в очереди для исполнения запроса.

Безусловно, что время конечной обработки на клиенте может быть немного выше за счет разности в производительности сервера. Отсюда может несколько возрастать время ожидания. В конечном счете, это все равно выгоднее, т.к. время ожидания в очереди запросов на сервере меньше.

Многие серверы не выдерживают нагрузки ("напора" запросов) и просто "подвисают". В таком случае есть два альтернативных способа: увеличение производительности и перенос части операций над данными на клиента. Как правило, увеличение производительности значительно более дорогостоящая операция, и тоже, в своем смысле, конечная. Остается только "разгрузка" сервера и перенос части обработки данных на клиента.

P.S. Нередко в ряде организаций в качестве сервера сознательно используют устаревшие компьютеры. На них хорошо размещать файловые хранилища, принт-серверы (к нему подключается офисный принтер), WEB-серверы (Интернет-серверы), небольшие базы данных (серверную часть). Это оправдано с экономической точки зрения.

Применение самых мощных компьютеров в качестве серверов целесообразно в банковской сфере, т.к. объем платежей неизменно возрастает. Соответственно, возрастает необходимый объем вычислительных ресурсов. Здесь оправдана "борьба" за единицы процентов увеличения производительности.

Сергей СОКОЛОВ (БГУИР)