SlideShare a Scribd company logo
1 of 297
Download to read offline
如何在有限資源下實現十年的後端服務演進
Kewang, Funliday
Kewang
●
王慕羣 Kewang
●
JavaScript / Java
●
PostgreSQL / MongoDB / Elasticsearch / HBase
●
Git / DevOps
●
熱愛開源
Linkedin
Linkedin kewangtw
kewangtw
SlideShare
SlideShare kewang
kewang
Gmail
Gmail cpckewang
cpckewang
Facebook
Facebook Kewang 的資訊進化論
Kewang 的資訊進化論
devopsday taipei
devopsday taipei '17
'17
hadoopcon
hadoopcon '14 '15
'14 '15
jcconf
jcconf '16 '17 '18
'16 '17 '18
GitHub
GitHub kewang
kewang
Funliday
Funliday kewang
kewang
modernweb
modernweb '18 '19 '20 '21
'18 '19 '20 '21
coscup
coscup '20 '21
'20 '21
mopcon
mopcon '14 '20 '22
'14 '20 '22
4
時間軸
5
時間軸
6
時間軸
●
從 Parse.com 停止服務開始
7
時間軸
●
從 Parse.com 停止服務開始
●
因為 Google Maps API 開始收費
8
時間軸
●
從 Parse.com 停止服務開始
●
因為 Google Maps API 開始收費
●
全世界的災難 COVID-19
9
開始
10
在我之前 (2014/9~2018/8)
11
在我之前 (2014/9~2018/8)
●
Funliday 小有一點點名氣
12
在我之前 (2014/9~2018/8)
●
Funliday 小有一點點名氣
●
剛募到天使輪資金
13
在我之前 (2014/9~2018/8)
●
Funliday 小有一點點名氣
●
剛募到天使輪資金
●
後端從 Parse.com 轉到 heroku+MongoDB
14
在我之前 (2014/9~2018/8)
●
Funliday 小有一點點名氣
●
剛募到天使輪資金
●
後端從 Parse.com 轉到 heroku+MongoDB
●
Google Maps API 開始收費
15
在我之前 (2014/9~2018/8)
●
Funliday 小有一點點名氣
●
剛募到天使輪資金
●
後端從 Parse.com 轉到 heroku+MongoDB
●
Google Maps API 開始收費
●
Web,Android 殘破不堪
16
從開發景點資料庫開始
17
從開發景點資料庫開始
( 一條龍 )
18
從開發景點資料庫開始 - 背景 (2018/9)
19
從開發景點資料庫開始 - 背景 (2018/9)
●
Google Maps API 開始收費
20
從開發景點資料庫開始 - 背景 (2018/9)
●
Google Maps API 開始收費
– 以 Funliday 的使用方式,每個月要幾十萬台幣
21
從開發景點資料庫開始 - 背景 (2018/9)
●
Google Maps API 開始收費
– 以 Funliday 的使用方式,每個月要幾十萬台幣
– 我的第一個專案就是解耦 Google Maps API
22
從開發景點資料庫開始 - 團隊 (1*2+0.5*2)
●
iOS 、 Web 、 Backend 、找錢、會計: 1
●
Android : 0.5
●
Design : 0.5
●
景點資料庫: 1 一個在日本 part time
一個還有正職工作
23
從開發景點資料庫開始 - 實作
24
從開發景點資料庫開始 - 實作
●
OpenStreetMap :景點資料庫基礎
25
從開發景點資料庫開始 - 實作
●
OpenStreetMap :景點資料庫基礎
●
PostgreSQL :關聯資料庫基礎
26
從開發景點資料庫開始 - 實作
●
OpenStreetMap :景點資料庫基礎
●
PostgreSQL :關聯資料庫基礎
●
PostGIS : GIS 新手入門
27
從開發景點資料庫開始 - 實作
●
OpenStreetMap :景點資料庫基礎
●
PostgreSQL :關聯資料庫基礎
●
PostGIS : GIS 新手入門
●
Elasticsearch :全文搜尋資料庫
28
從開發景點資料庫開始 - 實作
●
OpenStreetMap :景點資料庫基礎
●
PostgreSQL :關聯資料庫基礎
●
PostGIS : GIS 新手入門
●
Elasticsearch :全文搜尋資料庫
●
Redis : Sorted Set 實作 autocomplete
29
Elasticsearch - function score 自訂評分函數
30
Elasticsearch - function score 自訂評分函數
31
Elasticsearch - function score 自訂評分函數
32
Redis - Sorted Set 實作 autocomplete
33
Redis - Sorted Set 實作 autocomplete
34
Redis - Sorted Set 實作 autocomplete
用 x00 區分是否為結果
35
Redis - Sorted Set 實作 autocomplete
用 x00 區分是否為結果
36
從開發景點資料庫開始
37
從開發景點資料庫開始
( 有 team 的話 ...)
38
有 team 的話 ...
●
OpenStreetMap+PostgreSQL+PostGIS : 1
●
Elasticsearch : 1
●
Redis : 1
39
接手後端開發並重構
40
接手後端開發並重構
( 一條龍 )
41
接手後端開發並重構 - 背景 (2019/9)
42
接手後端開發並重構 - 背景 (2019/9)
●
找錢太花心力,要儘量減少開發工作
43
接手後端開發並重構 - 背景 (2019/9)
●
找錢太花心力,要儘量減少開發工作
●
功能愈來愈多,技術債造成擴展困難
44
接手後端開發並重構 - 團隊 (1*4)
●
iOS 、 Web 、找錢、會計: 1
●
Android : 1
●
Design : 1
●
Backend : 1 都回歸團隊,還缺 Web
45
接手後端開發並重構 - 實作
46
接手後端開發並重構 - 實作
●
Callback hell
47
接手後端開發並重構 - 實作
●
Callback hell
– Node.js 早期都是使用 callback 為主
48
接手後端開發並重構 - 實作
●
Callback hell
– Node.js 早期都是使用 callback 為主
– 持續調整為 Promise (async/await)
49
Callback hell
50
Callback hell
51
Callback hell
亂!有 thenable 又有 async/await
52
接手後端開發並重構 - 實作
53
接手後端開發並重構 - 實作
●
MongoDB schema 偏亂
54
接手後端開發並重構 - 實作
●
MongoDB schema 偏亂
– schema 一開始沒有通盤規劃
55
接手後端開發並重構 - 實作
●
MongoDB schema 偏亂
– schema 一開始沒有通盤規劃
– RDBMS 無法套用在 NoSQL 上
56
接手後端開發並重構 - 實作
●
MongoDB schema 偏亂
– schema 一開始沒有通盤規劃
– RDBMS 無法套用在 NoSQL 上
– 有 NoSQL 基礎,容易理解 schema 設計
57
MongoDB schema 偏亂
58
MongoDB schema 偏亂
59
MongoDB schema 偏亂
測試資料夾裡面有許多景點
60
MongoDB schema 偏亂 - RDBMS 的做法
61
MongoDB schema 偏亂 - RDBMS 的做法
62
MongoDB schema 偏亂 - RDBMS 的做法
POI collection
63
MongoDB schema 偏亂 - RDBMS 的做法
64
MongoDB schema 偏亂 - RDBMS 的做法
65
MongoDB schema 偏亂 - RDBMS 的做法
POI folder collection
66
MongoDB schema 偏亂 - NoSQL 的做法
67
MongoDB schema 偏亂 - NoSQL 的做法
68
MongoDB schema 偏亂 - NoSQL 的做法
要怎麼顯示,就怎麼存
69
接手後端開發並重構 - 實作
70
接手後端開發並重構 - 實作
●
API 沒有 RESTful
71
接手後端開發並重構 - 實作
●
API 沒有 RESTful
– API 全部都是 POST /actionName
72
接手後端開發並重構 - 實作
●
API 沒有 RESTful
– API 全部都是 POST /actionName
– 資料塞在 Request body
73
接手後端開發並重構 - 實作
●
API 沒有 RESTful
– API 全部都是 POST /actionName
– 資料塞在 Request body
●
持續正規化 body 、 header
74
接手後端開發並重構 - 實作
●
API 沒有 RESTful
– API 全部都是 POST /actionName
– 資料塞在 Request body
●
持續正規化 body 、 header 沒有 HTTP cache
75
API 沒有 RESTful
76
API 沒有 RESTful
77
API 沒有 RESTful
parseMemberObjectId, token 要統一放到 header
78
接手後端開發並重構 - 實作
79
接手後端開發並重構 - 實作
●
擴展 Express.js 函式
80
接手後端開發並重構 - 實作
●
擴展 Express.js 函式
– req.funliday
81
接手後端開發並重構 - 實作
●
擴展 Express.js 函式
– req.funliday
– res.success
82
擴展 Express.js 函式 - req.funliday
83
擴展 Express.js 函式 - req.funliday
84
擴展 Express.js 函式 - req.funliday
自訂 header 放到 x-funliday 裡面
85
擴展 Express.js 函式 - req.funliday
86
擴展 Express.js 函式 - req.funliday
87
擴展 Express.js 函式 - req.funliday
取出 x-funliday-header
88
擴展 Express.js 函式 - req.funliday
89
擴展 Express.js 函式 - req.funliday
90
擴展 Express.js 函式 - req.funliday
與 semver 實際運用
91
擴展 Express.js 函式 - res.success
92
擴展 Express.js 函式 - res.success
93
擴展 Express.js 函式 - res.success
可支援 object 以及 array
94
擴展 Express.js 函式 - res.success
95
擴展 Express.js 函式 - res.success
96
擴展 Express.js 函式 - res.success
資料庫多回傳一筆資料,可以判斷是否還有下一頁
97
接手後端開發並重構
98
接手後端開發並重構
( 有 team 的話 ...)
99
有 team 的話 ...
●
MongoDB schema 偏亂: 1
●
API 沒有 RESTful+ 擴展 Express.js 函式: 1
100
老大哥正在看著你
101
老大哥正在看著你
( 一條龍 )
102
老大哥正在看著你 - 背景 (2019/9)
103
老大哥正在看著你 - 背景 (2019/9)
●
為了記錄 log
104
老大哥正在看著你 - 背景 (2019/9)
●
為了記錄 log
●
機器一直死
105
老大哥正在看著你 - 團隊 (1*4)
●
iOS 、 Web 、找錢、會計: 1
●
Android : 1
●
Design : 1
●
Backend : 1 團隊沒有變化,還在找 Web
106
老大哥正在看著你 - 實作
107
老大哥正在看著你 - 實作
●
加上 log
108
老大哥正在看著你 - 實作
●
加上 log
– 原本使用 heroku 合作的 papertrail
109
老大哥正在看著你 - 實作
●
加上 log
– 原本使用 heroku 合作的 papertrail
– 因為有裝 Elasticsearch ,所以整合進 ELK stack
110
老大哥正在看著你 - 實作
●
加上 log
– 原本使用 heroku 合作的 papertrail
– 因為有裝 Elasticsearch ,所以整合進 ELK stack
一開始為了省事,之後為了省錢
111
老大哥正在看著你 - 實作
112
老大哥正在看著你 - 實作
●
加上 APM
113
老大哥正在看著你 - 實作
●
加上 APM
– Application Performance Monitoring
114
老大哥正在看著你 - 實作
●
加上 APM
– Application Performance Monitoring
– 也是使用 heroku 合作的 New Relic
115
老大哥正在看著你 - 實作
●
加上 APM
– Application Performance Monitoring
– 也是使用 heroku 合作的 New Relic
– 原本要改用 Elastic APM ,但安裝失敗
116
老大哥正在看著你 - 實作
●
加上 APM
– Application Performance Monitoring
– 也是使用 heroku 合作的 New Relic
– 原本要改用 Elastic APM ,但安裝失敗
一開始為了省事,之後為了省錢
117
老大哥正在看著你 - 實作
118
老大哥正在看著你 - 實作
●
加上 status page
119
老大哥正在看著你 - 實作
●
加上 status page
– 避免被動得知系統發生錯誤
120
老大哥正在看著你 - 實作
●
加上 status page
– 避免被動得知系統發生錯誤
– 直到 2023/6 才加上去
121
老大哥正在看著你 - 實作
●
加上 status page
– 避免被動得知系統發生錯誤
– 直到 2023/6 才加上去
– 使用 Uptime Kuma
122
加上 status page
123
加上 status page
124
老大哥正在看著你
125
老大哥正在看著你
( 有 team 的話 ...)
126
有 team 的話 ...
127
有 team 的話 ...
●
全部交給 SRE !
128
持續加入各種功能
129
持續加入各種功能
( 一條龍 )
130
持續加入各種功能 - 背景 (2019/6)
131
持續加入各種功能 - 背景 (2019/6)
●
Funliday 不可能只有景點跟行程
132
持續加入各種功能 - 背景 (2019/6)
●
Funliday 不可能只有景點跟行程
●
開始讓使用者寫遊記 (2014 就有的想法 )
133
持續加入各種功能 - 背景 (2019/6)
●
Funliday 不可能只有景點跟行程
●
開始讓使用者寫遊記 (2014 就有的想法 )
●
這時,還沒想到如何賺錢
134
持續加入各種功能 - 團隊 (1*5)
●
iOS 、找錢、會計: 1
●
Web : 1
●
Android : 1
●
Design : 1
●
Backend : 1
新功能上線,需要 Web 實作
135
持續加入各種功能 - 實作
136
持續加入各種功能 - 實作
●
寫遊記
137
持續加入各種功能 - 實作
●
寫遊記
– 上傳圖片: S3+CloudFront
138
持續加入各種功能 - 實作
●
寫遊記
– 上傳圖片: S3+CloudFront
– 縮圖功能
139
持續加入各種功能 - 實作
●
寫遊記
– 上傳圖片: S3+CloudFront
– 縮圖功能
●
第一版使用 Lambda (Python+thumbor)
140
持續加入各種功能 - 實作
●
寫遊記
– 上傳圖片: S3+CloudFront
– 縮圖功能
●
第一版使用 Lambda (Python+thumbor)
●
第二版自製 image service (Node.js+sharp)
141
持續加入各種功能 - 實作
●
寫遊記
– 上傳圖片: S3+CloudFront
– 縮圖功能
●
第一版使用 Lambda (Python+thumbor)
●
第二版自製 image service (Node.js+sharp)
●
第三版新增 Blurhash
142
第一版使用 Lambda
143
第一版使用 Lambda
●
AWS labs 的解決方案 serverless-image-handler
144
第一版使用 Lambda
●
AWS labs 的解決方案 serverless-image-handler
●
payload 最大 6MB
145
第一版使用 Lambda
●
AWS labs 的解決方案 serverless-image-handler
●
payload 最大 6MB
●
但沒人會寫 python ,無法維護
146
第三版新增 Blurhash
147
第三版新增 Blurhash
148
第三版新增 Blurhash
149
第三版新增 Blurhash
150
第三版新增 Blurhash
qeFsDNIo8_x]%2WARiWXpf%MngkXRkj[jYt7?
wWVj]flV@ogt7V@bxt7t8ofV@kWWBj[ozkCxva
dWDogjYWBt8j[a~jZofoMRjoz
151
第三版新增 Blurhash
qeFsDNIo8_x]%2WARiWXpf%MngkXRkj[jYt7?
wWVj]flV@ogt7V@bxt7t8ofV@kWWBj[ozkCxva
dWDogjYWBt8j[a~jZofoMRjoz
資料量小,與其他解決方案比會少一次 request
152
持續加入各種功能 - 實作
153
持續加入各種功能 - 實作
●
定義資料結構一致的列表
154
持續加入各種功能 - 實作
●
定義資料結構一致的列表
– 至少要跟設計師討論
155
持續加入各種功能 - 實作
●
定義資料結構一致的列表
– 至少要跟設計師討論
– 統一遊記、行程、使用者、景點、商品列表
156
定義資料結構一致的列表
157
定義資料結構一致的列表
158
定義資料結構一致的列表
159
定義資料結構一致的列表
160
定義資料結構一致的列表
封面 + 標題 + 座標
161
定義資料結構一致的列表
162
定義資料結構一致的列表
163
定義資料結構一致的列表
164
定義資料結構一致的列表
用 type 決定顯示的方式,用 action 決定點擊的行為
165
持續加入各種功能
166
持續加入各種功能
( 有 team 的話 ...)
167
有 team 的話 ...
●
寫遊記: 2
●
定義資料結構一致的列表: 1
168
總算想到 SEO
169
總算想到 SEO
( 一條龍 )
170
總算想到 SEO - 背景 (2019/10)
171
總算想到 SEO - 背景 (2019/10)
●
Funliday 一開始只有 App
172
總算想到 SEO - 背景 (2019/10)
●
Funliday 一開始只有 App
●
要分享給一般使用者,做了 Web
173
總算想到 SEO - 背景 (2019/10)
●
Funliday 一開始只有 App
●
要分享給一般使用者,做了 Web
●
Web 開發使用 React
174
總算想到 SEO - 背景 (2019/10)
●
Funliday 一開始只有 App
●
要分享給一般使用者,做了 Web
●
Web 開發使用 React
●
沒有使用 create-react-app
175
總算想到 SEO - 背景 (2019/10)
●
Funliday 一開始只有 App
●
要分享給一般使用者,做了 Web
●
Web 開發使用 React
●
沒有使用 create-react-app
●
開發模式為前後端分離
176
總算想到 SEO - 團隊 (1*5)
●
iOS 、找錢、會計: 1
●
Web : 1
●
Android : 1
●
Design 、找錢: 1
●
Backend : 1
黑暗時期,連設計也要出來找錢
177
API 取得 metadata
178
API 取得 metadata
179
API 取得 metadata
180
API 取得 metadata
前後端分離的極致,很奇怪的模式
181
自建 prerender
182
自建 prerender
183
自建 prerender
自己用 puppeteer 開發的 prerender
184
自建 prerender
185
自建 prerender
186
自建 prerender
透過 Nginx 轉導 crawler 到 prerender
187
重要 route 改從 DB
188
重要 route 改從 DB
189
重要 route 改從 DB
190
重要 route 改從 DB
開始朝向 SSR 前進
191
新 route 改成 SSR
192
新 route 改成 SSR
193
新 route 改成 SSR
純 SSR ,需要不排斥寫後端的前端人
194
總算想到 SEO
195
總算想到 SEO
( 有 team 的話 ...)
196
有 team 的話 ...
●
重要 route 改從 DB : 2
●
新 route 改成 SSR : 2
197
開始導入電商
198
開始導入電商
( 一條龍 )
199
開始導入電商 - 背景 (2020/9)
200
開始導入電商 - 背景 (2020/9)
●
COVID-19 無法出國,報復式國旅
201
開始導入電商 - 背景 (2020/9)
●
COVID-19 無法出國,報復式國旅
●
除了流量,也要開始注意營收
202
開始導入電商 - 名詞解釋:分銷
203
開始導入電商 - 名詞解釋:分銷
●
在 Funliday 找商品
204
開始導入電商 - 名詞解釋:分銷
●
在 Funliday 找商品
●
在 Funliday 看商品細節
205
開始導入電商 - 名詞解釋:分銷
●
在 Funliday 找商品
●
在 Funliday 看商品細節
●
在 Funliday 結帳
206
開始導入電商 - 名詞解釋:分銷
●
在 Funliday 找商品
●
在 Funliday 看商品細節
●
在 Funliday 結帳
●
利潤高
207
開始導入電商 - 名詞解釋:分銷
●
在 Funliday 找商品
●
在 Funliday 看商品細節
●
在 Funliday 結帳
●
利潤高
●
各種意義上的開發成本高
208
開始導入電商 - 團隊 (1*6)
●
iOS 、找錢、會計: 1
●
Web : 1
●
Android : 1
●
Design 、找錢、營運: 1
●
Business Development : 1 ( 日本人 )
●
Backend : 1
設計開始扛營運
有了一位日本 BD
209
開始導入電商 - 分銷實作
210
開始導入電商 - 分銷實作
●
一個行程:很多景點組成
211
開始導入電商 - 分銷實作
●
一個行程:很多景點組成
●
一個遊記:一個行程 + 很多圖片
212
開始導入電商 - 分銷實作
●
一個行程:很多景點組成
●
一個遊記:一個行程 + 很多圖片
●
一個商品:一個遊記 + 可販賣
213
開始導入電商 - 分銷實作困難點
214
開始導入電商 - 分銷實作困難點
●
資料庫交易 (transaction)
215
開始導入電商 - 分銷實作困難點
●
資料庫交易 (transaction)
– 避免超賣
216
開始導入電商 - 分銷實作困難點
●
資料庫交易 (transaction)
– 避免超賣
●
租車金額試算 (estimate)
217
開始導入電商 - 分銷實作困難點
●
資料庫交易 (transaction)
– 避免超賣
●
租車金額試算 (estimate)
– 各家供應商算法不同
218
開始導入電商 - 分銷實作困難點
●
資料庫交易 (transaction)
– 避免超賣
●
租車金額試算 (estimate)
– 各家供應商算法不同
– 平日假日算法不同
219
開始導入電商 - 分銷實作困難點
●
資料庫交易 (transaction)
– 避免超賣
●
租車金額試算 (estimate)
– 各家供應商算法不同
– 平日假日算法不同
– 連假算法不同
220
開始導入電商 - 分銷實作困難點
●
資料庫交易 (transaction)
– 避免超賣
●
租車金額試算 (estimate)
– 各家供應商算法不同
– 平日假日算法不同
– 連假算法不同
– 連續租 n 日算法不同
221
開始導入電商 - 分銷實作困難點
●
資料庫交易 (transaction)
– 避免超賣
●
租車金額試算 (estimate)
– 各家供應商算法不同
– 平日假日算法不同
– 連假算法不同
– 連續租 n 日算法不同
– ... 等
222
開始導入電商 - 分銷營運困難點
223
開始導入電商 - 分銷營運困難點
●
客服成本超高
224
開始導入電商 - 分銷營運困難點
●
客服成本超高
– 人工出票
225
開始導入電商 - 分銷營運困難點
●
客服成本超高
– 人工出票
– 所有商品的 FAQ 都要完全了解
226
開始導入電商 - 分銷營運困難點
●
客服成本超高
– 人工出票
– 所有商品的 FAQ 都要完全了解
– ... 等
227
開始導入電商 - 分銷營運困難點
228
開始導入電商 - 分銷營運困難點
229
開始導入電商 - 分銷營運困難點
230
開始導入電商 - 分銷營運困難點
231
開始導入電商 - 分銷營運困難點
●
但景點商家不知道
232
開始導入電商 - 分銷營運困難點
●
但景點商家不知道
– QR code 不同
233
開始導入電商 - 分銷營運困難點
●
但景點商家不知道
– QR code 不同
– 現場退票
234
開始導入電商 - 分銷營運困難點
●
但景點商家不知道
– QR code 不同
– 現場退票
– ... 等
235
開始導入電商 - 分銷營運困難點
236
開始導入電商 - 分銷營運困難點
●
但 Funliday 不知道
237
開始導入電商 - 分銷營運困難點
●
但 Funliday 不知道
– 供應商商品已下架
238
開始導入電商 - 分銷營運困難點
●
但 Funliday 不知道
– 供應商商品已下架
– 供應商改價格
239
開始導入電商 - 分銷營運困難點
●
但 Funliday 不知道
– 供應商商品已下架
– 供應商改價格
– ... 等
240
開始導入電商 - 分銷營運困難點
241
開始導入電商 - 分銷營運困難點
●
票券及一日遊有無限組合,上架困難,舉例:
242
開始導入電商 - 分銷營運困難點
●
票券及一日遊有無限組合,上架困難,舉例:
– 平日 299 元、假日 399 元
243
開始導入電商 - 分銷營運困難點
●
票券及一日遊有無限組合,上架困難,舉例:
– 平日 299 元、假日 399 元
– 大人票 299 元、小孩票 199 元
244
開始導入電商 - 分銷營運困難點
●
票券及一日遊有無限組合,上架困難,舉例:
– 平日 299 元、假日 399 元
– 大人票 299 元、小孩票 199 元
– 一個小孩一定要配一個大人
245
開始導入電商 - 分銷營運困難點
●
票券及一日遊有無限組合,上架困難,舉例:
– 平日 299 元、假日 399 元
– 大人票 299 元、小孩票 199 元
– 一個小孩一定要配一個大人
– 七八月第一週假日特價 99 元
246
開始導入電商 - 分銷營運困難點
●
票券及一日遊有無限組合,上架困難,舉例:
– 平日 299 元、假日 399 元
– 大人票 299 元、小孩票 199 元
– 一個小孩一定要配一個大人
– 七八月第一週假日特價 99 元
– ... 等
247
開始導入電商 - 分銷營運困難點
248
開始導入電商 - 分銷營運困難點
249
開始導入電商 - 分銷營運困難點
250
開始導入電商 - 分銷營運困難點
251
開始導入電商 - 分銷營運困難點
252
開始導入電商 - 分銷營運困難點
●
業務開發困難
253
開始導入電商 - 分銷營運困難點
●
業務開發困難
– 店家主動聯絡希望上架他們商品,但利潤低
254
開始導入電商 - 分銷營運困難點
●
業務開發困難
– 店家主動聯絡希望上架他們商品,但利潤低
– 店家都已在雙 K 上架,不想在 Funliday 上架
255
開始導入電商 - 分銷營運困難點
●
業務開發困難
– 店家主動聯絡希望上架他們商品,但利潤低
– 店家都已在雙 K 上架,不想在 Funliday 上架
– 沒有專職台灣業務開發夥伴
256
開始導入電商 - 分銷營運困難點
●
業務開發困難
– 店家主動聯絡希望上架他們商品,但利潤低
– 店家都已在雙 K 上架,不想在 Funliday 上架
– 沒有專職台灣業務開發夥伴
– ... 等
257
開始導入電商
258
開始導入電商
( 有 team 的話 ...)
259
有 team 的話 ...
●
專門客服: 2
●
業務開發: 2
260
導購真香
261
導購真香 - 名詞解釋
262
導購真香 - 名詞解釋
●
在 Funliday 找商品
263
導購真香 - 名詞解釋
●
在 Funliday 找商品
●
在 OTA 看商品細節
264
導購真香 - 名詞解釋
●
在 Funliday 找商品
●
在 OTA 看商品細節
●
在 OTA 結帳
265
導購真香 - 名詞解釋
●
在 Funliday 找商品
●
在 OTA 看商品細節
●
在 OTA 結帳
●
利潤低
266
導購真香 - 名詞解釋
●
在 Funliday 找商品
●
在 OTA 看商品細節
●
在 OTA 結帳
●
利潤低
●
各種意義上的開發成本低
267
導購真香 - 名詞解釋
●
在 Funliday 找商品
●
在 OTA 看商品細節
●
在 OTA 結帳
●
利潤低
●
各種意義上的開發成本低
●
客服成本超低
268
導購真香 - 名詞解釋
●
在 Funliday 找商品
●
在 OTA 看商品細節
●
在 OTA 結帳
●
利潤低
●
各種意義上的開發成本低
●
客服成本超低
Online Travel Agency :線上旅行社
269
導購真香 - 背景 (2023/6)
270
導購真香 - 背景 (2023/6)
●
分銷太困難,引進導購合作
271
導購真香 - 背景 (2023/6)
●
分銷太困難,引進導購合作
●
供應商先搞定雙 K 就好
272
導購真香 - 背景 (2023/6)
●
分銷太困難,引進導購合作
●
供應商先搞定雙 K 就好
●
現有系統可直接支援
273
導購真香 - 團隊 (1*8)
●
iOS 、找錢、會計: 1
●
Web : 1( 香港人 )
●
Android : 1
●
Design 、營運: 1
●
Business Development : 1 ( 日本人 )
●
Marketing : 1
●
Backend : 2
設計可以專心在營運上面
團隊愈來愈多元
多了一位行銷和後端
274
導購真香 - 實作
275
導購真香 - 實作
●
後端不需太多調整
276
導購真香 - 實作
●
後端不需太多調整
●
前端有依照原規格實作,少許調整就可上線
277
導購真香 - 實作
278
導購真香 - 實作
279
導購真香 - 實作
導購轉址頁
280
導購真香 - 實作
281
導購真香 - 實作
282
回顧一下
283
回顧一下
284
回顧一下
285
Conclusion
286
永遠迎接更多的困難
287
永遠迎接更多的困難
●
前端開發很奔放
288
永遠迎接更多的困難
●
前端開發很奔放
– 為了前端孤兒,後端要支援舊前端
289
永遠迎接更多的困難
●
前端開發很奔放
– 為了前端孤兒,後端要支援舊前端
●
新創資深工程師的 context switch 要夠快速
290
永遠迎接更多的困難
●
前端開發很奔放
– 為了前端孤兒,後端要支援舊前端
●
新創資深工程師的 context switch 要夠快速
– 許多 knowhow 都放在腦子裡
291
永遠迎接更多的困難
●
前端開發很奔放
– 為了前端孤兒,後端要支援舊前端
●
新創資深工程師的 context switch 要夠快速
– 許多 knowhow 都放在腦子裡
●
創業最缺的就是時間
292
永遠迎接更多的困難
●
前端開發很奔放
– 為了前端孤兒,後端要支援舊前端
●
新創資深工程師的 context switch 要夠快速
– 許多 knowhow 都放在腦子裡
●
創業最缺的就是時間
– 可以用錢解決的就不要花時間研究
293
ONE MORETHING
294
295
296
References
●
Funliday Tech Blog
●
Slideshare by kewang
297

More Related Content

Similar to 如何在有限資源下實現十年的後端服務演進

Docker 基礎介紹與實戰
Docker 基礎介紹與實戰Docker 基礎介紹與實戰
Docker 基礎介紹與實戰Bo-Yi Wu
 
快快樂樂學 Angular 2 開發框架
快快樂樂學 Angular 2 開發框架快快樂樂學 Angular 2 開發框架
快快樂樂學 Angular 2 開發框架Will Huang
 
以Code igniter為基礎的網頁前端程式設計
以Code igniter為基礎的網頁前端程式設計以Code igniter為基礎的網頁前端程式設計
以Code igniter為基礎的網頁前端程式設計Amigo 陳兆祥
 
D2_node在淘宝的应用实践_pdf版
D2_node在淘宝的应用实践_pdf版D2_node在淘宝的应用实践_pdf版
D2_node在淘宝的应用实践_pdf版Jackson Tian
 
Continuous Delivery Workshop with Ansible x GitLab CI (5th)
 Continuous Delivery Workshop with Ansible x GitLab CI (5th) Continuous Delivery Workshop with Ansible x GitLab CI (5th)
Continuous Delivery Workshop with Ansible x GitLab CI (5th)Chu-Siang Lai
 
Node.js在淘宝的应用实践
Node.js在淘宝的应用实践Node.js在淘宝的应用实践
Node.js在淘宝的应用实践taobao.com
 
深入淺出 autocomplete
深入淺出 autocomplete深入淺出 autocomplete
深入淺出 autocompleteMu Chun Wang
 
如何與全世界分享你的 Library
如何與全世界分享你的 Library如何與全世界分享你的 Library
如何與全世界分享你的 LibraryMu Chun Wang
 
Full stack-development with node js
Full stack-development with node jsFull stack-development with node js
Full stack-development with node jsXuefeng Zhang
 
凌波微步:wagon + VS Code 的輕功哲學
凌波微步:wagon + VS Code 的輕功哲學凌波微步:wagon + VS Code 的輕功哲學
凌波微步:wagon + VS Code 的輕功哲學Shengyou Fan
 
Gulp.js 自動化前端任務流程
Gulp.js 自動化前端任務流程Gulp.js 自動化前端任務流程
Gulp.js 自動化前端任務流程洧杰 廖
 
Continuous Delivery Workshop with Ansible x GitLab CI (3rd)
Continuous Delivery Workshop with Ansible x GitLab CI (3rd)Continuous Delivery Workshop with Ansible x GitLab CI (3rd)
Continuous Delivery Workshop with Ansible x GitLab CI (3rd)Chu-Siang Lai
 
Python 于 webgame 的应用
Python 于 webgame 的应用Python 于 webgame 的应用
Python 于 webgame 的应用勇浩 赖
 
Funliday 新創生活甘苦談
Funliday 新創生活甘苦談Funliday 新創生活甘苦談
Funliday 新創生活甘苦談Mu Chun Wang
 
HTML5 实战 WebApp 阅读应用– Shiu
HTML5 实战 WebApp 阅读应用– ShiuHTML5 实战 WebApp 阅读应用– Shiu
HTML5 实战 WebApp 阅读应用– ShiuJingchao Di
 
Beyond rails server
Beyond rails serverBeyond rails server
Beyond rails serverMichael Chen
 
前端框架發展
 前端框架發展 前端框架發展
前端框架發展Chi-wen Sun
 
这年头,你只需要懂Node webkit
这年头,你只需要懂Node webkit这年头,你只需要懂Node webkit
这年头,你只需要懂Node webkitLainZQ
 
Node.js 進攻桌面開發
Node.js 進攻桌面開發Node.js 進攻桌面開發
Node.js 進攻桌面開發Fred Chien
 
從頭打造 C#、.NET 與 ASP.NET Core 開發環境
從頭打造 C#、.NET 與 ASP.NET Core 開發環境從頭打造 C#、.NET 與 ASP.NET Core 開發環境
從頭打造 C#、.NET 與 ASP.NET Core 開發環境Will Huang
 

Similar to 如何在有限資源下實現十年的後端服務演進 (20)

Docker 基礎介紹與實戰
Docker 基礎介紹與實戰Docker 基礎介紹與實戰
Docker 基礎介紹與實戰
 
快快樂樂學 Angular 2 開發框架
快快樂樂學 Angular 2 開發框架快快樂樂學 Angular 2 開發框架
快快樂樂學 Angular 2 開發框架
 
以Code igniter為基礎的網頁前端程式設計
以Code igniter為基礎的網頁前端程式設計以Code igniter為基礎的網頁前端程式設計
以Code igniter為基礎的網頁前端程式設計
 
D2_node在淘宝的应用实践_pdf版
D2_node在淘宝的应用实践_pdf版D2_node在淘宝的应用实践_pdf版
D2_node在淘宝的应用实践_pdf版
 
Continuous Delivery Workshop with Ansible x GitLab CI (5th)
 Continuous Delivery Workshop with Ansible x GitLab CI (5th) Continuous Delivery Workshop with Ansible x GitLab CI (5th)
Continuous Delivery Workshop with Ansible x GitLab CI (5th)
 
Node.js在淘宝的应用实践
Node.js在淘宝的应用实践Node.js在淘宝的应用实践
Node.js在淘宝的应用实践
 
深入淺出 autocomplete
深入淺出 autocomplete深入淺出 autocomplete
深入淺出 autocomplete
 
如何與全世界分享你的 Library
如何與全世界分享你的 Library如何與全世界分享你的 Library
如何與全世界分享你的 Library
 
Full stack-development with node js
Full stack-development with node jsFull stack-development with node js
Full stack-development with node js
 
凌波微步:wagon + VS Code 的輕功哲學
凌波微步:wagon + VS Code 的輕功哲學凌波微步:wagon + VS Code 的輕功哲學
凌波微步:wagon + VS Code 的輕功哲學
 
Gulp.js 自動化前端任務流程
Gulp.js 自動化前端任務流程Gulp.js 自動化前端任務流程
Gulp.js 自動化前端任務流程
 
Continuous Delivery Workshop with Ansible x GitLab CI (3rd)
Continuous Delivery Workshop with Ansible x GitLab CI (3rd)Continuous Delivery Workshop with Ansible x GitLab CI (3rd)
Continuous Delivery Workshop with Ansible x GitLab CI (3rd)
 
Python 于 webgame 的应用
Python 于 webgame 的应用Python 于 webgame 的应用
Python 于 webgame 的应用
 
Funliday 新創生活甘苦談
Funliday 新創生活甘苦談Funliday 新創生活甘苦談
Funliday 新創生活甘苦談
 
HTML5 实战 WebApp 阅读应用– Shiu
HTML5 实战 WebApp 阅读应用– ShiuHTML5 实战 WebApp 阅读应用– Shiu
HTML5 实战 WebApp 阅读应用– Shiu
 
Beyond rails server
Beyond rails serverBeyond rails server
Beyond rails server
 
前端框架發展
 前端框架發展 前端框架發展
前端框架發展
 
这年头,你只需要懂Node webkit
这年头,你只需要懂Node webkit这年头,你只需要懂Node webkit
这年头,你只需要懂Node webkit
 
Node.js 進攻桌面開發
Node.js 進攻桌面開發Node.js 進攻桌面開發
Node.js 進攻桌面開發
 
從頭打造 C#、.NET 與 ASP.NET Core 開發環境
從頭打造 C#、.NET 與 ASP.NET Core 開發環境從頭打造 C#、.NET 與 ASP.NET Core 開發環境
從頭打造 C#、.NET 與 ASP.NET Core 開發環境
 

More from Mu Chun Wang

你畢業後要任職的軟體業到底都在做些什麼事
你畢業後要任職的軟體業到底都在做些什麼事你畢業後要任職的軟體業到底都在做些什麼事
你畢業後要任職的軟體業到底都在做些什麼事Mu Chun Wang
 
網路服務就是一連串搜尋的集合體
網路服務就是一連串搜尋的集合體網路服務就是一連串搜尋的集合體
網路服務就是一連串搜尋的集合體Mu Chun Wang
 
使用 PostgreSQL 及 MongoDB 從零開始建置社群必備的按讚追蹤功能
使用 PostgreSQL 及 MongoDB 從零開始建置社群必備的按讚追蹤功能使用 PostgreSQL 及 MongoDB 從零開始建置社群必備的按讚追蹤功能
使用 PostgreSQL 及 MongoDB 從零開始建置社群必備的按讚追蹤功能Mu Chun Wang
 
大解密!用 PostgreSQL 提升 350 倍的 Funliday 推薦景點計算速度
大解密!用 PostgreSQL 提升 350 倍的 Funliday 推薦景點計算速度大解密!用 PostgreSQL 提升 350 倍的 Funliday 推薦景點計算速度
大解密!用 PostgreSQL 提升 350 倍的 Funliday 推薦景點計算速度Mu Chun Wang
 
如何使用 iframe 製作一個易於更新及更安全的前端套件
如何使用 iframe 製作一個易於更新及更安全的前端套件如何使用 iframe 製作一個易於更新及更安全的前端套件
如何使用 iframe 製作一個易於更新及更安全的前端套件Mu Chun Wang
 
pppr - 解決 JavaScript 無法被搜尋引擎正確索引的問題
pppr - 解決 JavaScript 無法被搜尋引擎正確索引的問題pppr - 解決 JavaScript 無法被搜尋引擎正確索引的問題
pppr - 解決 JavaScript 無法被搜尋引擎正確索引的問題Mu Chun Wang
 
Google Maps 開始收費了該怎麼辦?
Google Maps 開始收費了該怎麼辦?Google Maps 開始收費了該怎麼辦?
Google Maps 開始收費了該怎麼辦?Mu Chun Wang
 
Git 可以做到的事
Git 可以做到的事Git 可以做到的事
Git 可以做到的事Mu Chun Wang
 
如何利用 OpenAPI 及 WebHooks 讓老舊的網路服務也可程式化
如何利用 OpenAPI 及 WebHooks 讓老舊的網路服務也可程式化如何利用 OpenAPI 及 WebHooks 讓老舊的網路服務也可程式化
如何利用 OpenAPI 及 WebHooks 讓老舊的網路服務也可程式化Mu Chun Wang
 
如何與 Git 優雅地在樹上唱歌
如何與 Git 優雅地在樹上唱歌如何與 Git 優雅地在樹上唱歌
如何與 Git 優雅地在樹上唱歌Mu Chun Wang
 
API Blueprint - API 文件規範的三大領頭之一
API Blueprint - API 文件規範的三大領頭之一API Blueprint - API 文件規範的三大領頭之一
API Blueprint - API 文件規範的三大領頭之一Mu Chun Wang
 
團體共同協作與版本管理 - 01認識共同協作
團體共同協作與版本管理 - 01認識共同協作團體共同協作與版本管理 - 01認識共同協作
團體共同協作與版本管理 - 01認識共同協作Mu Chun Wang
 
手把手教你如何串接 Log 到各種網路服務
手把手教你如何串接 Log 到各種網路服務手把手教你如何串接 Log 到各種網路服務
手把手教你如何串接 Log 到各種網路服務Mu Chun Wang
 
你有想過畢業九年後的你會變什麼樣子嗎?
你有想過畢業九年後的你會變什麼樣子嗎?你有想過畢業九年後的你會變什麼樣子嗎?
你有想過畢業九年後的你會變什麼樣子嗎?Mu Chun Wang
 
HR Search - 輕鬆管理面試者
HR Search - 輕鬆管理面試者HR Search - 輕鬆管理面試者
HR Search - 輕鬆管理面試者Mu Chun Wang
 
Hedis - GET HBase via Redis
Hedis - GET HBase via RedisHedis - GET HBase via Redis
Hedis - GET HBase via RedisMu Chun Wang
 
104學年度行動裝置程式設計課程說明
104學年度行動裝置程式設計課程說明104學年度行動裝置程式設計課程說明
104學年度行動裝置程式設計課程說明Mu Chun Wang
 
Webduino introduction
Webduino introductionWebduino introduction
Webduino introductionMu Chun Wang
 

More from Mu Chun Wang (20)

你畢業後要任職的軟體業到底都在做些什麼事
你畢業後要任職的軟體業到底都在做些什麼事你畢業後要任職的軟體業到底都在做些什麼事
你畢業後要任職的軟體業到底都在做些什麼事
 
網路服務就是一連串搜尋的集合體
網路服務就是一連串搜尋的集合體網路服務就是一連串搜尋的集合體
網路服務就是一連串搜尋的集合體
 
使用 PostgreSQL 及 MongoDB 從零開始建置社群必備的按讚追蹤功能
使用 PostgreSQL 及 MongoDB 從零開始建置社群必備的按讚追蹤功能使用 PostgreSQL 及 MongoDB 從零開始建置社群必備的按讚追蹤功能
使用 PostgreSQL 及 MongoDB 從零開始建置社群必備的按讚追蹤功能
 
大解密!用 PostgreSQL 提升 350 倍的 Funliday 推薦景點計算速度
大解密!用 PostgreSQL 提升 350 倍的 Funliday 推薦景點計算速度大解密!用 PostgreSQL 提升 350 倍的 Funliday 推薦景點計算速度
大解密!用 PostgreSQL 提升 350 倍的 Funliday 推薦景點計算速度
 
如何使用 iframe 製作一個易於更新及更安全的前端套件
如何使用 iframe 製作一個易於更新及更安全的前端套件如何使用 iframe 製作一個易於更新及更安全的前端套件
如何使用 iframe 製作一個易於更新及更安全的前端套件
 
pppr - 解決 JavaScript 無法被搜尋引擎正確索引的問題
pppr - 解決 JavaScript 無法被搜尋引擎正確索引的問題pppr - 解決 JavaScript 無法被搜尋引擎正確索引的問題
pppr - 解決 JavaScript 無法被搜尋引擎正確索引的問題
 
Google Maps 開始收費了該怎麼辦?
Google Maps 開始收費了該怎麼辦?Google Maps 開始收費了該怎麼辦?
Google Maps 開始收費了該怎麼辦?
 
Git 可以做到的事
Git 可以做到的事Git 可以做到的事
Git 可以做到的事
 
如何利用 OpenAPI 及 WebHooks 讓老舊的網路服務也可程式化
如何利用 OpenAPI 及 WebHooks 讓老舊的網路服務也可程式化如何利用 OpenAPI 及 WebHooks 讓老舊的網路服務也可程式化
如何利用 OpenAPI 及 WebHooks 讓老舊的網路服務也可程式化
 
如何與 Git 優雅地在樹上唱歌
如何與 Git 優雅地在樹上唱歌如何與 Git 優雅地在樹上唱歌
如何與 Git 優雅地在樹上唱歌
 
API Blueprint - API 文件規範的三大領頭之一
API Blueprint - API 文件規範的三大領頭之一API Blueprint - API 文件規範的三大領頭之一
API Blueprint - API 文件規範的三大領頭之一
 
團體共同協作與版本管理 - 01認識共同協作
團體共同協作與版本管理 - 01認識共同協作團體共同協作與版本管理 - 01認識共同協作
團體共同協作與版本管理 - 01認識共同協作
 
Git 經驗分享
Git 經驗分享Git 經驗分享
Git 經驗分享
 
手把手教你如何串接 Log 到各種網路服務
手把手教你如何串接 Log 到各種網路服務手把手教你如何串接 Log 到各種網路服務
手把手教你如何串接 Log 到各種網路服務
 
你有想過畢業九年後的你會變什麼樣子嗎?
你有想過畢業九年後的你會變什麼樣子嗎?你有想過畢業九年後的你會變什麼樣子嗎?
你有想過畢業九年後的你會變什麼樣子嗎?
 
HR Search - 輕鬆管理面試者
HR Search - 輕鬆管理面試者HR Search - 輕鬆管理面試者
HR Search - 輕鬆管理面試者
 
Hedis - GET HBase via Redis
Hedis - GET HBase via RedisHedis - GET HBase via Redis
Hedis - GET HBase via Redis
 
104學年度行動裝置程式設計課程說明
104學年度行動裝置程式設計課程說明104學年度行動裝置程式設計課程說明
104學年度行動裝置程式設計課程說明
 
Webduino introduction
Webduino introductionWebduino introduction
Webduino introduction
 
Lightning Hedis
Lightning HedisLightning Hedis
Lightning Hedis
 

如何在有限資源下實現十年的後端服務演進