聊一聊開發中的一些坑
本文轉載自微信公眾號「HHFCodeRv」,作者haohongfan 。轉載本文請聯系HHFCodeRv公眾號。
本篇文章羅列一些開發業務時遇到的那些坑。
微服務銀彈
當前的市面上各種微服務,DDD的課收割了一波又一波的韭菜,有同學聽完了課就要迫不及待的嘗試一下。學習新知識的動力當然值得肯定,但是具體落地需要根據公司實際場景來。
某前同事找我咨詢架構相關的事情,跟他一番交流讓我徹底無語了。
這是他們公司 JAVA 架構師落地的方案(2個開發,其中一個還是架構師,真是鬧)。姑且不論架構師水平如何,當我看到 2 個后端開發,拆出了 17 個服務時,我的建議是立即開除這個人。
我們在一個公司有一定的技術話語權時,想落地我們學到的技術時,一定要根據實際情況來,不能想當然的去橫向、縱向拆分服務。
是否拆分微服務條件:
- 公司業務是否到了一定規模
- 人員數量是否到了一定數量
- 服務治理能力是否完備,比如:配置中心,服務注冊發現,日志系統等
- 是否有了一套完整的監控方案
- 持續集成,持續部署能力是否完備
- 服務部署是虛擬機還是 kubernetes ? 是否有足夠能力運維?
- ....
總之,對于業務規模較小的公司,開發人員較少時,一定不要為了拆微服務而去拆,單體服務完全夠用。
一個 class 走天下
用這個 case 吐槽下某些 php 程序員。
相信大部分同學都有一定的強迫癥,比如:函數的參數個數,函數的行數,每行的最大長度等等。當然這些判斷,借助 lint 工具都能完全解決。
對于函數參數的控制,一般正確的做法:抽離程序邏輯,盡量控制函數邏輯。實在不行的可以借助 struct 或者 class 的封裝特性,往下傳遞參數。
不過有些 phper 卻借助了 php 的特性,搞了一些騷操作:將所有的參數或者返回值全都放在一個全局的 Class 的 static 變量里面,這樣就不需要函數間傳遞參數了。大概形式如下:
- class CommonService
- {
- //存儲接口的入參
- static public $inputParams = null;
- static public $output = [];
- static public $objMap = [];
- //....
- }
這個寫法有以下這些特點:
- 這個 Common Service 基本貫穿了整個業務邏輯
- 不同的位置都可能在更改或者讀取某個字段
造成的結果:
- 不相關的業務邏輯強行耦合
- 某些位置剛修改的字段,可能被再次更改
- 預期之外的修改將整個邏輯污染
- 業務邏輯變得晦澀難懂
其實完全簡單的封裝就能解決的事情,搞出來的這種代碼,讓人實在忍不住吐槽。
MySQL 里面全是 json
大部分互聯網公司,MySQL 肯定是業務數據庫的標配選擇,畢竟運維成熟。
我們設計數據庫的時候,教科書是讓我們至少遵守“第三范式”:
不過真實業務開發中,設計 MySQL 的時候,有的時候為了查詢簡單,會將某些字段設計成 json, 這樣就減少一張關聯表的查詢。這種設計其實還算是比較合理做法。
但是更多的情況下,很多人把數據庫字段設置成 json,美名是為了更好的擴展性。
比如下面這種設計:
由于商品的屬性字段是特別多的,不同商品的屬性是不固定的。為了擴展性,將商品屬性字段全都塞到一個 json 里面,而且 json 也有一套邏輯在里面:aflag 與 bflag 會互相覆蓋。
這么設計造成的結果:
商品屬性字段基本處于無法控制的地步
哪些商品擁有哪些屬性是不知道的
一個商品擁有哪些屬性,需要通過一系列復雜的解析,計算才能知道
json 的字段是不確定的,golang/java 解析起來困難
json 字段作為擴展性,這個擴展性是我覺得是值得商榷的,因為大部分場景下能做擴展的字段,基本都是業務邏輯沒有想清楚。如果一個表的某個字段是 json 類型,而且 json 里的字段能新增、修改,刪除,最終就會造成這個 json 最終變得不可控,早晚走上數據庫數據治理的地步。
無腦吹 GraphQL
喜歡看博客或者公眾號的同學,對 GraphQL 都不會陌生。看過 GraphqQL 的同學上來就被其特性吸引了。
特性:
- 請求你所要的數據不多不少
- 獲取多個資源只用一個請求
- 描述所有的可能類型系統
- API 演進無需劃分版本
是不是很有吸引力?看到這些特性,我覺得大部分同學都會忍不住嘗試下。
我有幸具體落地過 GraphQL,這里就想吐槽一番。
開發流程
GraphQL 是有默認的 Schema 的,這個 Schema 類似于 Protobuf。如果 Client、Server 對不齊這個 Schema 的話,Client 直接獲取不到任何數據了。
在使用 http RESTFUL 開發 api 接口時,差不多是這個流程:
但是使用了 GraphQL,需要 Client/Server 雙方坐下來,將各個字段都仔細討論清楚了。了解過 GraphQL 的同學都知道,GraphQL 能從一個類型訪問到另外一個任意類型,為了這個實現這個目標,雙方討論字段的過程簡直慢的不可想象。可能排期都過去一星期了,字段都沒對清楚。
固然字段對清楚對開發結果的反饋是正向的,但是這個 Client/Server 之間的溝通過程真的很慢。
網關
GraphQL 最大的問題就是網關。
客戶端使用 Graphql 的最大問題是:客戶端只能有一個 Schema。所以當你有多個 Graphql Server 時想對外提供服務時,就需要合并 Schema。目前市面流行的網關 Nginx, APISIX, Kong 都不支持將 Schema 合并。
于是你只能將所有的業務都耦合到同一個 GraphQL 中,無形中將 GraphQL 做成了單體服務。
曾經調研過這個問題,發現只有 JS 提供一個合并 schema 的功能,其他語言基本都沒有這個實現。
復雜度
GraphQL 另外一個問題就是對查詢復雜度的控制。
GraphQL 可用從一個類型任意查詢到任意一個類型。假如沒有任何控制的話,客戶端一次請求能將所有的數據全都拉取出來。
當時遇到過的一個問題:客戶端拉取所有的列表,又將列表中每條記錄的詳情,通過一次請求全部請求,導致的結果:服務器直接就崩了。
GraphQL 提供了復雜度和深度的控制功能,但是這個復雜度和深度是很難計算的。
綜上:不建議項目使用 GraphQL。




































