精選後端開發技巧大集合

Hi,你們好,很榮幸有這個機會能夠經過寫博文的方式,把這些年在後端開發過程當中總結沉澱下來的經驗和設計思路分享出來html

模塊化設計

根據業務場景,將業務抽離成獨立模塊,對外經過接口提供服務,減小系統複雜度和耦合度,實現可複用,易維護,易拓展前端

項目中實踐例子:node

Before:python

在返還購APP裏有個【個人紅包】的功能,用戶的紅包數據來自多個業務,如:邀請新用戶註冊領取100元紅包,大促活動雙倍紅包,等各類活動紅包,多個活動業務都實現了一套不一樣規則的紅包領取和紅包獎勵發放的機制,致使紅包不可管理,不能複用,難維護難拓展mysql

After:程序員

  • 重構紅包業務
  • 紅包可後臺管理
    • 紅包信息管理,可添加,可編輯,可配置紅包使用的規則,可管理用戶紅包
  • 紅包獎勵發放統一處理
  • 應用業務的接入只須要專一給用戶進行紅包發放便可

設計概要redis

Before VS Aftersql

產品有時提出的業務需求沒有往這方面去考慮,結合場景和將來拓展須要,在需求討論的時候提出模塊化設計方案,並能夠協助產品進行設計數據庫


通用服務抽離

在項目開發中常常會遇到些相似的功能,可是不一樣的開發人員都各自實現,或者由於不能複用又從新開發一個,致使了相似功能的重複開發,因此咱們須要對可以抽離獨立服務的功能進行抽離,達到複用的效果,而且能夠不斷拓展完善,節約了後續開發成本,提升開發效率,易於維護和拓展express

項目中實踐例子:

Before

在業務中常常須要對用戶進行信息通知,如:短信定時通知,APP消息推送,微信通知,等

開發人員在接到需求中有通知功能的時候沒有考慮後續拓展,就接入第三方信息通知平臺,而後簡單封裝個信息通知方法,後續也有相似信息通知需求的時候,另外一個開發人員發現當前這個通知方法沒法知足本身的需求,而後又本身去了解第三方平臺從新封裝了通知方法,或者後續需求加了定時通知的功能,開發人員針對業務去實現了個定時通知功能,可是隻能本身業務上使用,其餘業務沒法接入,沒有人去作這塊功能的抽離,長此以往就演變成功能重複開發,且不易於維護和拓展

After

接觸到這種能夠抽離通用服務需求的時候,就會與產品確認這種需求是否後續會存在相似的須要,而後建議這把塊需求抽離成通用服務,方便後續維護與拓展

設計概要

 

Before VS After

 

構獨立服務

項目開發過程當中有些需求是與所在項目業務無關,如:收集用戶行爲習慣,收集商品曝光點擊,數據收集提供給BI進行統計報表輸出,公用拉新促活業務(柚子街和返還公用),相似這種需求,咱們結合應用場景,考慮服務的獨立性,以及將來的拓展須要,架構獨立項目進行維護,在服務器上獨立分佈式部署不影響現有主業務服務器資源

項目中實踐例子:

架構用戶行爲跟蹤獨立服務,在開發前預估了下這個服務的請求量,並會有相對大量的併發請求

架構方案:

  • 項目搭建選擇用nodejs來作服務端
    • 單進程,基於事件驅動和無阻塞I/O,因此很是適合處理併發請求
    • 負載均衡:cluster模塊/PM2
  • 架構nodejs獨立服務
  • 提供服務接口給客戶端
  • 接口不直接DB操做,保證併發下的穩定性
  • 數據異步入庫
    • 經過程序把數據從:消息隊列=>mysql
  • nodejs+express+redis(list)/mq+mysql

用戶行爲跟蹤服務的服務架構圖

 


高併發優化

高併發除了須要對服務器進行垂直擴展和水平擴展以外,做爲後端開發能夠經過高併發優化,保證業務在高併發的時候可以穩定的運行,避免業務停滯帶來的損失,給用戶帶來很差的體驗

緩存:

  • 服務端緩存
    • 內存數據庫
      • redis
      • memcache
    • 方式
      • 優先緩存
        • 穿透DB問題
      • 只讀緩存
        • 更新/失效刪除
    • 注意
      • 內存數據庫的分配的內存容量有限,合理規劃使用,濫用最終會致使內存空間不足
      • 緩存數據須要設置過時時間,無效/不使用的數據自動過時
      • 壓縮數據緩存數據,不使用字段不添加到緩存中
      • 根據業務拆分佈式部署緩存服務器
  • 客戶端緩存
    • 方式
      • 客戶端請求數據接口,緩存數據和數據版本號,而且每次請求帶上緩存的數據版本號
      • 服務端根據上報的數據版本號與數據當前版本號對比
      • 版本號同樣不返回數據列表,版本號不同返回最新數據和最新版本號
    • 場景:
      • 更新頻率不高的數據

服務端緩存架構圖

 


異步

異步編程

  • 方式:
    • 多線程編程
    • nodejs異步編程
  • 場景:
    • 參與活動成功後進行短信通知
    • 非主業務邏輯流程須要的操做,容許異步處理其餘輔助業務,等

業務異步處理

  • 方式
    • 業務接口將客戶端上報的數據PUSH到消息隊列(MQ中間件),而後就響應結果給用戶
    • 編寫獨立程序去訂閱消息隊列,異步處理業務
  • 場景:
    • 大促活動整點搶限量紅包
      • 參與成功後委婉提示:預計X天后進行紅包發放
    • 併發量比較大的業務,且沒有其餘更好的優化方案,業務容許異步處理
  • 注意:
    • 把控隊列消耗的進度
    • 保證冪等性和數據最終一致性
  • 缺陷:
    • 犧牲用戶體驗

【業務異步處理】架構圖

 

【業務異步處理】除了能夠在高併發業務中使用,在上面通用服務的設計裏也是用這種架構方式


限流

在類秒殺的活動中經過限制請求量,能夠避免超賣,超領等問題 
高併發的活動業務,經過前端控流,分散請求,減小併發量

  • 服務端限流
    • redis 計數器
    • 如:類秒殺活動
  • 客戶端控流
    • 經過參與活動遊戲的方式
    • 紅包雨/小遊戲,等方式

服務降級

當服務器資源消耗已經達到必定的級別的時候,爲了保證核心業務正常運行,須要丟卒保車,棄車保帥,服務降級是最後的手段,避免服務器宕機致使業務停滯帶來的損失,以及給用戶帶來很差的體驗

  • 業務降級
    • 從複雜服務,變成簡單服務
    • 從動態交互,變成靜態頁面
  • 分流到CDN
    • 從CDN拉取提早備好的JSON數據
    • 引導到CDN靜態頁面
  • 中止服務
    • 中止非核心業務,並進行委婉提示

高併發優化概要圖

 


防刷/防羊毛黨

大多數公司的產品設計和程序猿對於推廣活動業務的防刷意識不強,在活動業務設計和開發的過程當中沒有把防刷的功能加入業務中,給那些喜歡刷活動的人創造了不少的空子
等到你發現本身被刷的時候,已經產生了不小的損失,少則幾百幾千,多則幾萬

隨着利益的誘惑,如今已經浮現了一個新的職業「刷客」,專業刷互聯網活動爲生,養了N臺手機+N個手機號碼+N個微信帳號,刷到的獎勵金進行提現,刷到活動商品進行低價轉手處理,開闢了一條新的灰色產業鏈

咱們要拿起武器(代碼)進行自個人防護,風控,加高門檻,經過校驗和限制減小風險發生的各類可能性,減小風險發生時形成的損失

這裏列出經常使用套路(具體應用結合業務場景):

校驗請求合法性

  • 請求參數合法性判斷
  • 請求頭校驗
    • user-agent
    • referer
    • ... ...
  • 簽名校驗
    • 對請求參數進行簽名
  • 設備限制
  • IP限制
  • 微信unionid/openid合法性判斷
  • 驗證碼/手機短信驗證碼
    • 犧牲體驗
  • 自建黑名單系統過濾

業務風控

  • 限制設備/微信參與次數
  • 限制最多獎勵次數
  • 獎池限制
  • 根據具體業務場景設計... ...

應對角色

  • 普通用戶
  • 技術用戶
  • 專業刷客
    • 目前尚未很好的限制方式

防刷/防羊毛黨套路概要圖

附加

  • APP/H5中籤名規則應該由客戶端童鞋開發,而後拓展API給前端JS調用,在H5發起接口請求的時候調用客戶端拓展的簽名,這樣能夠避免前端JS裏構造簽名規則而被發現破解

併發問題

多操做

  • 場景:

當==同用戶==屢次觸發點擊,或者經過模擬併發請求,就會出現多操做的問題,好比:簽到功能,一天只能簽到一次,能夠得到1積分,可是併發的狀況下會出現用戶能夠得到多積分的問題

  • 剖析:

簡化簽到邏輯通常是這樣的:

查詢是否有簽到記錄 --> 否 --> 添加今日簽到記錄 --> 累加用戶積分 --> 簽到成功 
查詢是否有簽到記錄 --> 是 --> 今日已經簽到過

假設這個時候用戶A併發兩個簽到請求,這時會同時進入到 【查詢是否有簽到記錄】,而後同時返回否,就會添加兩條的簽到記錄,而且多累加積分

  • 解決方案:

最理想簡單的方案,只須要在簽到記錄表添加【簽到日期】+【用戶ID】的組合惟一索引,當併發的時候只有會一條能夠添加成功,其餘添加操做會由於惟一約束而失敗

庫存負數

  • 場景:

當==多用戶==併發點擊參與活動,如:抽獎活動,這個時候獎品只有一個庫存了,理論上只有一個用戶能夠得到,可是併發的時候每每會出現他們都成功得到獎品,致使獎品多支出,加大了活動成本

  • 剖析:

有問題的邏輯流程通常是這樣的:

中獎 --> 查詢獎品庫存 --> 有 --> 更新獎品庫存 --> 添加中獎紀錄 --> 告知中獎 
中獎 --> 查詢獎品庫存 --> 無 --> 告知無中獎

假設抽獎活動,當前獎品A只有最後一個庫存,而後用戶A、B、C,同時參與活動同時中獎獎品都是A,這個時候查詢商品庫存是存在1個,就會進行更新庫存,添加中獎紀錄,而後就同時中獎了

  • 解決方案:

最理想根本就不須要用多作一個庫存的SELECT獎品庫存操做,只須要UPDATE 獎品庫存-1 WHERE 獎品庫存>=1,UPDATE成功後就說明是有庫存的,而後再作後續操做,併發的時候只會有一個用戶UPDATE成功

總結:

在開發業務接口的時候須要把==同用戶==和==多用戶==併發的場景考慮進去,這樣就能夠避免在併發的時候產生數據異常問題,致使成本多支出 
可使用下面的工具進行模擬併發測試:

  • Apache JMeter
  • Charles Advanced Repeat
  • Visual Studio 性能負載

數據採集技巧(番外)

廣泛方案

  • 獲取平臺數據接口
  • 模擬接口請求
  • 數據解析過濾
  • 數據構造入庫

使用selenium+Headless自動化測試框架

  • 開發
    • 推薦用python開發
      • python+selenium+headless
    • 控制請求頻率,避免被平臺限制請求
    • 使用代理IP,繞過請求IP限制
  • 優勢
    • 無需模擬接口請求
      • 沒法攻克數據接口模擬請求(加密簽名等)
      • 接口版本頻繁變化(須要從新調研)
    • 平臺接口/頁面版本變化,能夠快速調整
      • 只須要調整採集數據所在的HTML元素的位置(class/id)
    • 能夠用戶操做/選中/點擊/模擬登錄,等
      • 登錄失效後能夠模擬登錄
      • 能夠發送登錄二維碼到釘釘進行掃碼登陸
  • 應用場景:
    • 競品數據採集
    • 淘寶商品價格和自建商品庫後臺價格監控
    • 淘寶領券金額和自建商品庫後臺券金額監控
    • ... ...

反反爬蟲

在作數據採集的過程當中,有些平臺會對重要數據的請求設置反爬蟲策略,避免數據被競品挖掘和利用,以及消耗大量資源拖垮服務器,
反爬蟲和反反爬蟲是技術之間的較量,這場沒有硝煙的戰爭永不停息。(程序員何須爲難程序員)

  • 反爬蟲能夠分爲如下兩種

    • 服務端限制
      • 服務器端行請求限制,防止爬蟲進行數據請求
    • 前端限制
      • 前端經過CSS和HTML標籤進行干擾混淆關鍵數據,防止爬蟲輕易獲取數據
  • 破解服務端限制:
    • 模擬設置請求頭
      • Referer
      • User-Agent
      • Authorization
      • .....
    • 破解簽名
      • 簽名規則
        • 在JS中找到簽名規則
    • 控制請求平率
      • 調整請求時間,延遲請求
    • 代理IP
      • 切換請求的代理IP,自建/第三方
    • 登陸限制
      • 帶上登陸成功後的Cookie/Authorization
    • 驗證碼限制
      • 識圖,基於庫/第三方
    • 投毒破解
      • 爲了防止被投毒,須要對數據進行抽樣校驗
  • 破解前端限制:
    • font-face,自定義字體干擾
      • 找到ttf字體文件地址,而後下載下來,使用font解析模塊包對ttf文件進行解析,與文字編碼進行映射出中文
    • 僞元素隱藏式
      • 在CSS裏找到xxxx::before {content: "中文";}對應的中文
    • backgroud-image移量
      • 經過背景圖片的position位置偏移量和圖片中的內容進行映射
    • html標籤干擾
      • 過濾掉干擾混淆的HTML標籤,或者只讀取有效數據的HTML標籤的內容

總結

做爲後端開發者,不只是完成需求功能開發,要結合業務場景進行合理設計,架構將來,對核心業務進行壓測優化,以保證業務在併發下可以正常運行,同時要考慮安全問題以及防刷,防羊毛黨,在編碼上避免壞代碼味道,面相抽象開發,適當使用設計模式,避免技術債

開發應該銘記於心的精句

    • 技術的存在價值,是讓技術推進業務增加,實現公司盈利增加
    • 沒有最好的架構只有最適合的架構
    • 開發語言只是工具,在適合的場景中使用適合的工具
    • 抽象思惟是從具體存在的各不相同的問題當中洞察問題的本質,理解產品需求的深層次模型,治本而不是治標
    • 知識很重要,她雖然不能直接給你財富,可是能夠給你不少機會,活到老學到老
    • 首發於SFLYQ博客
相關文章
相關標籤/搜索