Upload
-
View
104
Download
0
Embed Size (px)
Citation preview
Сервис POI
Петров Андрей / Hotellook
Определение
POI (point of interest) — достопримечательность или другой объект, отмеченный точкой на карте.
Задачи• Показывать расстояние от отеля до
ближайших POI. • Сортировать выдачу по расстоянию
до POI• Объединить несколько источников
данных• Провести нагрузочное тестирование
Источники данных• OSM - полигон• Expedia - перевод• Популярный сервис -
рейтинг• Hotellook -
отобранные пляжи и подъемники
Объединение источников
• Популярный сервис: Sutomorska Plaza• osm: Sutomore• expedia: Sutomore Beach• hotellook: Beach Sutomore
Объединение по имени
1. Sutomore Beach
2. sutomore beach
3. sutomorebeach
4. sutomore
5. + Левинштейн
Объединение источников
В результате получается супер POI, у которой есть:
• Полигон из OSM
• Перевод из Expedia
• Рейтинг из Популярного сервиса
Пути решенияПосчитать все заранее Посчитать во время
поиска+ нет проблем с производительностью
+ поиск нужных отелей среди всех, например пляжных или лыжных
— фоновый процесс обновление данных, за которым нужно следить
— скорость обновления данных
— триггеры при обновлении отелей или пой
+ нет кэша+ быстрое изменение
параметров
— квадратичная сложность— необходимо укладываться
в 5 секунд
Выбор языка• Python3
$ time python3 calc.py
real 0m2.889suser 0m2.743ssys 0m0.055s
• GO$ time
./go_calc
real0m0.274s
user0m0.250s
sys0m0.011s
vs
Минимальная рамка
Рамка для аэропорта
Рамка для пляжей и подъемников
PostGIS
Было:Время: 198,762 мс
select * from poiwhere ST_DWithin(geom, ST_MakeEnvelope(37.903013, 55.550331, 37.298765, 55.891429, 4326)::geography, 100000);
Seq Scan on poi (cost=0.00..28525.54 rows=423 width=776) Filter: (((geom)::geography && '0103000020E610000001000007C073'::geography && _st_expand((geom)::geography, '100000'::double precision)) AND _st_dwithin((geom)::geography, '0103000020E6100C64B40'::geography, '100000'::double precision, true))
PostGIS
Стало:Время: 1,298 мс
select * from poiwhere geom && ST_MakeEnvelope(38.803013, 55.390331, 36.298765, 56.891429, 4326) and category = 'metro_station';
Index Scan using metro_station_gix on poi (cost=0.14..8.16 rows=1 width=776) Index Cond: (geom && '0103000020E6100000010000000F5DF6B14B40'::geometry)
Подсчет расстояния$ time ./pythagorus46291.37379901246
real 0m0.404suser 0m0.367ssys 0m0.015s
$ time ./haversine 46291.36062403893
real 0m2.731suser 0m2.624ssys 0m0.045s
package mainimport "math"
func main() { for i := 0; i < 10000000; i++ { distance(37.735882, 55.359127, 37.637795, 55.771724) }}
func distance(lon1,lat1,lon2,lat2 float64) float64 { rad_per_deg := math.Pi / 180 rm := 6371.0 * 1000.0
lon1 = lon1 * rad_per_deg lon2 = lon2 * rad_per_deg lat1 = lat1 * rad_per_deg lat2 = lat2 * rad_per_deg
x := (lon2 - lon1) * math.Cos(0.5*(lat2+lat1)) y := lat2 - lat1
return rm * math.Sqrt(x*x+y*y)}
Структура сервиса• Запрос: [[18.866293,42.282179],
[18.866323,42.284180], [18.866234,42.283423], [18.866232,42.282133]]
• Ответ: { "pois": [ { "id": 300640, "rating": 6.1, "category": "beach", "name": "Greco", "location": { "lat": 42.283052, "lon": 18.840151 } }], "distance": { "18.866293,42.282179": { "300640": 2113, "303734": 2427, "304982": 1737, "309401": 1714 } }}
1. запрос2. определение рамки3. расширение рамки4. поиск пой в БД5. подсчет расстояния6. фильтрование7. сортировка8. ответ
Нагрузочное тестирование
./vegeta attack -duration 60s -connections 5 -targets piter.json Latencies [mean, 95, max] 2.06s, 3.67s, 4.93s
1
2