У нас действительно странная проблема с DNS на наших экземплярах EC2. Приложение, которое мы запускаем в некоторых из наших экземпляров, представляет собой службу на основе Java, которая обеспечивает серверную часть для приложения Android. В рамках своей функциональности он отправляет push-уведомления на телефоны через Google API. Для этого он должен сделать SSL-запрос к android.apis.google.com. К сожалению, при запуске этого на наших экземплярах EC2 мы получаем ошибку сертификата, потому что имя хоста не совпадает с именем сертификата:
hostname in certificate didn't match: <android.apis.google.com> != <.gstatic.com> OR <gstatic.com> OR <.gstatic.com>
Мы отследили проблему до разницы в результатах DNS. Когда мы запрашиваем DNS для android.apis.google.com из нашего офиса (где все работает) получаем в ответ:
android.apis.google.com. 300 IN CNAME clients.l.google.com.
clients.l.google.com. 160 IN A 74.125.226.230
clients.l.google.com. 160 IN A 74.125.226.231
clients.l.google.com. 160 IN A 74.125.226.232
clients.l.google.com. 160 IN A 74.125.226.233
clients.l.google.com. 160 IN A 74.125.226.238
clients.l.google.com. 160 IN A 74.125.226.224
clients.l.google.com. 160 IN A 74.125.226.225
clients.l.google.com. 160 IN A 74.125.226.226
clients.l.google.com. 160 IN A 74.125.226.227
clients.l.google.com. 160 IN A 74.125.226.228
clients.l.google.com. 160 IN A 74.125.226.229
Когда мы выполняем тот же запрос с сервера EC2, мы получаем другой набор результатов DNS:
android.apis.google.com. 300 IN CNAME clients.l.google.com.
clients.l.google.com. 300 IN A 72.14.204.138
clients.l.google.com. 300 IN A 72.14.204.100
clients.l.google.com. 300 IN A 72.14.204.101
clients.l.google.com. 300 IN A 72.14.204.102
clients.l.google.com. 300 IN A 72.14.204.113
Есть идеи, почему результаты DNS будут так резко отличаться от EC2? И, что более важно, как мы можем это исправить?
Мы действительно пробовали использовать собственный валидатор имени хоста. По словам наших разработчиков, это позволило продолжить подключение, но проблема в том, что он подключен не к тому серверу, поэтому запрос все равно не выполняется.
У Google очень много IP-адресов, и они будут обслуживать вас с тех IP-адресов, которые географически наиболее близки к тому месту, где, по их мнению, вы находитесь.
Когда я dig
против собственного общедоступного DNS Google на 8.8.8.8
, Я получаю тот же список, что и от EC2:
[] csternal@~: dig @8.8.8.8 android.apis.google.com
; <<>> DiG 9.6-ESV-R4-P3 <<>> @8.8.8.8 android.apis.google.com
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 38592
;; flags: qr rd ra; QUERY: 1, ANSWER: 6, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;android.apis.google.com. IN A
;; ANSWER SECTION:
android.apis.google.com. 300 IN CNAME clients.l.google.com.
clients.l.google.com. 300 IN A 72.14.204.102
clients.l.google.com. 300 IN A 72.14.204.113
clients.l.google.com. 300 IN A 72.14.204.100
clients.l.google.com. 300 IN A 72.14.204.101
clients.l.google.com. 300 IN A 72.14.204.138
;; Query time: 83 msec
;; SERVER: 8.8.8.8#53(8.8.8.8)
;; WHEN: Thu Mar 15 11:38:13 2012
;; MSG SIZE rcvd: 145
Проблема, с которой вы столкнулись, выглядит так: https://stackoverflow.com/questions/6296547/c2dm-ioexception-when-sending-message
Чаще всего для устранения сообщения об ошибке, которое вы получаете, предлагается определить настраиваемую проверку имени хоста. Основная проблема, с которой вы столкнулись, заключается в том, что имя домена, возвращаемое URL-адресом Google Android, является .google.com. К сожалению, это вызывает некоторые проблемы, так как Android SDK находится на android.apis.google.com. JVM не будет проверять эту комбинацию по умолчанию (.sdk.google.com будет приемлемым).
Вот пример того, как вы можете создать свой собственный валидатор имени хоста:
URL url = new URL("https://android.apis.google.com/c2dm/send"); HostnameVerifier hVerifier = new HostnameVerifier() { public boolean verify(String hostname, SSLSession session) { return true; } }; HttpsURLConnection conn = (HttpsURLConnection) url.openConnection(); conn.setHostnameVerifier(hVerifier);
Странный. Все снова заработало - как по волшебству.
Это может быть проблема, исходящая от платформы DNS Amazon EC2 (проблема обновления) или проблема с результатами кеширования, исходящая от вашей «виртуальной формы» или платформы Amazon.