Apache Ignite.NET 2.8的新功能

Apache Ignite.NET 2.8的新功能
瘦客戶端和分區感知
從一開始,Ignite就支持客戶端和服務端連接模式。不過即使客戶端模式不存儲數據也不執行計算,它仍然相對“笨重”,啓動Ignite.NET客戶端節點需要一個嵌入式的JVM環境,可能至少需要一秒鐘,並且消耗幾兆字節的內存。

在某些場景中,例如短期在線應用、低功耗客戶端主機、命令行工具等,可能不希望這樣的架構。因此Ignite從2.4版本開始,新增了輕量級的瘦客戶端協議來處理這些場景,下面是簡單的比較:

胖客戶端 瘦客戶端
啓動時間 1300 ms 15 ms
內存佔用 40 MB (.NET + Java) 70 KB
是否需要 Java 是 否
Ignite.NET瘦客戶端通過Ignition.StartClient()啓動,並提供一組和胖客戶端類似的API。根接口是分開的(IIgnite-> IIgniteClient,ICache-> ICacheClient),但是方法的命名方式相同,並且大多數代碼可以輕鬆地來回切換。

瘦客戶端協議是開放、可擴展並且文檔化的,這樣也爲其他語言(例如Python、JavaScript和PHP)的客戶端鋪平了道路。

分區感知
瘦客戶端的初始實現使用接入指定服務端節點的單個連接來執行所有的操作。大家都知道Ignite在集羣節點之間平均分配緩存數據,當瘦客戶端連接到節點A,但請求的數據在節點B上時,則必須從A到B發出另一個網絡請求,這樣並不高效。

Ignite從2.8版本開始,引入了瘦客戶端分區感知功能:瘦客戶端可以接入所有服務端節點,確定給定鍵的主節點,並將請求直接路由到該節點,從而避免了額外的網絡負載。這種路由非常快,它通過鍵哈希值的一些基本數學運算,就可以根據已知的分區分佈確定目標節點。通過IgniteClientConfiguration.EnablePartitionAwareness = true打開/關閉分區感知後,cache.Get操作的性能測試結果如下:

Method Mean Error StdDev
Get 90.73 us 2.114 us 5.892 us
GetPartitionAware 31.56 us 0.618 us 1.234 us

具體測試中,集羣拓撲、網絡速度和緩存數據量可能有所不同,測試結果可能會不一樣,但改進幅度是很大的。

故障轉移
瘦客戶端多節點連接還意味着故障轉移的能力:如果一個或多個服務端節點發生故障,則客戶端會自動切換到其他連接。

跨平臺支持:.NET Core、Linux、macOS
Ignite從2.4版本開始引入了.NET Core 2.x支持,最終放棄了和Windows相關的C++部分,並切換到JNI層的純.NET實現,從而使Ignite.NET應用可以在Linux和macOS上運行。

Ignite在2.8版本中新增了官方的.NET Core 3.x支持,並且可以在該框架支持的任何操作系統上以任何模式運行:服務端、客戶端、瘦客戶端。

Ignite改進了NuGet軟件包中處理jar文件的方式,使用MSBuild.targets文件替換了post_build腳本,該文件更可靠,跨平臺,並且可以通過dotnet build以及dotnet publish處理:.jar文件會被自動複製到構建和發佈目錄,從而生成一個獨立的軟件包。

注意最低系統要求仍然相同:.NET 4.0和Visual Studio2010,Ignite會保證主要版本(2.x)內的向後兼容性。但是在即將推出的Ignite 3.x中將切換到.NET Standard 2.0。

LINQ:Conditional和批量更新
SQL的UPDATE .. WHERE ..或DELETE .. WHERE ..在ORM和LINQ中通常無法實現。Ignite最終使用.Where()來獲取數據,然後一個一個更新,這個方案不是很理想,並且也不夠優雅。

假設要凍結所有一年以上未使用我們網站的用戶:

ICacheClient cache = client.GetCache("person");

var threshold = DateTime.UtcNow.AddYears(-1);

IQueryable> inactiveUsers = cache.AsCacheQueryable()

.Where(entry => entry.Value.LastActivityDate < threshold);

foreach (var entry in inactiveUsers)
{

entry.Value.IsDeactivated = true;
cache[entry.Key] = entry.Value;

}
這個代碼會將匹配的數據加載到本地節點,浪費內存並給網絡造成了壓力,這也違背了Ignite並置處理的原則:即將代碼發到數據所在處,而不是將數據拉到代碼所在處。

解決方法是使用SQL代替:

cache.Query(new SqlFieldsQuery(

"UPDATE person SET IsDeactivated = true WHERE LastActivityDate < ?", threshold));

簡單、簡潔、高效:Ignite會將查詢發送到所有節點,並對每個緩存數據在本地執行更新,從而避免了節點之間的任何數據移動。但是開發者不想要C#中的SQL,而是想要LINQ,因爲它經過了編譯器檢查,並且由於IDE的高效而更易於讀寫。

Ignite在2.5中通過LINQ引入了DML更新(除了Ignite2.1中的刪除操作):

cache.AsCacheQueryable()

.Where(entry => entry.Value.LastActivityDate < threshold)
.UpdateAll(d => d.Set(person => person.IsDeactivated, true));

它將效率和LINQ的優點結合起來,轉換爲與上面相同的SQL查詢。

動態服務代理
IServices.GetDynamicServiceProxy()是一個返回dynamic實例的新API,這樣就無需事先創建接口即可調用任意服務,例如:

interface ISomeService
{

int GetId(string data);

}
...
ISomeService proxy = ignite.GetServices().GetServiceProxy("someService");
var id = proxy.GetId("foo");
可以替換爲:

dynamic proxy = ignite.GetServices().GetDynamicServiceProxy("someService");
var id = proxy.GetId("foo");
這在POC、調用Java服務等許多場景中都很有用。

後續甚至還可以通過字符串名字調用服務的方法:

var methodName = "foo";
var proxy = (DynamicObject) ignite.GetServices().GetDynamicServiceProxy("someService");
proxy.TryInvokeMember(new SimpleBinder(methodName), new object[0], out var result);
總結
今後,瘦客戶端協議及其各種語言的實現是Apache Ignite社區的主要方向之一,其中分區感知是一個重要的里程碑。下一步是自動服務端節點發現,這樣就不必手動提供端點列表。在即將發佈的版本中,還會將計算、服務、事務(已在Java瘦客戶端中提供)和其他API添加到瘦客戶端,瘦客戶端的功能將變得更爲強大。

原文地址https://my.oschina.net/liyuj/blog/3190945

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章