XRPC的目標很是明確,就是給.net core平臺實現一個百萬級別的遠程方法調用RPC通信組件。它的設計理念和GRPC同樣,基於鏈接複用的機制實現高吞的性能;XRPC採用了HTTP2複用的思想,在協議設計上也相似文本和二進制相結合;在應用層面並沒使用消息而是基於接口代理的方式讓使用更簡便。git
XRPC採用了基於文本+二進制相結合的通信協議,頭以文本的方式表現主要是描述請求的位置和附加信息,這樣設計的好處就是在實現網關的時候只須要解釋頭部就能作很好的負載策略。二進制處理並無像GPRC同樣使 Protobuf,而是使用了在.net core平臺下相對更高效的組件MessagePack。github
在早期不少RPC是基於獨享連和鏈接池的方式進行構建,這樣的好處就是實現起來方便簡單,但這種設計就沒法把不一樣請求的請求混合到一個IO上。致使網絡IO隨併發消息的增加而增加,從而侷限了性能的發揮。XRPC的設計是儘可能在最少鏈接狀況發揮更高效的網絡處理能力,這樣就能夠把N個請求的數據複用在一個IO上,而從讓網絡利用率大大提高。api
但這種設計的缺點就是使用起來很是複雜,不過在.NET
提供async/await
支持下總體設計和應用就變得相對簡單和清晰不少了。如今模塊已經完成基礎功能版本,如下介紹一下如何使用。安全
組件如今只完成最基礎的功能,後面會引用Actor
的一些基礎元素,讓在併發業務處理數據上更高效。能夠經過Nuget
引用組件網絡
Install-Package BeetleX.XRPC -Version x
XRPC是經過接口的方式來描述服務,經過接口制定相關服務的邏輯,具體實現以下:併發
[Controller(typeof(IUserService))] public class UserService : IUserService { public Task<User> Add(string name, string email, string city, string remark) { User user = new User(); user.Name = name; user.EMail = email; user.City = city; user.Remark = remark; return Task.FromResult(user); } public Task<List<User>> List(int count) { List<User> result = new List<User>(); for (int i = 0; i < count; i++) { User user = new User(); user.ID = Guid.NewGuid().ToString("N"); user.City = "GuangZhou"; user.EMail = "Henryfan@msn.com"; user.Name = "henryfan"; user.Remark = "http://ikende.com"; result.Add(user); } return Task.FromResult(result); } public bool Login(string name, string pwd) { return (name == "admin" && pwd == "123456"); } public User Modify(User user) { return user; } public void Save() { Console.WriteLine("user saved"); } }
class Program { private static XRPCServer mXRPCServer; static void Main(string[] args) { mXRPCServer = new XRPCServer(); //mXRPCServer.ServerOptions.DefaultListen.Port = 80; mXRPCServer.Register(typeof(Program).Assembly); mXRPCServer.Open(); Console.Read(); } }
經過Register
註冊相關程序集,組件會把程序集中全部控制器加載到內存中,能夠經過日誌加載狀況:async
client = new XRPCClient("localhost", 9090); client.Connect(); client.NetError = (c, e) => { Console.WriteLine(e.Error.Message); }; client.TimeOut = 10000;
定義一個XRPCClient
對象來進行遠程訪問,對象默認最大鏈接數是2,也能夠根據本身實狀況進行調整,不建增長這樣會致使網絡IO也會增長影響總體性能。性能
var api = client.Create<IUserService>(); var lresult = await api.Login("admin", "123456"); Console.WriteLine(lresult); var result = await api.Add("henry", "henryfan@msn.com", "gz", "http://github.com"); Console.WriteLine($"{result.Name}\t{result.EMail}\t{result.City}\t{result.Remark}"); await api.Save(); Console.WriteLine("save completed"); User user = new User(); user.ID = Guid.NewGuid().ToString("N"); user.Name = "henry"; user.EMail = "henryfan@msn.com"; user.City = "GuangZhou"; user.Remark = "http://github.com/ikende"; result = await api.Modify(user); Console.WriteLine($"{result.Name}\t{result.EMail}\t{result.City}\t{result.Remark}"); var items = await api.List(5); foreach(var item in items) { Console.WriteLine($"{item.Name}\t{item.EMail}\t{item.City}\t{item.Remark}"); }
經過Create方法能夠建立接口代理,這個代理是線程安全的,正常狀況只須要建立一個靜態成員便可;建立接口後只須要調用相關方法便可完成遠程方法的調用。測試
組件設計的性能目標是百萬級別RPS的遠程方法調用,不過在一臺4核物機做爲服務測試並無達到這個目標,不過測試結果還算比較理想,在以上示例代碼Login方法,採用500個併發模擬的狀況RPS達到將近70萬。如下是不一樣方法在不一樣併發數下的測試結果。ui
詳細測試代碼:https://github.com/IKende/XRPC/tree/master/Samples/Performance