Здравствуйте, dimgel, Вы писали: D>А это кстати идея. Зачем "между", если можно отдельным слоем в само приложение. Тут неподалёку про DAL и BL спрашивали — так вот у меня есть и то, и другое, и ответственность DAL — как раз кеши (моя вещь, как хочу — так и называю ). Надо будет чутка расширить их функционал.
Тут главное — зависимости отследить.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[24]: [давненько мы за REST не срались] Paradigm mismatch is unavoidable!
Здравствуйте, Sinclair, Вы писали:
D>>А это кстати идея. Зачем "между", если можно отдельным слоем в само приложение. Тут неподалёку про DAL и BL спрашивали — так вот у меня есть и то, и другое, и ответственность DAL — как раз кеши (моя вещь, как хочу — так и называю ). Надо будет чутка расширить их функционал. S>Тут главное — зависимости отследить.
Вот поэтому я и выношу все кеши в отдельный прокси-слой. А та идейка от IT, на недопонимание которой я в своё время жаловался (≈"я кеширую не entities, а результаты вызовов методов"), похоже по этой же причине и недопонимается.
Re[22]: [давненько мы за REST не срались] Paradigm mismatch is unavoidable!
Здравствуйте, Sinclair, Вы писали:
G>>Делать зарос в базу для проверки каждый раз будет крайне неэффективно. S>Не факт. Во-первых, даже если мы подготовили полный результат, и только теперь убедились, что у клиента такой уже есть, отдать 304 всё ещё лучше с точки зрения трафика. Во-вторых, потенциально запрос, вычисляющий только LastModifiedTimestamp или только ETag может оказаться эффективнее полного запроса. Ну, а главное — альтернативы-то никакой нет. Только если ставить между SQL и кодом приложения какой-то ещё кэш, который поддерживает механизм нотификаций или ещё какой-то метод быстрее выяснить, что некоторый запрос устарел, на основе знаний о привнесённых изменениях.
Я такой подход проверял. Получилось на небольшой нагрузке, пока все данные находятся гарантированно в кеше SQL, работает быстро. А как только память кончается, то получается что на каждый запрос пользователя гарантированно в базу летит как минимум один "тяжелый" запрос, ибо нужно собрать данные из нескольких связанных таблиц. База начинает загибаться при таком подходе, а веб-серверы отдыхать.
Следующая идея была — вычислять дату последнего изменения в момент изменения и хранить в базе. Потом из базы перехало в распределенный кеш, ну и в итоге получится middleware, который к базе не имеет отношения. К нему кстати прикрутили в итоге watchdog, чтобы синхронизировать данные из базы с отметками в кеше. По сути был изобретен поллинг, только через одно место. Но даже поллинг сильно снижал нагрузку по сравнению с первоначальным вариантом. Нотификации должны сократить нагрузку еще сильнее при правильном использовании, так как на одно изменение может прилетать одна нотификация
Re[6]: [давненько мы за REST не срались] Paradigm mismatch is unavoidable!
Здравствуйте, dimgel, Вы писали:
D>Скажи лучше, как тебе такая идейка для отладки RESTful-сервиса: отдавать XML с <?xls-stylesheet?>, чтобы можно было прям настоящее живое API из-под браузера глазками-ручками тестировать.
Можно, но смысла не очень много. Все равно лучше специальный клиент накидать. Я, к примеру, обычно на коленке пишу на дотнете с обычным HttpWebRequest. Дешево и сердито. Можно потом и к автоматичным интеграционным тестам подцепить, и тех разработчиков кто сервисом пользуется пятачком ткнуть (у них любая проблема сразу же означает, что "что то с сервисом не так", хотя в 90% случаев косяки у них).
Re[7]: [давненько мы за REST не срались] Paradigm mismatch is unavoidable!
Здравствуйте, fddima, Вы писали:
F>3-rd party товарищи умудряющтся отвечать NaN в JSON, что никак недопустимо.
JSON != REST. Я, к примеру, предпочитаю по ряду причин старый добрый XML, а JSON появляется только тогда, когда с той стороны в основном JS, да и то не всегда. Ну и есть же тот же WebAPI, который сам отдаст клиенту то, что он хочет.
Re[19]: [давненько мы за REST не срались] Paradigm mismatch is unavoidable!
Здравствуйте, netch80, Вы писали:
N>Но REST в описанном виде рассчитан в том числе и на участие промежуточных HTTP proxy с локальными кэшами (типа знаменитого squid, или nginx frontend). (Прокси не обязан быть публичным, он может быть и внутренним только для целей данного сервиса — но он всё равно может быть.) Предположим, что содержимое ответа /my/contacts не настолько секретно, чтобы не доверять его промежуточным автоматическим участникам. Как ты сделаешь различение, что есть /my/contacts для клиента 1 и /my/contacts для клиента 2? Прокси не в состоянии это различить. Максимум, что ты можешь — сказать ему не кэшировать. Но даже в этом случае прокси имеет право соптимизировать, если идут одновременные запросы на один и тот же URL от разных участников и один из ответов ещё не отдан до конца. Авторизация, согласно RFC 2616 и тому подобным, не влияет на кэширование.
Вопрос. Не так давно где-то краем уха я слышал, что в HTTP 2.0 будет форсировано использование SSL, т.е. это будет всегда https. ХЗ сколько в этом правды, но если у меня весь сайт (как минимум личный кабинет и API) будут под https, все промежуточные прокси пролетают как фанера над парижем, я так понимаю? И как с этим разработчики REST API живут? Не юзают SSL?
(Кроме того, несколько непонятна эта вот ортогональность авторизации и кеширования. Т.е. на концептуальном уровне разумно, но практически — )
Пояснение к первым двум пунткам: REST — это, по сути, HTTP с дополнительными абстракциями. 100% REST'а и его абстракций берутся только и исключительно из HTTP. Если вы не понимаете вышеперечисленного, о каком REST'е идет речь?
3. Richardson Maturity Model. Вам нужен уровень 3. HATEOAS — это адский звиздец, но когда его понимаешь, понимаешь «как мы без этого жили раньше-то?»
Пояснение к пункту 3. REST == Representational State Transfer. Передача состояния представления.
Мы передаем состояние.
Мы передаем состояние представления.
Мы не передаем данные. Мы не передаем объекты. Мы передаем какое-то состояние для какого-то представления этих данных. Как вы представляете эти данные — это ваши личные вопросы. Для того, чтобы различать разные представления (и их версии) у вас есть Content-Type/Accept (см. пункт 2):
В первую репрезентацию можно посылать PATCH (или POST с X-HTTP- Method-Override) только с amount'ами. Во второй — что душе пожелается. Откуда у людей проблема с обновлением сотни элементов за один раз? От непонимания
На правах рекламы:
— https://github.com/klarna/jesse для валидации JSON Schemas
— https://github.com/klarna/katt для тестирования REST-запросов используя старый формат Apiary Blueprints (виден в моих примерах выше)
— и дай бог в течение пары месяцев (полгода-год ) мы выпустим тулзу для внятного дизайна этих самых JSON-схем (на node.js, на радость хипстерам)
Насчет всего остального слушайте Синклера, он говорит правду.
Что-то у меня такое чувство, что "отче наш" это должно быть для разработчиков HTTP-сервера, а прикладному программисту хватит doGet(), doPost(), doOptions(), doPut(), doDelete() из Servlet API.
M>(да, HTTP-заголовки существуют не просто для того, чтобы на них тупо смотреть).
Спасибо, кэп.
Re[20]: [давненько мы за REST не срались] Paradigm mismatch is unavoidable!
Здравствуйте, dimgel, Вы писали:
D>Вопрос. Не так давно где-то краем уха я слышал, что в HTTP 2.0 будет форсировано использование SSL, т.е. это будет всегда https. ХЗ сколько в этом правды,
Во-первых, HTTP/1.1 живее всех живых и сейчас, к слову, находится в состоянии "драфты нового комплекта IETF RFC одобрили и после финального редактирования получат регистрацию":
Юристы могут поискать различия, я, кроме странностей стиля, ничего быстро не накопал, но и не старался.
Во-вторых, так называемый HTTP/2.0 сейчас в состоянии глубокой беты (первая отсылка на proposed standard в конце этого года), со сломами совместимости с прошлыми версиямии шумной дискуссии во всех кругах на тему "а нафига он такой и можно ли им в принципе заменить существующее", и ответ, скорее всего, что заменить он не может. Что может — это дополнить. Например, подняв соединение по 1.1, сделать ему upgrade до SPDY — да, скорее всего будут позволять. Умение в сервере сразу определять входной протокол — наверно, тоже (по первой ссылке это таки обещают).
В-третьих, самому протоколу это глубоко пофиг — там бинарные фреймы по TCP-like каналу. Скорее всего, эти слухи основаны на одной фразе из википедии:
For use within HTTPS, SPDY needs the TLS extension Next Protocol Negotiation (NPN), thus browser and server support depends on the HTTPS library.
ключевое слово тут "если", то есть "for <use within HTTPS>". Если не within HTTPS, то, соответственно, поддержка HTTPS не нужна.
D>(Кроме того, несколько непонятна эта вот ортогональность авторизации и кеширования. Т.е. на концептуальном уровне разумно, но практически — )
Ну вот пример из моего свежего опыта. Клиент обращается "дай мои объекты" по короткому URL типа /my/objects. Он получает редирект на /objects/id=${his_id} и забирает его содержимое. /my/objects у всех может быть разный. А вот /objects/id=${his_id}, если у читающего вообще есть право их получать — одинаковое. Но мы не знаем заранее, кто может такое получать — он сам, непосредственный начальник, главный шеф или какой-то сотрудник внутренней безопасности (который при этом, в отличие от прочих, может не иметь права получать содержимое объектов). Значит, надо писать "Vary: Authorization".
Но если содержимое открытое, то такого ограничения не надо писать. Несмотря на то, что оно может зависеть от конкретного клиента, от авторизации (изначально). Например, иногда есть причины делать, что ресурс доступен по временному секретному URI, но всем, кто его знает.
То есть решать это вообще-то серверу и только ему. Главное — не забыть регулировать.
M>>1. Курить эту диаграмму, учить наизусть и знать, как «Отче Наш»: https://raw.github.com/for-GET/http-decision-diagram/master/httpdd.png (Она намного более полная и вменяемая, чем известная диаграмма Webmachine).
D>Что-то у меня такое чувство, что "отче наш" это должно быть для разработчиков HTTP-сервера, а прикладному программисту хватит doGet(), doPost(), doOptions(), doPut(), doDelete() из Servlet API.
Это только так кажется.
M>>(да, HTTP-заголовки существуют не просто для того, чтобы на них тупо смотреть).
D>Спасибо, кэп.
Вот именно поэтому только doGet и прочими не обойтись. Даже составление и обработка грамотного ETag'а — это уже больше, чем просто doGet()
Здравствуйте, Mamut, Вы писали:
M>Это только так кажется. M>Вот именно поэтому только doGet и прочими не обойтись. Даже составление и обработка грамотного ETag'а — это уже больше, чем просто doGet()
Возможно. Я планирую плотно заняться обдумыванием генератора REST API (с предварительным ковырянием в чужих, и может даже O'Relly придётся дочитать, т.к. пока что не понятно ни черта) не раньше чем через месяц. А одну книжку осилил заранее, чтобы пока что в фоновом режиме хоть что-то утряслось.
M>>Это только так кажется. M>>Вот именно поэтому только doGet и прочими не обойтись. Даже составление и обработка грамотного ETag'а — это уже больше, чем просто doGet()
D>Возможно. Я планирую плотно заняться обдумыванием генератора REST API (с предварительным ковырянием в чужих, и может даже O'Relly придётся дочитать, т.к. пока что не понятно ни черта) не раньше чем через месяц. А одну книжку осилил заранее, чтобы пока что в фоновом режиме хоть что-то утряслось.
Про REST говорят, что он simple, но никак не easy И это, увы, так
D>2. Из процитированного предложения следует одна простая вещь: с помощью REST можно отредактировать запись в базе, но нельзя, к примеру, отправить email. Нельзя сделать ничего такого, что не является чтением/записью данных.
D>3. То есть, если нам надо отправить email, мы либо пуляем RPC поверх HTTP (раз mismatch), либо прикидываемся, что "отправка email" — это типа разновидность записи данных такая (два mismatch). Куда не плюнь — всюду mismatch.
Чем отправка email'а принципиально отличается от записи данных? Ничем Потому что в подавляющем большинстве случаев мы не отправляем email, а складируем его в очередь sendmail'а какого-нибудь.
POST /internal/emails
> Content-Type: application/vnd.mega.spam.email-v1+json
{
"to": ["email1", "email2", "email3"],
"from": "ceo@paipal.com",
"subject": "Claim your prize",
"body": "Claim your prize...",
}
Возможные ответы:
Если обработка прошла сразу
< 201
< Location: /internal/emails/230
Если просто поставили в очередь
< 202
< Location: /internal/emails/230/status
Во втором случае:
-- письмо все еще в очереди
GET /internal/emails/230/status
< 202
< Location: /internal/emails/230/status
-- письмо уже обработано
GET /internal/emails/230/status
< 201
< Location: /internal/emails/230
Пока письмо еще в очереди, попытка его получить:
GET /internal/emails/230
> Accept: application/vnd.mega.spam.email.informational-v1+json
< 404
N>Но REST в описанном виде рассчитан в том числе и на участие промежуточных HTTP proxy с локальными кэшами (типа знаменитого squid, или nginx frontend).
M>>Смотря, что ты имеешь в виду под генератором REST API
D>Понятия не имею. Но успел увидеть краем уха, что такие бывают. Мне надо хоть от чего-то оттолкнуться.
Мы лопатим вручную По-моему, что-то есть для Java, но увы, не знаю
Здравствуйте, Sinclair, Вы писали:
S>Здравствуйте, dimgel, Вы писали: D>>Любопытно и доля истины ощущается. Но ограниченность множества глаголов — объективный факт. (Я ХЗ как ты относишься к типу ресурса "контроллер", мне же он кажется натягиванием презерватива на глобус — отход от концептуально правильного REST-а, пригодного в чистом виде — повторюсь — только для ресурсопомоек, в угоду суровой правде жизни.) S>Спор беспредметен. Во всех предыдущих инкарнациях, REST выигрывал у RPC на его же поле. Я по-прежнему открыт к дискуссии в формате "вот схема RPC API, и по-моему это плохо воспроизводится в REST". В ответ на что я предъявляю схему REST-сервиса, который делает то же самое, плюс решает пару проблем, о которых автор RPC по наивности не подумал. Либо я соглашаюсь, что да, таки в данном случае RPC лучше, и мы наконец-то имеем хоть один пример, где RPC выигрывает.
Тогда не в порядке спора и попыток переубедить. Объясните как реализовать с помощью REST процедуру логона. Ну точнее не реализовать, а какие API (ресурсы должны быть). Типичный сценарий:
1. Клиент начинает сессию (передает имя пользователя, и способ аутентификации).
2. Сервер поднимает плагин, отвечающий за этот способ и отдает ему имя пользователя.
3. Плагин генерит некие данные (challenge), отдает серверу, а он отдает клиенту.
4. Клиент запрашивает у пользователя его секретные данные (пароль, палец и пр), отсылает серверу.
5. Сервер передает эти данные плагину, который может:
a. Сказать, что логон успешен.
b. Сказать, что логон не успешен.
с. Затребовать новые данные.