28.10.2009

Как определить город посетителя (определение адреса по ip)

Все хорошие сайты умеют определять адрес, вернее, город, в котором живет посетитель. И делается это, понятно, по ip-адресу. Только вот кто откуда берет географические привязки ip? Лично я решил использовать сервис IpGeoBase. Он позволяет скачать базу целиком или же использовать xml-сервис. Я предпочел пока второй вариант, чтобы не заморачиваться с ежедневным выкачиванием базы. Понятно, что когда поток посетителей у меня возрастет до небывалых высот, я буду выкачивать базу. А пока у меня это работает очень быстро и выглядит так (код на Питоне 2.6):

#coding=utf-8

def getGeoData(ip):
  """Получить город по ip-адресу (адрес предается как строка).
  Возвращает словарь с элементами-строками city, region, district
  "
""

  import httplib
  import re
  from xml.dom.minidom import parseString

  conn = httplib.HTTPConnection("194.85.91.253:8090")
  conn.request("POST", "/geo/geo.html", \
    "<ipquery><fields><all/></fields><ip-list><ip>" + ip + \
    "</ip></ip-list></ipquery>")
  resp = conn.getresponse()

  data = resp.read()
  conn.close()

  # если ничего не найдено
  if re.search("<message>Not found</message>", data):
    return None

  dom = parseString(data)
  city = dom.documentElement.getElementsByTagName('city')[0]\
    .firstChild.nodeValue
  region = dom.documentElement.getElementsByTagName('region')[0]\
    .firstChild.nodeValue
  district = dom.documentElement.getElementsByTagName('district')[0]\
    .firstChild.nodeValue

  return {'city' : city, 'region' : region, 'district' : district}


Теперь вопрос остальным: кто как справляется с этой задачей?

UPD: иногда сервис неверно определяет адрес по ip, потому что некоторые провайдеры используют общий DHCP для всех регионов, или же информация об адресах еще не собрана. Войдя на IpGeoBase, можно указать свой правильный адрес, если по ip он определился неверно.

15.10.2009

Memcached для Windows и .NET

Вообще, довольно странно размещать memcached на машине с виндой, так как за операционку надо платить. Гораздо дешевле под эти нужды поднимать линуховые тачки. Но, допустим, у вас веб-приложение на ASP.NET или веб-сервис, который хостится под IIS. Кэш вы храните как синглтон в рабочем процессе, у вас отлично реазилованы многопоточные блокировки и т.д. Или даже вы используете какую-нибудь библиотеку для кэширования. Однако, по расписанию регулярно происходит рестарт рабочего процесса, и весь кэш теряется - приходится грузить данные заново.

Еще хуже, если вы включаете для пула приложений режим "веб-сад", т.е. позволяете IIS запускать несколько рабочих процессов для вашего сервиса. Теперь каждый экземпляр вашего сервиса будет делать запросы в базу и складывать все в свой собственный кэш. Вот для таких случаев лучше всего подходит memcached для windows. Этот кэш будет существовать в единственном экземпляре, обслуживать сколько угодно процессов и сбрасываться только при рестарте системы.

Собственно, сам memcached тянуть отсюда (ищите бинарник под свою винду). В архиве будет один exe-шник. Его можно скопировать, например, в C:\Program files\Memcached\ (папку предварительно надо создать). Потом из командной строки запускаем memcached -d install, в результате он регистрирует себя как windows-сервис (службу) и выполняется с правами "локальная система". По умолчанию он слушает на 11211 порту. Осталось только стартануть сервис memcached из консоли управления службами. После перезагрузки он будет запускаться автоматически.

Теперь про клиентскую часть. Под .NET клиентов несколько, я себе поставил этот. Из архива нам нужны только 2 модуля: log4net.dll и собственно Enyim.Caching.dll. В проекте не забудьте указать ссылки на оба.

sample.config содержит фрагменты, которые вы должны вставить в app.config или web.config. Там может быть указано несколько серверов - вам надо оставить только один с адресом 127.0.0.1 и прописать порт 11211. Особое внимание на тэг <memcached enabled="true"> - так работать не будет. Его надо заменить просто на <memcached>.

Все, можно пользоваться. Мануалов к этому клиенту я не нашел, но он должен придерживаться общепринятого стандарта, так что пойдет любая документация по memcached-клиенту. Еще хочется отметить, что все собственные типы данных, которые вы собираетесь класть к кэш, должны быть помечены атрибутом [Serializable] или [DataContract] (это из WCF). В общем, они должны быть сериализуемыми.

Небольшой пример на C#:

// создание клиента очень быстрое,
// так что не обязательно делать его синглтоном

MemcachedClient client = new MemcachedClient();
// сохранить в кэше
client.Store(StoreMode.Set, "MyIntValue", 12345,
    DateTime.Now.AddMinutes(20));
// получить из кэша
int value = client.Get<int>("MyIntValue");
// удалить из кэша
client.Remove("MyIntValue");

05.10.2009

Проблемы с easy_install MySQL-python

Пробовал поставить таким образом MySQL-python, чтобы Django заработал с MySQL, но никаким образом мне это не удавалось. У меня Windows XP и Python 2.6. Уже решил, что буду ставить Python25. Но, помог готовый инсталлятор под винду, собранный добрым человеком - вот ссылка. Качать надо "MySQL-python-1.2.3c1.win32-py2.6.exe" - это последняя версия.

Кстати, 1 октября вышел новый релиз Питона - 2.6.3. Исправлено около ста багов, новых фич не добавлено.