Posts
MongoDB Compass - Install with Homebrew
要使用 Homebrew 安裝 MongoDB Compass,可以調用如下命令:
brew cask install mongodb-compass 安裝完可以透過應用程式這邊啟動 MongoDB Compass。
read morePosts
Redis - Generate Snowflake generator id with client info
在做分散式系統時,有些情境下免不了要給節點維一的識別號,像是在用 Snowflake 分散式 Id 演算法時會需要給予 10 bit 長的 Generator id,用以避免 Id 碰撞。
識別號有的會直接取 IP 某段,或是 Process no,這樣並不能確保值的唯一。要確保維一只能依賴自行靠設定將設定值錯開,或是設計一個演算法配給。
若是搭配 Redis 使用,最直覺的演算法可能就是在每個服務實體啟動時去 Redis 註冊一個唯一的識別值,服務實體與識別值的資訊都放置在 Redis 中,並設有過期時間。每個服務定時到 Redis 延長過期時間,如果資訊過期,則對應的識別碼要釋出給新服務用。
上面的演算法很直覺,但有兩點較大的問題,一個是實作上很麻煩,一個是定時到 Redis 延長過期時間的做法對系統來說不是很好。好在 Redis 有維護每個連線的 Client 資訊,也都取的到,透過 Redis client 的資訊實作上會簡單許多,對系統來說處理也比較沒那麼吃重。
舉個例子來說,假設我用 Redis 的 Hash 來實作,Key 假定為 generator,裡面的 field 用來放 Generator id,value 用來放 Redis client 的 Id。
generator => { {$generator-id, $redis-client-id}, ... } 這樣在第一個服務上線時,Redis 內的資料是空的。
generator => { } 這時透過 Redis 命令 CLIENT LIST 取得所有連線的 Id,與 CLIENT ID 命令取得當前連線的 Id,就可以去更新並配給 Generator id。像是所有連線 Id 問回來只有一個連線,且連線 Id 跟當前連線 Id 一樣都是 0,就會將 Generator id 0 配給 Redis client 0。
read morePosts
gRPC - Streaming
gRPC 的 Streaming 可用來做大量資料的傳輸,不論是 Client 傳到 Service,或是 Service 回給 Client。
使用上就是在 proto 檔用 stream 去定義要使用 Streaming 的地方,看是用在傳入還是回傳。
... service Greeter { ... rpc SayHellos (stream HelloRequest) returns (stream HelloReply) {} } ... 然後 Service 與 Client 透過 IServerStreamWriter 寫資料、透過 IAsyncStreamReader 讀取資即可。
以寫入來說,可透過迴圈搭配 WriteAsync() 將資料逐筆寫入,最後透過 CompleteAsync() 告知寫入完成。
foreach (var item in data) { await stream.WriteAsync(item); } await stream.CompleteAsync(); 或是引用 Grpc.Core.Utils,直接透過 WriteAllAsync() 將所有資料寫入。
... await stream.WriteAllAsync(data); ... 以讀取來說,可用迴圈搭配 MoveNext() 移至下筆可用的資料,再用 Current 取出資料做處理。
read morePosts
Try .NET - Installation
要安裝 Try .NET,可透過 dotnet tool install 將 dotnet-try 安裝到全域。
dotnet tool install --global dotnet-try 安裝完就可以開始使用。
dotnet try -h 若無法運行,可查驗一下是否為路徑問題。
export PATH="$PATH:/root/.dotnet/tools" 若有需要可透過 dotnet tool update 更新 dotnet-try 套件。
dotnet tool update -g dotnet-try
read morePosts
MongoDB - Clear system.profile collection
在做 MongoDB 的 Profiling 時,有時我們會需要清除 system.profile collection 內的資料。
像是這邊筆者已經有資料在 system.profile collection 內。
db.system.profile.count() 要將 system.profile collection 清除,先要將 Profiler 關閉,也就是透過 db.setProfilingLevel 將 Profiling 等級設為 0。
db.setProfilingLevel(0) 然後 drop system.profile collection。
db.system.profile.drop() Link profiling - How to delete system.profile collection from a MongoDB? - Stack Overflow
read morePosts
MongoDB - Check profiling level and status
MongoDB 在設定好 Profiler 後,可用 db.getProfilingLevel 查驗設定的 Profiling 層級。
db.getProfilingLevel() 或是用 db.getProfilingStatus 查驗整個 Profiling 設定。
db.getProfilingStatus()
read morePosts
MongoDB - Enable and configure database pofiling
要設定或啟用 MongoDB Profiler 功能去能監控較慢的運行,可先進入 MongoDB。
mongo 切到指定資料庫。
use $db 透過 db.setProfilingLevel 設定 Profiling 的層級與定義耗費多少毫秒是慢的處理。
db.setProfilingLevel($level, $slowms) Profiling 的層級如下:
Level Description 0 The profiler is off and does not collect any data. This is the default profiler level. 1 The profiler collects data for operations that take longer than the value of slowms. 2 The profiler collects data for all operations. 如果層級設為 0,則會停止 Profiling;設為 1,則會抓取比 slowms 久的操作;設為 2,則會抓取所有操作。
設定完實際運行程式,MongoDB Profiler 就會依 Profiling 的設定幫我們抓出慢的操作。
read morePosts
migrate - MongoDB driver
migrate 要對 MongoDB 進行資料庫的 Migration,Migration 檔案內要放置要給 MongoDB 用 db.runCommand 運行的命令,附檔名為 json。
migrate 的資料庫這邊要參照下列格式設定。就可以透過 migrate 做資料庫的 Migration。
mongodb://user:password@host:port/dbname?query 運行 Migration 後資料庫內會多個 schema_migrations collection,用以存放 Migration 的資訊。
Link MongoDB
read morePosts
migrate - MySQL/MariaDB driver
migrate 要對 MySQL/MariaDB 進行資料庫的 Migration,migrate 的資料庫這邊要參照下列格式設定。
mysql://user:password@tcp(host:port)/dbname?query Migration 檔案用 SQL 語法下去撰寫。
就可以透過 migrate 做資料庫的 Migration。
運行 Migration 後資料庫內會多個 schema_migrations 資料表,用以存放 Migration 的資訊。
schema_migrations 資料表內只會有一筆紀錄,只會有 version 與 dirty 資訊,沒有 Migration 的版本紀錄,也沒有 CRC 檢查碼驗證。
Link MySQL
read morePosts
MethodBoundaryAspect.Fody - Altering asynchronous method behavior
MethodBoundaryAspect.Fody 要修改非同步方法的回傳值,可在 OnExit 方法實作時將 MethodExecutionArgs.ReturnValue 屬性值轉回 Task,用 ContinueWith 串接處理,並將之塞回 MethodExecutionArgs.ReturnValue。
if (args.ReturnValue is Task<...> t) { args.ReturnValue = t.ContinueWith(...); } 像是如果要撰寫一個可將方法回傳值變大寫的 Attribute 的話,可像下面這樣撰寫。
using System.Threading.Tasks; using MethodBoundaryAspect.Fody.Attributes; namespace MethodBoundaryAspect.Fody.Demo { public sealed class UpperAttribute : OnMethodBoundaryAspect { public override void OnExit(MethodExecutionArgs args) { if (args.ReturnValue is Task<string> t) { args.ReturnValue = t.ContinueWith(task => t.Result.ToUpper()); } else { args.ReturnValue = (args.ReturnValue as string).ToUpper(); } } } } 在要做大寫轉換的方法上加掛 Attribute。
using System; using System.
read more