嗯..這篇文章筆記性質很重,因為工作上需要就順便記錄一下流程以及可能遇到的問題。

安裝

1
brew install mongodb

真的就這樣!
好吧!我有先安裝 HomeBrew 這個套件,相信 macOS 使用者應該都知道,這個套件能處理相依性的問題,若有使用linux like 的應該很能體會各種套件相依性的難搞。
BTW,不需要特別先 brew update,因為使用 brew 就會先執行 update 指令囉。

啟動mongodb前準備

MongoDB預設的DB路徑是 /data/db,所以要先配合建立這個資料夾,並賦予權限。

1
2
3
sudo mkdir -p /data/db
sudo chown pattrichou /data/db //pattrichou請自行替換成你的使用者名字
mongod //啟動

小提醒:你可以使用 whoami 指令來查詢使用者名稱

如果你不是想使用預設的路徑,可以透過 –dbpath 參數來指定DB路徑

1
mongod --dbpath <your own path>
閱讀全文 »

軟體架構圖是讓人理解系統非常重要的,而用於表現、體現軟體架構的圖有非常多種,這邊談到的是C4模型。

圖勝表、表勝文

大家都知道圖的重要性,繪製一張好的圖需要很多次的來回討論與修改,儘管花費很多時間,一但完成能夠大幅縮短後人了解系統的時間。

好啊!那來畫UML吧

UML並不是不好,而是有一些限制在,簡單列一下我的感受:

  • 觀看高度不夠。如果是想讓人快速了解系統或是要跟老闆報告,這些圖都不太適合,通常需要其他圖片來輔助。
  • 外行看不懂。圖片畫出來就是要與人溝通的,如果門檻過高讓人看不懂無異於無字天書,如果你的對象是工程師,那我想應該不會有太大問題。
  • 你真的懂UML?UML包含了各種類型的圖,除非有認真學習過怎麼繪製,否則裡面的每個細節可能會被誤用,一但誤用,就是誤會的開始了..
    例如循序圖的 Component/Entity是什麼?何時該用虛線何時該用實線…等等
  • 到底要多詳細?同樣一張圖片,無法有明確的規範到底該畫到多詳細,有的人認為寫出描述即可,有的人需要畫出實作的方法名稱

說了一些點,本篇不是討論UML的,不過我依然認為他還是個對溝通有用的圖,如果真的有寫文件的話,甚至如果真的有人看的話。

C4 Model

最近接觸到C4 Model架構,用來描述軟體架構的概念,當然相同的工具、做法有很多種,這邊就先寫一篇心得來記錄一下。
作者將架構圖的視野由高至低分為四個等級,第一等級是最上層也是最粗略的。

以下圖片街擷取自官網

閱讀全文 »

在這個硬體成本不算高的年代,記憶體的使用通常都略微不那麼謹慎;往往在宣告數字型別時不會太謹慎(還是剛好我遇到的都…),例如只有short 需求卻宣告成 int 這種狀況屢見不鮮。

若要好好地控制記憶體使用量,避免溢位的需求就要特別注意,尤其這種狀況通常發生在執行期,log也可能也無法完整紀錄當時狀況,因此 Checked 語法就派上用場了。

1
2
3
4
short shortNumber = 32767;
Console.WriteLine($"Org short number: {shortNumber}");
shortNumber += 1;
Console.WriteLine($"Plus 1 to short number:{shortNumber}");

顯示結果如下:

1
2
Org short number: 32767
Plus 1 to short number:-32768

明明只有加1卻出現了意想不到的數字。為了避免這種情況發生,可以使用Checked語法來做檢查,至少如果有問題會先彈出exception。

1
Console.WriteLine($"Plus 1 to short number:{checked(shortNumber+=1)}");

結果是直接跳出exception並告知以下結果:

1
Unhandled Exception: System.OverflowException: Arithmetic operation resulted in an overflow.

當然我們也可以預先使用try catch來攔截相關的錯誤

閱讀全文 »

環境準備

這篇主要是講在mac os下,.Net core 的程式如何連線至MySql資料庫。需要具備的工具如下

  • MySql
  • .Net core 2.1 or later
  • MySql workbench (option)
    這套軟體是Mysql的管理GUI,如果習慣使用terminal的就不需要

安裝Mysql

這個基本上毫無難度,除非不熟mac的使用者可能會需要學習如何安裝程式。
特別要注意的是安裝後要從“系統偏好設定”裡面開MySql的服務,如果沒看到的話,就重啟OS即可。

alt
alt

習慣使用指令的人也可以直接到安裝目錄開啟

1
2
# cd /usr/local/mysql/bin
# sudo ./mysql -u root -p

建立資料庫/資料表與資料

1
2
3
4
5
6
create database TestConn;
use TestConn;
create table Connection(ConnStr varchar(100), Remark varchar(100));

insert Connection(Connstr, remark) values('conn1', 'remark1');
insert Connection(Connstr, remark) values('conn2', 'remark2');
閱讀全文 »

.Net Core 2.0 之前

在 .Net core 專案底下編譯出來的只有 dll 與 json 的設定檔,有時候一些情況下還是使用 .exe 來執行 console 專案會比較方便。

.Net core 2.0 以前必須要在 csproj 裡面設定這個屬性,並且指定相對應的 os

1
2
3
<PropertyGroup>
<RuntimeIdentifiers>win10-x64</RuntimeIdentifiers>
</PropertyGroup>

上述就是建置出可在 win10 x64執行的 exe檔案。

.Net Core 2.0 之後 (Terminal Command)

當然也可以執行在terminal 執行輸入指令

1
dotnet publish -c Release -r win10-x64

-c 是建置的configuration,預設資料夾是 Debug
-r 是建置目標的 framework,就是本篇文章的目的

Platform 清單

閱讀全文 »

交換器(Exchange)是什麼?

當訊息寫入RabbitMQ時,並非直接將訊息寫入佇列中,而是透過交換器(Exchange)將訊息正確分派到佇列中,而依據就是訊息自帶的RouteKey是否與BindKey相符合;若完全沒有符合的佇列,則會自動遺棄該訊息。

交換器有哪幾種?

常用的交換器有四種 Direct, Fanout, Topic and Headers.

  • Direct: 預設的模式,即直接將訊息分配到 RouteKey 與 BindKey 完全相同的佇列上。
    Case1: BindKey: “log.info
    log.debug -> 不符合
    log.info -> 符合
    log.infomation -> 不符合
  • Fanout: 顧名思義就是將此訊息分配到每一個佇列上,等於是複製了n次。若設定fanout的話會自動忽略 BindKey與RouteKey。
  • Topic: Topic是較常用也是靈活度最高的模式,有點像是.net的routing概念,只要符合規格的RouteKey就會被傳遞到正確的queue。
    特殊符號分別是: * (一個任意字)與 # (零以上個任意字)。

    Case1:

    1
    2
    3
    4
    5
    BindKey: "*I.am.*"
    I.am.boy -> 符合
    I.am.girl -> 符合
    I.amNot.girl -> 不符合
    I.am.boy.too ->不符合

    Case2:

    1
    2
    3
    4
    BindKey "#.strong"
    He.is.strong -> 符合
    Not.strong -> 符合
    I.am.not.strong.neither -> 不符合
  • Headers: 從訊息中的header與BindKey做批配比較,並寫入queue中。這部分我也很少用,之後有特別研究再來補上怎麼使用。

    使用上的效能當然還是 fanout > direct > topic,但我認為除非在很極端的狀況下,否則比較這個的意義並不大,畢竟工具的使用還是以符合需求為主。
    另一點要注意的是RouteKey長度限制為255 bytes。

Fanout模式的演示

首先我們在宣告Exchange時將type指定為 “fanout”,當然在訂閱端也是需要的,程式碼一樣就不再貼上。

1
channel.ExchangeDeclare(exchange: "logs", type:"fanout");

其他部分沒有改變,將專案建置好後,開啟兩個訂閱者程式,然後執行Sender.exe以fanout模式送出一個訊息,就可以看到兩個視窗幾乎同時收到該訊息,且進行處理。
alt

程式範例檔

閱讀全文 »

交換器(Exchange)的路由(Routing)功能

現在我們已經更正確的使用交換器功能,而非將訊息直接寫入佇列,為什麼需要這樣做呢?因為RabbitMQ交換器擁有路由功能,當訊息進入交換器時,可以透過種類來分配到不同的佇列裡,以官網的例子就是LOG處理機制。

LOG的重要程度可大致分為 Debug, Info, Warning, Error, Fatal.
Warning以上要分配到 Queue1
Debug與Info 等級則要放到 Queue2

這樣在宣告佇列時就可以綁定到該分配器,但指定不同QueneName, RouteKey. EX:

1
2
channel.QueueBind(queue: queueName, exchange: "direct_logs", routingKey: "INFO");
channel.QueueBind(queue: queueName, exchange: "direct_logs", routingKey: "WARNING");

以下會用publisher分別發送兩個訊息到交換器,並指定不同的RouteKEY

Publisher

宣告兩個訊息並指定RouteKey分別為”ERROR”與”INFO”

1
2
3
4
5
6
7
8
9
10
11
12
channel.ExchangeDeclare(exchange: "direct_logs", type: "direct");
var msg_error = $"This is Error msg.";
var msg_info = $"This is Info msg";

channel.BasicPublish(exchange: "direct_logs",
routingKey: "ERROR",
basicProperties: null,
body: Encoding.UTF8.GetBytes(msg_error));
channel.BasicPublish(exchange: "direct_logs",
routingKey: "INFO",
basicProperties: null,
body: Encoding.UTF8.GetBytes(msg_info));

Subscriber

閱讀全文 »

佇列的功能

當系統已經繁忙逐漸無法及時回應需求,或是需求本身需要一段時間處理,以及複雜的HTTP請求這些狀況都很適合搭配訊息佇列來做處理。
這邊用sleep來模擬處理很久的訊息。

Publisher (範例命名為Sender)

基本上與範例一的內容一樣,就不多著墨。

Consumer (範例命名為Receiver)

為了模擬處理很久的訊息,在收到訊息後將內容逐一字元顯示。

1
2
3
4
5
foreach (var i in message.ToCharArray())
{
Thread.Sleep(150);
Console.Write("{0}", i);
}

其他內容也與範例一是相同的,如果有不理解的可以回頭看第一篇文章。

為了更幫助理解,建議可以執行兩個 receiver.exe,再分別多次執行 sender.exe 這樣看以看多個訊息進入佇列後,每個 receiver 在繁忙中如何分配處理。

訊息處理確認機制(Acknowledgement)

閱讀全文 »

什麼是RabbitMQ

RabbitMQ是訊息的中介層,可以想像是一個幫你保管、處理的佇列,只要發布者(Publisher)將訊息寫入後,該訊息會被放入指定的佇列,等待接收者(Consumer)的拿取。
特性大概有以下幾種:

  • 由Erlang開發
  • 符合進階訊息佇列協定(AMQP)
  • 支援非常多種語言與平台
  • 訊息接收、處理的可靠性
  • 高度靈活的路由功能
  • 高可用性(Availability)
  • 內建監控與管理介面
  • 可建立集群,提昇資料安全與服務不中斷
  • 提供各種插件(plugin)靈活運用

細節會在日後的文章陸續揭露或探討,而安裝方法非常簡單,網路上也有很多範例就不在這邊贅述了。
本文所使用的程式語言是 .NET Framework C#

Hello RabbitMQ

如果是.net core使用者須先建立專案,這邊以console模式當範例,依序建立兩個專案並進入專案加入RabbitMQ.Client package

1
2
3
4
5
6
7
dotnet new console -n Sender
cd Sender/
dotnet add package RabbitMQ.Client
cd ..
dotnet new console -n Receiver
cd Receiver/
dotnet add package RabbitMQ.Client

撰寫Publisher (範例命名為Sender)

  1. 建立連線的物件,hostname目前都是在本機所以localhost即,UserName與Password則需要另外建立。
    若是剛安裝好,預設是guest/guest為唯一且admin帳號。
1
2
var factory = new ConnectionFactory()
{ HostName = "localhost", UserName = "admin", Password = "pass123" };
閱讀全文 »