Надо бы попробовать эти сервисы, как на презентации рекомендуют
А вот и оригинальная презентация
Надо бы попробовать эти сервисы, как на презентации рекомендуют
А вот и оригинальная презентация
продолжение см часть II “Идеальное” решение
Multipart/mixed MIME messages.
Так как HTTP протокол полон приятных сюрпризов, то есть ещё один способ втиснуть несколько request-ов в один, и соотвественно несколько respons-ов тоже, в один. Всё, что надо сделать – это указать “Content-Type: multipart/mixed”. А затем аккуратно перечислить все что надо. Разделительные символы прилагаются.
Вот пример
POST /batch-proxy HTTP/1.1 Host: example.org Content-Type: multipart/mixed; boundary=batch -batch Batch-Operation: POST /my/resource1 Host: example.org Content-Type: application/xml <?xml version="1.0″?> <entry xmlns="...">...</entry> -batch Batch-Operation: DELETE /my/resource2 Host: example.org If-Match: "ABC123XYZ"
Выглядит замечательно, не так ли? Снимается проблема ~37% overhead в трафике, так как можно текст передавать как текст, а двоичные данные как двоичные данные. Правда на этом достоинства и кончаются. А проблемы всё теже самые, и не REST и security hole, и не прозрачность в общем, смотри выше по списку.
Кроме того, надо помнить, что MIME был создан для передачи 8-битного текста через 7-ми битный SMTP. Да в нём есть много интересного, но HTTP не является MIME совместимым протоколом. Есть тонкие различия вызванные в основном тем, что HTTP оптимизировался для передачи данных через двоичные соединения + обратная совместимость, а у MIME были совсем другие проблемы – вроде ограничения на максимальную длинну строки в e-mail. Всех желающих углубится в эти различия приглашаю ознакомится с секцией 19.4 RFC2616
На практике всё это означает, что клиенту и серверу нужно иметь качественный парсер MIME сообщений. Не просто продвинутый HTTP клиент, но и такой довольно экзотический парсер. По этому пути пошли ребята из Microsoft построив свою ADO.NET Data Services Framework а также в Google – batching для GData. Если вам такой путь приемлем – то для Java есть бесплатный mime4j, а для .NET есть комерческий Mime4Net.
Для тех, кто не хочет возится с MIME есть уж совсем плохое решение
XML/JSON mark-up
Берем и решаем задачу в лоб. Конвертируем всё в текст, для разметки используем XML или JSON.
Пример с JSON
POST /batch-proxy HTTP/1.1
Content-Type: application/json
Accept: application/json
X-HTTP-Method-Override: BATCH
[
{
"method" : "PUT",
"url" : "http://someserver.com/some/resource/url",
"body" : "<request body goes here>",
"If-Match" : "xxxxxxxxxxx"
},
{
"method" : "GET",
"url" : "http://someserver.com/some/resource/url2"
},
]
Пример с XML
POST /batch-proxy HTTP/1.1
Content-Type: application/xml
Accept: application/xml
X-HTTP-Method-Override: BATCH
<?xml version='1.0'?>
<batch xmlns:b='http://batch.someserver.com/schema'>
<b:request verb='put' uri= http://someserver.com/some/resource/url'>
<b:headers>
<b:header name='Content-Type' value='text/xml; charset=UTF-8' />
<b:header name='Content-Length' value='XXX' />
</b:headers >
<b:body>
<![CDATA[ ... ]]>
</b:body>
</b:request>
<b:request verb='get' uri='http://someserver.com/some/resource/url2'>
<b:headers>
<b:header name='Accept' value='text/xml' />
</b:headers >
</b:request>
</batch>
Очевидно, что XML намного более избыточен, но решение следует принимать на основании доступности того или другого парсера. Ответы сервера выглядят точно также.
Таким образом:
А вот так например может выглядять response содержащий двоичные данные
200 OK
Content-Type: application/json; charset=UTF-8'
[
{
"code" : 200,
"Content-type": "application/octet-stream",
"Content-transfer-encoding": "base64",
"body": "PGh0bWw+CiAgPGhlYWQ+CiAgPC9oZWFkPgogIDxib2R=="
}
{
"code" : 200,
"Content-type": "application/octet-stream",
"Content-transfer-encoding": "base64",
"body": "PGh0bWw+CiAgPGhlYWQ+CiAgPC9oZWFkPgogIDxib2R=="
}
]
Что же плохого в этом решении? А все из списка приведенного в самом начале статьи. Всё что ни возьми – всё и плохо, и не REST. И тем не менее этот подход является самым простым для реализации. А простотой не стоит пренебрегать.
Есть несколько приёмов которые помогут предложить пристойные ответы на список недостатков. Можно
продолжение см часть I Общие положения

HTTP 1.1 протокол изначально поддерживает приём-передачу нескольких request-response. Для этого нужны persisted connections, pipelining и chunking см ниже.
Клиент открывает соединение, пишет туда request-ы, читает respons-ы. Кроме очевидных требований о поддержке этих persisted connections, pipelining и chunking на сервере и клиенте, есть ещё одна неприятность - протокол требует, что бы клиент выслал заново все свои запросы сделанные в рамках этого pipelined соединения если оно прервётся в середине сеанса. А для того, что бы эту перепосылку можно было сделать без опаски, все запросы должны быть idempotent, т.е. только GET, HEAD, OPTIONS, PUT и DELETE. Это решение действительно очень хорошее с точки зрения REST – URI уникально адресуют ресурсы, HTTP headers означают правильные вещи и обрабатываются правильным образом, все транзитные сервера видят HTTP метод и могут, что-то правильное по этому поводу предпринять.
Однако, это «идеальное» решение существует главным образом на бумаге. Persisted connections не поддерживают мобильные устройства. Не все HTTP клиенты умеют читать chunked responses и использовать pipelining, привет AJAX рещениям. Да что chunked responses – для многих библиотек послать PUT запрос – уже проблема. Финальным аккордом тут является отсутствие поддержки метода POST в HTTP pipelining.
Раз «идеальное» решение не подходит, вернёмся к идее тунелирования HTTP протокола внутри HTTP.
Что такое persisted connections, pipelining и chunking:
По умолчанию все соеднинения в HTTP 1.1 постоянные. Сервер не закрывает соединение сразу после обработки запроса тем самым позволяя клиенту использовать это соединение опять и опять. Если клиент желает получить несколько ресурсов с одного и тогоже сервера получается большой выигрыш в производительности. Вместо того, что бы открывать несколько соединений, все запросы пройдут по этому единственному каналу. Как клиент так и сервер могут оборвать этот канал с помощью HTTP header «Connection: close». Интересно, что запросы-ответы не обязаны быть строго последовательными, другими словами, клиент не обязан ждать ответа на первый запрос, а может сразу делать следующий и следующий, это становится возможным благодаря
Клиент посылает серию запросов, а сервер возвращает ответы в том порядке в котором были получены запросы. Часто бывает, что содержимое ответа генерируется динамически и сервер не знает точную длину которую следовало бы поместить в HTTP header Content-Length. Это нормально, в HTTP 1.1 в отличие от HTTP 1.0 заголовок Content-Length не является обязательным.
Так как Content-Length не передаётся, то нужен какой-то механизм, который бы сообщил клиенту, где кончается один response и начинается следующий. HTTP 1.1 решает эту проблему с помощью
В случае динамических ресурсов, когда response не содержит Content-Length, он содержит Transfer-Encoding: chunked. Само же тело содержит куски с указаннием длины индивидуального куска. Кусок нулевой длины отмечает конец respons-а. Тут, пользуясь случаем, передаю привет IE6, который виснет, если ему этот последний кусок не передать.
Зачем я это всё рассказываю – в большинстве случаев, все эти технические детали скрыты в HTTP библиотеках или даже в абстракциях самого языка, но если мы уж собрались строить HTTP внутри HTTP то это надо понимать.
Что же делать? К сожалению существует только плохое решение и очень плохое.
продолжение см часть III “Плохие” решения
HTTP внутри HTTP это, как реторта с
личинками дельфинов – вещь в себе
Если вы разрабатываете REST API, то рано или поздно к вам придут ваши клиенты с просьбой сделать пакетную обработку. Сделать так, что бы сервер приимал произвольный набор запросов одним пакетом и отправлял назад все результаты тоже одновременно. Это касается не только GET запросов, а любых методов – PUT, POST, DELETE и т.д. Ответы тоже будут разные, и будут содержать различные типы данных – например текст в различных encoding-ах и charset-ах, или двоичные данные в произвольном формате. В общем случае, скажут они, было бы полезно уметь обрабатывать пакеты любых HTTP запросов, в том числе запросы к внешним серверам которые необходимо исполнить последовательно с запросами к серверам из локальной сети.
С первого взгляда это кажется замечательной идеей. Клиент делает единственный POST запрос, получает единственный ответ и здорово экономит на сетевых задержках. На самом деле, здесь столько подводных камней, что вы сможете пожалеть что вообще с этим связались. Но выбора обычно нет. Что же тут плохого? Посмотрим сначала на
Ну вот и всё, что бы из REST сделать SOAP больше ничего не нужно. На самом деле, стало даже хуже, чем если бы SOAP использовалось с самого начала – транзитные сервера теперь не знают у каких request/response HTTP headers значат то, что написанно в спецификации, а у каких уже ничего не значат.
Существуют также и
Каким бы образом это решение не было бы сделано, результат будет являться тунелированием HTTP протокола внутри HTTP протокола. Задумайтесь на секунду, что это значит.
На самом деле, если заглянуть в спецификацию протокола HTTP 1.1 то можно увидеть, что существует «Идеальное» решение
продолжение см часть II “Идеальное” решение
Последняя преграда на пути к полному забвению AppManager-а – это email alerts. AppManager out of the box может их отсылать и вести состояние мониторов, а Cacti нет. К счастью решение есть. Вот тут нужно взять Plugin Architecture и установить, затем здесь взять plug-in Thold.
Выглядеть оно обещает вот так
Народ на форумах вроде не жалуется. Надо как руки дойдут попробовать. К сожалению AppManager уже всё равно куплен.
Замечательная статья о парадигмах программирования ссылка
Замечательный текст. Про рунет времен первого интернет бума. Очень познавательно.
http://www.ashmanov.com/pap/bubble/
Настоящие имена компаний изменены, но при желании узнаются. Сохраню пожалуй себе на случай если пропадёт статья.
Жизнь внутри пузыря
Предал светлые идела Java, работаю над проектом на C#. Прошёл месяц, так что все начальные впечатления должны были сгладится – и вот каков сухой остаток.
Чувствую себя маленькой шестеренкой в большом часовом организме Microsoft. Я уже и забыл как это. Никогда не испытывал никаких неприязненных чувств к MS, всегда считал да и продолжаю считать holy war-ные дела большими глупостями. Но разница с Java миром сильно режет глаз.
.Net это мир чистогана в империи MS. Шаг влево, шаг вправо, прыжок на месте карается тщетным чтением MSDN. Все что нужно среднестатистическому программисту уже сделано в core .NET, если это не сделано – значит это продаётся вот тут и тут за $1000+, если это не продаётся, значит это ересь.
Забавно видеть как такое заботливо прокопанное русло неотвратно приводит ко всё большему и большему vendor-binding. Это как карусель, на которой весело ехать, но тяжело соскочить.
Наверно если бы я был Microsoft я бы тоже себя так вёл, в конце концов мы тут не благотворительностью занимаемся, но не приятно чувствовать как тебя тянут куда-то.
P.S. А сам язык C# – хорош да.