Upload
fwdays
View
967
Download
2
Embed Size (px)
Citation preview
Как modnaKastaтрансформироваласьАлександр Соловьëв, CTO modnaKasta
750 RPS3-6k пользователей на сайте днëм одновременно(по версии GA)120 Gb размер базы~80-100k строк Python'а
2 / 30
Много ли это?Достаточно, чтоб умирать от
нагрузки
3 / 30
Как оно было
4 / 30
Метадатапары
5 / 30
И в них у нас хранится...=# SELECT k.key, k.id, COUNT(p.id)-# FROM product_metadatapair p-# JOIN product_metadatakey k ON p.key_id = k.id-# GROUP BY k.key, k.id-# ORDER BY COUNT(p.id); key | id | count----------+----+---------- Объем | 18 | 26 | 3 | 27 Описание | 17 | 176 Номер | 2 | 443 Pазмер | 1 | 3112 Размер | 16 | 15212192(6 rows)
6 / 30
И наличие...
7 / 30
И корзина!
8 / 30
Problems?22 запроса на 1 размер
9 / 30
Problems?22 запроса на 1 размер
110 запросов на 5 размеров
10 / 30
Problems?22 запроса на 1 размер
110 запросов на 5 размеров
Это исправили кешированием
11 / 30
Problems?22 запроса на 1 размер
110 запросов на 5 размеров
Это исправили кешированием
Которое завязано на корзину, поэтомукешируется для каждого юзера отдельно
12 / 30
А как должно быть?
13 / 30
А еще заказыЗаказ создавался на входе в корзинуPayment'ы создавались при выборе, но никогда неудалялись
Пустых неоформленных заказов в базе миллионыКорзина не синглтон, найти текущую - проблема
14 / 30
Восстановление пароля!commit f2c3eaa1e0747075c005d74094a5391b51498cf6Author: v.ishchenko <[email protected]>Date: Thu Feb 5 17:56:09 2015 +0200
Fix password reset send letter
diff --git a/user/urls.py b/urls.py@@ -166 +166 @@
- url(r'^reset/(?P<confirm>[A-Za-z0-9\-]+)/$',+ url(r'^reset/(?P<confirm>[^/]+)/$',
15 / 30
И остальноеМиграций нетРазмерные сетки картинкамиБаннерная система на KyotoDB/Lua/Python/JSПочтовая очередь на KyotoDB на каждом сервереотдельно
16 / 30
При чëм здесь фронтэнд
17 / 30
При чëм здесь фронтэнд
Чëрнаяпятница
18 / 30
Теперь
19 / 30
Что там у насReactClojureScriptDatascriptJavelin
20 / 30
ReactНу какие собственноальтернативы?
21 / 30
ClojureScriptworth repeatingЛисп
Персистентные структуры данныхФункциональное программированиеКомпилируется в JSМинифицируется в advanced режиме ClosureCompiler
22 / 30
Архитектура
23 / 30
Персистентная база данных в памятиЯзык запросов DatalogФормат хранения: триплетыСсылки, джойны, агрегации
24 / 30
Получить из базы баннеры(d/q db
'[:in $ ?contains-now? :find ?e :where [?e :banner/id] [?e :starts-at ?start] [?e :finishes-at ?finish] [(?contains-now? ?start ?finish)]]
(fn [start finish] (time/within? start finish (time/now))))
25 / 30
Пример компонента
Компонент Аргумент - , рисует баннера для этого местаРеагирует на ячейку Рисует список баннеров
(rum/defc Banners < rum/reactive [id] (let [all-banners (rum/react BANNERS) banners (get all-banners id)] [:div {:class "banners"} (for [banner banners] [:img {:src banner :data-banner-id id}])]))
Bannersid
BANNERS
26 / 30
Серверный рендеринг
- функция, котораяотрисовывает реакт-приложение в строкуПолученные для рендеринга данные отдаются наклиент
(defn handler [req res] (.writeHead res 200 {"Content-Type" "text/html"}) (main/render-to-string (.-url req) (fn [initial content] (.end res (render-template initial content)))))
(def app (.createServer http handler))(.listen app 6000 "0.0.0.0")
render-to-string
27 / 30
Весь рендеринг
возвращаетколичество запросов "в процессе"
(defn render-to-string [url callback] (router/set-route url)
(let [comp (router/Root data/db)] ;; Отрендерить 1 раз, чтоб запустить AJAX-запросы (js/React.renderToString comp)
;; Ждëм завершения запросов (add-watch xhr/current-queries ::render (fn [_ _ _ value] (when (zero? (get-xhr-request-count)) (callback db (js/React.renderToString comp)))))))
get-xhr-request-count
28 / 30
И что, удобно?React же :-)Live reload без потери состоянияLive reload есть и на сервереСтруктурное редактирование это счастье (paredit)Количество кода меньше, чем на JSШаринг кода между сервером и клиентом !Tooling вокруг очень крутой
29 / 30
(map answer(some good? questions))
30 / 30