Разработка API: Как следует обрабатывать отдельные классы ошибок из асинхронного вызова XMLHTTP? - PullRequest
0 голосов
/ 27 августа 2009

У меня есть устаревшее приложение VB6, которое должно выполнять асинхронные вызовы веб-службы. Веб-сервис предоставляет метод search, позволяющий конечным пользователям запрашивать центральную базу данных и просматривать результаты из приложения. Я использую MSXML2.XMLHTTP для выполнения запросов и написал класс SearchWebService, который инкапсулирует вызов веб-службы и код для асинхронной обработки ответа.

В настоящее время SearchWebService вызывает для вызывающего абонента одно из двух событий: SearchCompleted и SearchFailed. Возникает событие SearchCompleted, которое содержит результаты поиска в параметре для события, если вызов завершается успешно. SearchFailed повышается при обнаружении любого типа отказа, который может быть любым от неправильно отформатированного URL-адреса (это возможно, потому что URL-адрес настраивается пользователем) до низкоуровневых сетевых ошибок, таких как «Хост не найден» , к ошибкам HTTP, таким как внутренние ошибки сервера. Он возвращает строку сообщения об ошибке конечному пользователю (которая извлекается из тела ответа веб-службы, если таковое имеется, или из текста кода состояния HTTP, если ответ не имеет тела, или переводится из кода ошибки сети, если ошибка сети). происходит).

Из-за различных требований безопасности вызывающее приложение не обращается к веб-службе напрямую, а обращается к ней через прокси-веб-сервер, работающий на сайте клиента, который, в свою очередь, обращается к реальной веб-службе через VPN. Однако SearchWebService не знает, что вызывающее приложение обращается к веб-службе через прокси-сервер: ему просто дают URL-адрес и говорят сделать запрос. Наличие прокси является требованием уровня приложения.

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

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

Я думал, что одним из способов справиться с этим было бы, чтобы класс SearchWebService обнаруживал различные типы ошибок и вызывал разные события в каждом случае. Например, вместо одного события SearchFailed у меня могло бы быть событие NetworkError для низкоуровневых сетевых ошибок (которое указывало бы на проблему с доступом к прокси-серверу), событие ConfigurationError для недопустимых свойств в SearchWebService класс (например, передача неправильно отформатированного URL-адреса) и ServiceError для ошибок, которые происходят на удаленном веб-сервере (это означает, что прокси-сервер работает нормально, но удаленный сервер возвратил ошибку).

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

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

Первоначально я сохранил одно событие SearchFailed и просто добавил к событию дополнительный параметр errorCode, но это быстро запуталось, особенно в тех случаях, когда не было логического кода ошибки (например, если VB6 вызывает "настоящую" ошибку, т. Е. Если класс XMLHTTP не зарегистрирован).

1 Ответ

1 голос
/ 27 августа 2009

Я думаю, что некоторые идеи, которые я использовал с исключениями Java, могут применяться здесь.

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

Следовательно, у меня есть небольшое количество конкретных исключений, которые, я думаю, будут соответствовать вашим событиям:

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

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

В случае InvalidRequestException мы могли бы поспорить, предоставив некоторую информацию о проблемах с вводом. Это может быть в строках «Несоответствующие скобки» или «Неизвестный столбец CUTSOMER в таблице ORDER». В случае TransientErrorException это может быть «Прокси-сервер не работает».

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

Так что либо исключение может содержать что-то вроде этого (извините за этот синтаксис Java, но я надеюсь, что идея ясна):

BaseException {
    String ErrorText;     // the error text itself

    // OR if you want to allow for internationaliation

    int ErrorCode;        // my application specific code, corresponds to text held by the UI
    String[] params;      // specific parameters to be substitued in the error text
                          // CUTSOMER and ORDER in my example above


    int SystemErrorCode;    // If you have an underlying error code it goes here


    String SystemErrorText; // any further diagnoistic you might need to give to 
                            // the user so that they can report the problem to the 
                            // help desk.

    // OR instead of the text (this is something I've seen done)

    int SystemErrorTag;     // A unique id for this particular error problem. 
                            // This server systems will label their message in the
                            // server logs. Users just tell the help desk this number
                            // they don't need to read detailed server error text.
* *} Тысяча двадцать-один
...