Comments 32
Вы, ребята, молодцы. И блог у вас классный, и распространяемые приложения очень даже.
По поводу этого геолокатора: я правильно понял, что оно не кеширует результаты и при каждом явном обращении к request.location пытается определить, откуда пользователь?
По поводу этого геолокатора: я правильно понял, что оно не кеширует результаты и при каждом явном обращении к request.location пытается определить, откуда пользователь?
0
Имхо это велосипед, и nginx и апач имеют mod_geoip, которую можно развернуть в памяти. Зачем лазить в БД на каждый запрос? По-моему это бред и ересь.
+1
GEOIP_COUNTRY_CODE and GEOIP_COUNTRY_NAME и все?
0
На каждый запрос никто в базу не лезет, один раз для пользователя, результат геолокации для пользователя кэшируется в куке (уже писал выше). Почему в базе, а не mod_geoip, написано в статье: «потребность в создании своей модели географии, отвечающей задачам бизнес-логики». Мы сделали выбор в пользу удобства создания своих кастомных регионов на основе географии ipgeobase в ущерб скорости и пока не жалеем.
0
Это все также можно сделать стандартным модулем для nginx mod_geo и не лазить в базу, это будет гораздо быстрее.
А минусующие — пусть приводят аргументы.
Мое мнение — даже на каждый первый запрос лазить в базу — очень плохо, когда этого можно избежать.
А минусующие — пусть приводят аргументы.
Мое мнение — даже на каждый первый запрос лазить в базу — очень плохо, когда этого можно избежать.
+2
А как сделать, чтобы mod_geoip работал с базой ipgeobase.ru?
0
wget ipgeobase.ru/files/db/Main/geo_files.tar.gz;tar xf geo_files.tar.gz;cat cidr_optim.txt |awk '{print $3$4$5" "$6";"}'
0
да можно и без mod_geo, сами используем бинарную базу от maxmind — шустро, просто
0
Вы правы в том, что когда можно избежать лезть в базу — лучше не лезть. А ведь может случиться так, что информация понадобится не для редиректа на поддомен, а в логике самого проекта. Простейший пример:
Можно получить эту информацию из nginx? Думаю, что можно. Но костыли, применяемые при этом, едва ли будут менее позорны, чем лишний запрос и красивый код :-)
<p>
Выберите город, {{ request.user }}. Текущее значение – <b>{{ request.location }}</b>
</p>
Можно получить эту информацию из nginx? Думаю, что можно. Но костыли, применяемые при этом, едва ли будут менее позорны, чем лишний запрос и красивый код :-)
0
никаких костелей там нет
proxy_set_header GEOIP_COUNTRY_CODE $geoip_country_code;
fastcgi_param GEOIP_COUNTRY_CODE $geoip_country_code;
+1
То есть Вы считаете, что размазать логику на два слоя — Джанги и фронтенда — это вовсе не костыль, а сделать один дополнительный запрос к БД — восьмой смертный грех? =)
0
Это вовсе не костыль, берем любой типичный виртуальный хостинг, GEOIP_COUNTRY_CODE вы видите в переменных окружения апача, никто на пэхопэ не залезает в базу данных GeoIP.dat. Кроме того, это эффективно работает с несколькими сайтами на сервере (хорошо если сервер ваш и пара сайтов, а если их на сервере 500), каждому отдельному скрипту на каждом отдельном виртуалхосте ненужно лазить ни в каких базы данных, будь они sql, текст или бинарник — все есть в переменных окружения сервера. И так все работает везде уже лет десять как, а то и больше.
+1
Не поймите меня неправильно, я не спорю о том, что nginx — великолепная штука, встроенная нересурсоёмкая геолокация из коробки — это тоже замечательно и правильно.
Но случай с джангой скорее исключение. Во-первых, она сама по себе достаточно прожорлива, поэтому её запускают обычно на ВДС или в облаках. Но не на виртуальных хостингах.
ВО-вторых, как ни крути, работа с нативными питоновскими объектами удобнее, чем две строки, получаемые из внешней среды.
Но случай с джангой скорее исключение. Во-первых, она сама по себе достаточно прожорлива, поэтому её запускают обычно на ВДС или в облаках. Но не на виртуальных хостингах.
ВО-вторых, как ни крути, работа с нативными питоновскими объектами удобнее, чем две строки, получаемые из внешней среды.
-2
Чёрт возьми, а давайте помиримся? :-)
Надо всего лишь предложить ребятам написать бэкенд для получения гео-локации из окружения и тогда мы оба будем правы!
Надо всего лишь предложить ребятам написать бэкенд для получения гео-локации из окружения и тогда мы оба будем правы!
0
Я не ссорился ;)
Это абсолютно не нужно писать, ибо все есть в request.META
Это абсолютно не нужно писать, ибо все есть в request.META
0
Если в приложении вам достаточно получить строку с названием города или страны — то django-geoip вам, конечно же не нужен. Я уверен, что для массы проектов request.META — более чем достаточно. Но это не наш случай и в заметке я объяснил почему.
0
Ну ё-моё :-)
В
Совсем другое дело django-geoip:
Я пару комментариев назад слово «костыли» по отношению к употребил именно с этой позиции: он может передать лишь текстовую строку, в то время как django-geoip оперирует полноценным питоновским объектом.
Для того, чтобы с тем же комфортом работать с geoip'ом инжиникса, придётся писать много кода (как раз те самые обращения к
В
request.META
будет простое текстовое значение типа RU
. Да, его легко вывести в шаблон, но на этом сфера его пользы и заканчивается.Совсем другое дело django-geoip:
{{ request.location }}
это полноценная модель, понимаете? Причём кастомизируемая. Её можно и сохранять, и расширять, и даже внешние ключи на неё вешать. Я пару комментариев назад слово «костыли» по отношению к употребил именно с этой позиции: он может передать лишь текстовую строку, в то время как django-geoip оперирует полноценным питоновским объектом.
Для того, чтобы с тем же комфортом работать с geoip'ом инжиникса, придётся писать много кода (как раз те самые обращения к
request.META
). Ну, или как меня осинило, предложить ребятам сделать поддержку mod_geoip, благо, насколько я понял их код, это делается элементарно с помощью storage.+1
Не совсем, Storage отвечает за то, где хранится результат geoip-поиска: в куках или нигде :)
Не трогать БД в текущей реализации не получится, разве что изменив middleware. Постараюсь в следующей версии подумать над поддержкой mod_geoip.
Не трогать БД в текущей реализации не получится, разве что изменив middleware. Постараюсь в следующей версии подумать над поддержкой mod_geoip.
0
Получать геолокацию из окружения не проблема, а как быть с тем, что нам нужна своя, пользовательская география, которую необходимо редактировать администрации сайта? Она хранится в базе обычно, поэтому там же для удобства их связывания хранятся и данные ipgeobase в нашем решении. Да, это не оптимально по производительности, зато позволяет контролировать всю бизнес-логику прямо в django.
Можно заморочиться и выгружать заранее подготовленные данные со своей географией в формате, который поддерживает nginx, чтобы полностью избавиться от завязки на БД. Это решение мне нравится, но пока что игра не стоит свеч для текущих проектов с их нагрузкой.
Можно заморочиться и выгружать заранее подготовленные данные со своей географией в формате, который поддерживает nginx, чтобы полностью избавиться от завязки на БД. Это решение мне нравится, но пока что игра не стоит свеч для текущих проектов с их нагрузкой.
0
Ну так и нужно хранить пользовательскую географию в модели. А если её внезапно не оказалось, или назначать администратором, или пусть юзер при следующем заходе сам инициализирует геолокацию.
А уж как она выполняться будет — от настроек проекта зависит. Хоть sql-поиском в базе IpGeoBase, хоть напрямую из окружения nginx :-)
А уж как она выполняться будет — от настроек проекта зависит. Хоть sql-поиском в базе IpGeoBase, хоть напрямую из окружения nginx :-)
0
Ну опустим тот факт, что SQL решение будет работать значительно медленнее, чем решения с бинарными базами.
Но зачем для хранения IP использовать BIGINT? Чтобы удвоить размер таблицы и индексов? Аналогично INT для городов и регионов, да даже в GeoIP с кучей дубликатов получается около 140 тысяч городов, регионов на порядок меньше.
Но зачем для хранения IP использовать BIGINT? Чтобы удвоить размер таблицы и индексов? Аналогично INT для городов и регионов, да даже в GeoIP с кучей дубликатов получается около 140 тысяч городов, регионов на порядок меньше.
+2
Плюс к этому db_index на полях start_ip и end_ip создаст два отдельных индекса, а при поиске по таблице будет использоваться один. Опять же получаем таблицу большего размера, чем необходимо.
+1
Вы правы, unsigned int тут хватило бы. Можно также уменьшить размер первичных ключей, бесспорно. Но зачем мелочиться, если вам действительно нужна производительность в первую очередь — не надо использовать SQL-решение :) У нас trade-off производительность меняем на удобство поддержки кастомной географии.
0
Ну пусть география у Вас кастомная, но IP то у Вас больше 4 байт не бывают (для IPv6 всё равно BIGINT не подходит)?
К примеру, у Вас сейчас один диапазон в таблице занимает 31 байт, если туда загнать базу GeoIP, то получим около 3,5 млн. диапазонов. Я протестил на базе GeoIP, получилось 106 МБ необходимых только для данных, и еще 158 МБ на индексы, т.е. только для одной таблицы с диапазонами вам понадобится 264 МБ. При том, что бинарная база с теми же данными GeoIP весит 25 МБ, и работает значительно быстрее. Приведя в порядок типы данных таблица похудеет на 85 МБ, замечу, что при этом вы абсолютно ничего не теряете. Если же сделать грамотно, то можно в MySQL добиться где-то 40-50 МБ.
P.S. я надеюсь Вы хоть не ищите диапазон с помощью запроса типа «ip» BETWEEN start_ip AND end_ip?
К примеру, у Вас сейчас один диапазон в таблице занимает 31 байт, если туда загнать базу GeoIP, то получим около 3,5 млн. диапазонов. Я протестил на базе GeoIP, получилось 106 МБ необходимых только для данных, и еще 158 МБ на индексы, т.е. только для одной таблицы с диапазонами вам понадобится 264 МБ. При том, что бинарная база с теми же данными GeoIP весит 25 МБ, и работает значительно быстрее. Приведя в порядок типы данных таблица похудеет на 85 МБ, замечу, что при этом вы абсолютно ничего не теряете. Если же сделать грамотно, то можно в MySQL добиться где-то 40-50 МБ.
P.S. я надеюсь Вы хоть не ищите диапазон с помощью запроса типа «ip» BETWEEN start_ip AND end_ip?
+1
Sign up to leave a comment.
GeoIP и Django