分類: 程式語言

Case Study: 以HackMD為例,使用Signed URL為雲端儲存服務做到authorization機制

Golang架構設計程式語言雜記雲端服務

公司目前的服務有幾隻API會提供用戶上傳檔案(KYC及回傳明細)用。而現有檔案上傳機制是將檔案以BLOB的形式存在資料庫的ATTACHMENT資料表內。

這種做法的好處是上傳檔案並且更改記錄狀態可以包成一包transaction,實現業務邏輯上資料的一致性(要嘛用戶的狀態為等待上傳並且屬於此用戶上傳的檔案還不存在、要嘛用戶的狀態為已上傳並且屬於此用戶上傳的檔案已歸檔)。

但是這樣做的壞處是DB那台機器對於操作下載檔案時會消耗一部分CPU與network io bandwidth,也就等於會拖慢DB處理關聯式資料CRUD的主業。隨著使用量的增加,團隊中最近開始考慮要將檔案上傳的功能拆出至DB以外的solution。

從檔案內容判斷是不是圖片檔

GolangNode.js程式語言計算機概論雜記

最近在工作上需要寫一隻圖片上傳的API,好讓使用者上傳證明用的圖片供後續人工審核用。身為一隻稱職的圖片上傳API,當收到使用者發過來的請求後第一步肯定要做參數檢查,驗證使用者上傳的檔案是不是真的是圖片檔,並將亂上傳的請求拒於門外。

但是今天使用者傳來的是檔案其實對API來說都是binary的形式,要怎麼檢驗它真的是圖片檔呢?如果用最直覺判斷副檔名的方式的話有可能會遇到使用者故意改副檔名,然後惡意上傳其它非影像的檔案,所以用副檔名擋肯定是不夠的。在survey了一下後,發現其實還有一招是可以從檔案內容中的magic number下手來判斷。

Node.js實作Mutex(互斥鎖)防止緩存擊穿

Node.js程式語言

最近在工作上需要寫一隻會高併發的API。為了不讓DB被灌爆,所以在DB前面再加一層redis當緩存,並且設定TTL過期,因此整個API程式流程大致上變成:

  • 從redis取資料 -> 成功取到資料 -> 返回

如果今天redis因為資料TTL過期導致取不到資料,這時候才訪問DB:

  • 從redis取資料 -> 沒有取到資料 -> 從DB取資料 -> 成功取到資料,將資料回存redis並設定TTL -> 返回

 
轉換成程式碼的話看起來也並沒有特別的複雜:

const item = await redisClient.hgetall(itemKey);
if(item) {
	return item;
}

const sql = 'SELECT * FROM `Product` WHERE `id` = ?';
const [rows, fields] = await dbConnection.query(sql, [itemKey]);
if(rows.length > 0) {
	const [item] = rows;
	await redisClient
		.multi()
		.hmset(itemKey, item)
		.expire(itemKey, 60)
		.exec();
	return item;
}

return null;

 
不過,魔鬼藏在細節裡。Node.js雖然說是使用單執行緒在執行,但因為用到了async/await的語法,所以實際上當遇到異步函式時,Node.js會將異步函式丟進event loop等有空時才執行,並且當promise被resolve或reject後才從剛剛await處接續往下。這就讓在高併發的情況下,會發生如下圖中的狀況。

完整圖解Node.js的Event Loop(事件迴圈)

Node.js程式語言

最近當完兵在面試Backend Engineer的缺,想把主力放在Node.js上,因此又把一些Node.js的核心觀念拿出來啃了一遍。網路上太多把前端瀏覽器的Event Loop與Node.js的Event Loop混著講的文章了,因此趁記憶猶新時把Node.js的Event Loop記錄一下,釐清一下觀念。

在開始前先做個小測驗,如果你都能答對代表你的觀念很清晰,這篇文章的內容你應該都懂了。如果答錯了就請繼續往下閱讀吧。

請寫出各個console.log();輸出的順序:

console.log('start');

process.nextTick(function() {
  console.log('nextTick1');
});

setTimeout(function() {
  console.log('setTimeout');
}, 0);

new Promise(function(resolve, reject) {
  console.log('promise');
  resolve('resolve');
}).then(function(result) {
  console.log('promise then');
});

(async function() {
  console.log('async');
})();

setImmediate(function() {
  console.log('setImmediate');
});

process.nextTick(function() {
  console.log('nextTick2');
});

console.log('end');

挑戰一下自己先別往下滑

再往下滑就是解答嘍!!

白話文講解支持向量機(二) 非線性SVM

Python機器學習程式語言

先恭喜一下我自己煎熬了四個月終於退伍了XD。趁著退伍後的空閒時間趕快來補齊之前還沒寫完的SVM續集。😝

在上一篇白話文講解支持向量機(一) 線性SVM中我們學到了線性SVM的損失函數、目標函數,以及調整超參數C來決定決策線在訓練時對於資料點的靈敏程度。本篇我們將來介紹當資料不是單純可以線性分割時,非線性SVM是如何分類資料的。

以下是本篇講解的順序:

  • 線性SVM(上一篇)
  • 特性
  • 損失函數
  • 目標函數
  • 目標函數中的正規化項