Балансировщик нагрузки Azure вызывает ошибку 400 «Неверное имя хоста» при обратной передаче - PullRequest
1 голос
/ 05 марта 2012

Попытка перенести веб-приложение для использования в Azure. Приложение прекрасно работает на стандартных IIS. При использовании эмулятора Azure для локального тестирования веб-приложения все обратные передачи приводят к

Неверный запрос - Неверное имя хоста

Ошибка HTTP 400. Неверное имя хоста запроса.

Я в растерянности, где искать, чтобы собрать больше информации. Пока я пробовал:

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

  • Просмотр в окне просмотра событий. Буквально нет журналов для этой проблемы ни в журналах приложений, ни в системных Windows.

  • Проверьте привязки IIS, созданные эмулятором Azure. Я заметил, что существуют привязки, созданные на IP-адресе 127.255.0.0, порту 8081. Если я изменю привязку этого IP-адреса на 127.0.0.1, обратные передачи снова будут работать правильно. Вот почему я считаю, что проблема связана с балансировкой нагрузки: если я обойду балансировщик нагрузки, мы снова в работе. Очевидно, что это не постоянное решение.

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

1 Ответ

2 голосов
/ 05 марта 2012

Я нашел ссылку, которая в значительной степени объясняет все это: http://social.msdn.microsoft.com/Forums/en-AU/windowsazuredevelopment/thread/87c729e8-094c-4578-b9d1-9c8ff7311577.

В приложении только Request.Url использовалось для определения фактической страницы, на которой находится пользователь, и затем оно моглобыть использованы для создания URL-адресов, чтобы направить их в другом месте.Это прекрасно работало только в IIS, потому что для того, кто просматривал веб-приложение со значением http://somedomain.com/page.aspx?var=1, этот параметр был бы установлен в параметре Request.Url.С точки зрения моего локального примера это просто будет http://127.0.0.1:8080/page.aspx?var=1.

В Azure балансировщик нагрузки фактически настроен для прослушивания этого IP-адреса на этом порту.Затем балансировщик нагрузки передает запрос одному из экземпляров, работающих на другом порту.Это приводит к тому, что свойство Request.Url имеет значение http://127.0.0.1:8081/page.aspx?var=1. Это свойство затем использовалось для создания URL-адресов, которые будут использоваться в вызовах Server.Transfer, что приводило к ошибочным запросам, поскольку они должны быть построены на исходном порту 8080, а непорт этого конкретного экземпляра, 8081.

Я углубился в декомпилированный код, пытаясь максимально имитировать свойство Request.Url, но сопоставить его с исходным запросом.Код для Request.Url немного странный:

public Uri Url {
  get {
    if (this._url == (Uri) null && this._wr != null) {
      string s = this.QueryStringText;
      if (!string.IsNullOrEmpty(s))
        s = "?" + HttpEncoder.CollapsePercentUFromStringInternal(s, this.QueryStringEncoding);
      if (AppSettings.UseHostHeaderForRequestUrl) {
        string knownRequestHeader = this._wr.GetKnownRequestHeader(28);
        try {
          if (!string.IsNullOrEmpty(knownRequestHeader))
            this._url = new Uri(this._wr.GetProtocol() + "://" + knownRequestHeader + this.Path + s);
        }
        catch (UriFormatException ex){}
      }
      if (this._url == (Uri) null) {
        string str = this._wr.GetServerName();
        if (str.IndexOf(':') >= 0 && (int) str[0] != 91)
          str = "[" + str + "]";
        this._url = new Uri(this._wr.GetProtocol() + "://" + str + ":" + this._wr.GetLocalPortAsString() + this.Path + s);
      }
    }
    return this._url;
  }
}

Я не могу найти информацию по HttpWorkerRequest.GetKnownRequestHeader(28).MSDN бесполезен.

Возвращает стандартный заголовок HTTP-запроса, соответствующий указанному индексу.

Хорошо.Каковы показатели?Декомпилированный код для этого метода просто возвращает (string)null.Так что на самом деле, я думаю, это ничего не делает.

Во всяком случае.В итоге я заменил свойство следующим:

new Uri( HttpContext.Current.Request.Url.Scheme + "://" + HttpContext.Current.Request.Headers[ "Host" ] + HttpContext.Current.Request.Url.PathAndQuery )

HttpContext.Current.Request.Headers[ "Host" ] возвращает исходный запрос hostname: port.Хост - обязательный заголовок, так что это должно быть хорошо.Надеемся, что использование этого обеспечивает всю согласованность предыдущего поведения, в то же время позволяя веб-приложению функционировать в Azure.

...