自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

如何讓前端程序員沒有后端也能完成項目

開發(fā) 前端
直接把 Mysql 暴露在公網(wǎng)給前端使用會有什么問題?要做到 Backend as a "Database",就知道如何解決。

 [[356823]]

答:Backend as a Database, Sort Of

直接把 Mysql 暴露在公網(wǎng)給前端使用會有什么問題:

  • I/O 邊界 => 性能考慮
    • 批量獲取多條數(shù)據(jù)
    • 對數(shù)據(jù)進(jìn)行 count / sum 等聚合
    • 把聚合結(jié)果做提前計算,冗余字段
  • 組織邊界 => 安全考慮
    • 數(shù)據(jù)權(quán)限校驗,防止非法訪問
    • 校驗業(yè)務(wù)規(guī)則
      • 產(chǎn)生的訂單價格應(yīng)該等于商品單價之和
      • 出庫單要創(chuàng)建,需要xxx領(lǐng)導(dǎo)簽字單

要做到 Backend as a "Database",就是回答以上問題如何解決。

User 表

Mysql / Postgresql 的權(quán)限太粗了??隙ㄊ且?Mysql / Postgresql 外邊套一層去校驗權(quán)限。這里有如下的挑戰(zhàn)要解決

  • B 端權(quán)限需要非常細(xì)致,不僅僅要到行,甚至到格。權(quán)限可能是按職位授予,也可能是因為工單分配臨時授予。
  • 權(quán)限校驗開銷不能太大,如果拿來做 C 端業(yè)務(wù),單據(jù)數(shù)量和用戶數(shù)量都可能會非常大。要減少因為行級別權(quán)限引入的開銷。所以要能按需打開不同的授權(quán)模式。
  • 沒有登錄的用戶需要登錄,或者能夠匿名瀏覽。如何方便給沒有用戶的訪問做適當(dāng)?shù)奶釞?quán)。
  • 非真實人類用戶的訪問,比如夜間的批處理,需要能夠有機器人的賬號
  • 賬號的初始化是如何描述的,誰來分配最初的那個管理員
  • 如果有多個 Project,每個 Project 有自己的用戶體系,不同的 User 表。這兩個 Project 要互相訪問,用什么 User 身份?

解決了以上問題,我們就獲得了一個內(nèi)建權(quán)限的“Database”,可以開放到公網(wǎng)給前端訪問。實際拉數(shù)據(jù)的時候,用的是人類用戶自己的身份。只要用戶自己對要訪問的數(shù)據(jù)表或者行有權(quán)限,就可以訪問到,否則就訪問不到。

業(yè)務(wù)數(shù)據(jù)表

寫一個 Typescript 的類,然后把 Mysql 的表建好。和 Java Hibernate 一樣

  1. @Biz.profile('買家''read'
  2. @Biz.profile('店長''read''create''update''delete'
  3. @Biz.profile('管理員''read''create''update''delete'
  4. @Biz.authentic({ rowPolicy: 'public' }) 
  5. @Biz.published 
  6. export class RegionFreightTmpl extends Biz.ActiveRecord { 
  7.     @Biz.lookup 
  8.     public readonly freightTmpl: FreightTmpl; 
  9.     // 計費模式:按件(目前只有按件) 
  10.     public freightTmplType: string; 
  11.     public firstPrice: number; 
  12.     public firstAmount: number = 1
  13.     public additionalPrice: number; 
  14.     public additionalAmount: number = 1
  15.     public regions?: string; 

查詢的時候直接用這個 class 來指代這張數(shù)據(jù)庫表就可以了。

視圖表

能夠做好權(quán)限校驗的前提是只暴露單表的簡單查詢。那么 count / sum / join 這些怎么處理? 難道是要發(fā)明一種 SQL 變種,然后搞 SQL 解析么?

一個簡單的做法就是引入“視圖表”的概念。把這些聚合查詢都建模成一張?zhí)摂M的視圖表。這樣在查詢的時候仍然是單表查詢。

  • 解決了 rpc 請求的時候如何表達(dá)復(fù)雜 query 的問題,避免了 sql over http
  • 解決了權(quán)限校驗難以確定目標(biāo)是什么的問題

物化視圖表

如果所有的聚合查詢都要按需計算則會非常慢。經(jīng)常我們需要一些按日期,按維度提前聚合好的中間結(jié)果。這個可以用物化視圖表來表達(dá)

  1. @(Biz.view`SELECT id, gender, age, city, SUM(OrderItem.cost) AS total 
  2. FROM ${impactSet} 
  3. JOIN ${User} on User.id = impactSet.userId 
  4. LEFT JOIN ${Order} on User.id = Order.userId 
  5. LEFT JOIN ${OrderItem} on Order.id = OrderItem.orderId`) 
  6. @(impactSet`SELECT DISTINCT(Order.userId) AS userId FROM ${ Order }`) 
  7. @(impactSet`SELECT DISTINCT(Order.userId) AS userId FROM ${ OrderItem } JOIN ${ Order } on Order.id = OrderItem.orderId`) 
  8. @Biz.source(Starriness, { dataSource: 'clickhouse' }) 
  9. export class UserWithTotal extends Biz.SqlView { 
  10.     public readonly id: string; 
  11.     public readonly userId: string; 
  12.     public readonly created_at: Date; 
  13.     public readonly total: number; 

物化視圖的問題在于什么時候刷新。通過用 SQL 定義 impactSet,我們可以由 mysql binlog 觸發(fā)物化在 clickhouse 中的物化視圖表刷新。

用戶行為表

物化視圖的來源是業(yè)務(wù)數(shù)據(jù)。用戶行為因為數(shù)據(jù)量比較大,不太適合直接插入到 mysql 中。把用戶行為單獨提供一張寬表來記錄用戶做過什么操作。寫入可以是內(nèi)存緩沖,或者經(jīng)過 kafka 這樣的隊列緩沖。

寬表的列應(yīng)該是按業(yè)務(wù)需求擴展的,如果業(yè)務(wù)上關(guān)心用戶操作的訂單id,或者商品id,則要加上這些字段。大概的 api 也類似 mixpanel 這些老牌分析廠商的上報接口。

物化視圖在計算報表的時候可以 join 用戶行為表和業(yè)務(wù)數(shù)據(jù)表來得出分析結(jié)果。

批量查詢

一次 rpc roundtrip 只能發(fā)一條查詢太慢了。那支持一個數(shù)組,一次可以提交多條查詢就好了。至于前端代碼中怎么把多個組件的查詢聚合到一個 rpc 中,這個就看前端的 data query 框架是怎么來弄了。無非就是全局搞個 buffer,在“合適的時候”刷一下這個 buffer,批量查一次。

存儲過程

細(xì)粒度的用戶權(quán)限只能解決數(shù)據(jù)完全被一個用戶擁有的問題。很多時候數(shù)據(jù)是協(xié)作數(shù)據(jù),有多個 stakeholder,那么就必須經(jīng)過協(xié)商好的規(guī)則去修改數(shù)據(jù),而不是一個用戶說了算。例如你可以決定今天的日記本里隨便寫啥,但是不能決定把今天晚飯的訂單改成0。日記是你擁有的,但是訂單是多個相關(guān)方都關(guān)心的。

解決業(yè)務(wù)規(guī)則校驗后寫入的問題就是存儲過程了。前端同學(xué)肯定是希望用 javascript 來寫存儲過程。實際上就是所謂 FaaS 的云函數(shù)。本質(zhì)上就是后端代碼仍然有,只是換了一撥人來寫。

如果業(yè)務(wù)規(guī)則比較簡單,例如只是一個狀態(tài)機的轉(zhuǎn)換圖,則可以用配置替代code。當(dāng)然大部分時候,復(fù)雜的業(yè)務(wù)邏輯,上 javascript 是最直觀的。

Data Migration

數(shù)據(jù)庫表結(jié)構(gòu)變更了肯定還是要寫 SQL 來升級數(shù)據(jù)庫的,標(biāo)準(zhǔn)做法沒啥說的。

Backend as a Database

  • 用 RPC 接口提供了一個類似 Database 的東西
  • 把后端業(yè)務(wù)切分成了 User表/業(yè)務(wù)數(shù)據(jù)表/視圖表/物化視圖表/用戶行為表/存儲過程/DataMigration 等預(yù)設(shè)的概念,變得更規(guī)整
  • 除了“需要經(jīng)過業(yè)務(wù)規(guī)則校驗之后寫入”這個例外,其他的后端接口都不需要上通用編程語言,可以用配置或者SQL定義解決
  • 這個解法既不是 GraphQL,也不是經(jīng)典的 BFF

 

責(zé)任編輯:張燕妮 來源: 知乎
相關(guān)推薦

2024-05-06 00:00:00

2021-08-28 23:26:14

程序員編碼電腦

2020-06-05 07:52:25

程序員離職編碼

2015-12-15 09:37:18

程序員設(shè)計勤奮

2020-02-14 15:16:16

程序員表白浪漫

2017-12-15 15:09:42

2013-05-27 17:12:41

面試Google

2020-09-14 11:00:37

程序員技術(shù)日志

2010-07-29 11:00:59

程序員

2015-12-07 11:44:31

程序員厭倦工作

2015-12-09 09:17:11

情緒厭倦程序員

2011-06-02 09:02:36

程序員

2012-09-11 10:33:40

2011-09-06 09:02:06

程序員

2018-11-01 15:20:17

前端程序員編程語言

2011-04-28 09:26:06

程序員

2021-03-29 10:14:45

程序員技能開發(fā)

2019-11-23 23:21:44

程序員前端全棧

2010-12-14 10:04:07

程序員

2011-06-14 09:47:57

程序員
點贊
收藏

51CTO技術(shù)棧公眾號