日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

深入理解kestrel的应用

發(fā)布時(shí)間:2023/12/4 编程问答 45 豆豆
生活随笔 收集整理的這篇文章主要介紹了 深入理解kestrel的应用 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

1 前言

之所以寫本文章,是因?yàn)樵谖彝V咕S護(hù)多年前寫的NetworkSocket組件兩年多來,還是有一些開發(fā)者在關(guān)注這個(gè)項(xiàng)目,我希望有類似需求的開發(fā)者明白為什么要停止更新,可以使用什么更好的方式來替換(其實(shí)很大原因是我把時(shí)間花在開發(fā)WebApiClient上面了)。那時(shí).netcore還沒有生下來,asp.net除了蝸居在iis里處理http,其它什么也不能干,而NetworkSocket是這樣定義的:

NetworkSocket是一個(gè)以中間件(middleware)擴(kuò)展通訊協(xié)議,以插件(plug)擴(kuò)展服務(wù)器功能的支持SSL安全傳輸?shù)耐ㄓ嵖蚣?#xff1b;目前支持http、websocket、fast、flex策略與silverlight策略協(xié)議。

2 Kestrel是什么

談到asp.netcore,人們自然就想到它的默認(rèn)服務(wù)器kestrel,在很多場景中,人們甚至認(rèn)為kestrel等于Web服務(wù)器,或者說它只能處理http和http之上的東西。本文先在此下個(gè)定義:Kestrel是一款基于中間件來處理tcp連接的服務(wù)器,并內(nèi)置了http(包含websocket、SignalR)解析中間件。也就是說,我們完全可以給kestrel添加其它中間件,用來處理非http的連接的業(yè)務(wù)場景,讓kestrel使用一個(gè)端口支持多種協(xié)議或多協(xié)議一個(gè)端口一種協(xié)議的要求。

2.1 Kestrel的中間件是什么

在asp.netcore的Startup里,我們使用app.UseXXX的擴(kuò)展方法來應(yīng)用各種中間件,比如UseRouting、UseStaticFiles等等,它本質(zhì)上還是調(diào)用了IApplicationBuilder.Use(Func<RequestDelegate, RequestDelegate> middleware),也就說Func<RequestDelegate, RequestDelegate>就是一個(gè)中間件。

對(duì)應(yīng)的,在kestrel世界里,也有一個(gè)IConnectionBuilder.Use(Func<ConnectionDelegate, ConnectionDelegate> middleware),Func<ConnectionDelegate, ConnectionDelegate>就是kestrel的中間件,我們可以如下安裝kestrel的中間件:

kestrel.ListenAnyIP(port: 80, listen => {listen.Use(next => context =>{if(true){// 中間件1的邏輯}else{return next(context);}}).Use(next => context =>{if(true){// 中間件2的邏輯}else{return next(context);}}); });

值得注意的是,kestrel的最后一個(gè)中間處理者是http中間件,以上代碼,實(shí)際的kestrel已經(jīng)包含3種處理者(文章后部分有中間件的篇幅,然后就容易理解了),邏輯1、邏輯2和http解析,我們可以簡單理解為Startup的app對(duì)象,對(duì)應(yīng)kestrel的內(nèi)置的那個(gè)最后中間件。

2.2 Kestrel的ConnectionContext

在kestrel中間件里,最重要的對(duì)象就是ConnectionDelegate,它等同于Func<ConnectionContext,Task>,我們可以理解為它就是一個(gè)Hanlder,傳入連接上下文,剩下就是我們要干的工作了,而中間件是除了這個(gè)Handler之外,我們還能拿到一個(gè)叫next的Handler,我們可以選擇是否調(diào)用它,如果不調(diào)用,流程終止。

ConnectionContext是kestrel的一個(gè)Tcp連接抽象,其核心屬性是Transport,表示雙工傳輸層的操作對(duì)象,另外提供Abort()方法用于服務(wù)端主動(dòng)關(guān)閉連接。基于ConnectionContext,很容易實(shí)現(xiàn)一個(gè)自定義協(xié)議的tcp雙工通訊服務(wù)器,相比從Socket寫起,我們可能可以減少100倍代碼量,而得到的是更高性能的服務(wù)。

3 基于Kestrel的SignalR+Redis的推送服務(wù)

本實(shí)戰(zhàn)中,我們使用asp.netcore內(nèi)置的SignalR功能,外加自己實(shí)現(xiàn)的部分Redis協(xié)議(只簡單實(shí)現(xiàn)發(fā)布訂閱功能),來做一個(gè)消息從云端推送到客戶端的服務(wù),我們的服務(wù)對(duì)客戶端支持redis協(xié)議訂閱或Signal協(xié)議訂閱,同時(shí)我們提供redis+signalR+http三種協(xié)議接口給云端其它微服務(wù)來發(fā)布消息,發(fā)布者不用關(guān)心客戶端是什么協(xié)議,只需要選擇自己喜歡的協(xié)議的發(fā)布接口來調(diào)用發(fā)布。

3.1 協(xié)議與ConnectionContext的關(guān)系

在我們的這個(gè)應(yīng)用里,一個(gè)連接不允許同時(shí)使用SignalR和Redis并存協(xié)議,也就是說,一個(gè)連接在發(fā)起第一個(gè)請(qǐng)求里,就確定了它整個(gè)生命周期里的協(xié)議。所以,我們需要分析連接讀取到的第一個(gè)數(shù)據(jù)包,確定它是否為Redis協(xié)議,如果不是redis協(xié)議,我們要將ConnectionContext傳達(dá)到下一個(gè)中間件(即http中間件)。

3.2 使用Redis中間件

如下代碼,Use里面就是Redis中間件,里面的個(gè)協(xié)議分析邏輯:

kestrel.ListenAnyIP(options.Port, listen => {listen.Use(next => async context =>{if (await Protocol.IsRedisAsync(context)){logger.LogDebug($"{context.RemoteEndPoint} {nameof(ClientType.Redis)} 連接");await redis.HandleAsync(context);logger.LogDebug($"{context.RemoteEndPoint} {nameof(ClientType.Redis)} 斷開");}else{logger.LogDebug($"{context.RemoteEndPoint} {nameof(ClientType.SignalR)} 連接");await next(context);logger.LogDebug($"{context.RemoteEndPoint} {nameof(ClientType.SignalR)} 斷開");}}); });

Protocol類

/// <summary> /// 連接的協(xié)議判斷 /// </summary> public static class Protocol {/// <summary>/// 返回連接是否為redis協(xié)議/// </summary>/// <param name="connection"></param>/// <returns></returns>public static async Task<bool> IsRedisAsync(ConnectionContext connection){var result = await connection.Transport.Input.ReadAsync();var state = IsRedis(result);connection.Transport.Input.AdvanceTo(result.Buffer.Start);return state;}/// <summary>/// 返回?cái)?shù)據(jù)是否為redis協(xié)議/// 這里不必嚴(yán)格檢查,只要能區(qū)分是http還是redis就行/// </summary>/// <param name="result"></param>/// <returns></returns>private static bool IsRedis(ReadResult result){if (result.Buffer.IsEmpty){return false;}var span = result.Buffer.FirstSpan;return span.Length > 0 && span[0] == '*';} }

3.3 RedisConnectionHandler

在3.2代碼里,有一個(gè)await redis.HandleAsync(context);這個(gè)redis就是RedisConnectionHandler實(shí)例,它的功能是處理一個(gè)redis連接從建立成功之后到斷開的所有邏輯。

我們知道,Redis有好幾十個(gè)命令,單單是實(shí)現(xiàn)發(fā)布和訂閱功能,我們也要實(shí)現(xiàn)必要的8個(gè)命令。說到這里,我的腦海里又閃現(xiàn)出一個(gè)長長的switch(收到的cmd) case xxx的代碼了,我們甚至還需要在switch之前寫公共性的代碼,比如打印收到的cmd內(nèi)容,還需要在switch里特別強(qiáng)調(diào)default分支:我們不支持這個(gè)命令。。。

既然kestrel基于連接處理中間件,上層的asp.netcore也是基于請(qǐng)求處理中間件,我們完全也可以也依葫蘆畫瓢,造一個(gè)Redis命令中間件Builder,最后將所有Redis中間件串起來,Buid得一個(gè)Redis處理委托。

var builder = new PipelineBuilder<RedisContext>(appServices, context => {// 沒有handler來處理return context.Client.ResponseAsync(RedisResponse.Error("unsupported cmd")); }) .Use((context, next) => {this.logger.LogDebug(context.ToString());// 驗(yàn)證客戶端是否已授權(quán)return context.Cmd.Name != RedisCmdName.Auth && context.Client.IsAuthed == false? context.Client.ResponseAsync(RedisResponse.Error("need auth password")): next(); });// 添加各個(gè)cmd對(duì)應(yīng)的handler條件分支 appServices.GetServices<IRedisCmdHanler>().ForEach(item => builder.When(item.CanHandle, item.HandleAsync));this.handler = builder.Build();

在RedisConnectionHandler,每收一個(gè)Redis命令,將命令包裝為RedisContext,然后使用build出來的handler對(duì)象來處理這個(gè)RedisContext就行。剩下的工作,就是我們一個(gè)命令實(shí)現(xiàn)一個(gè)IRedisCmdHanler對(duì)象就行,邏輯完全分開。

IRedisCmdHanler接口:

/// <summary> /// 定義redis命令處理者 /// </summary> interface IRedisCmdHanler {/// <summary>/// 返回是否可以處理/// </summary>/// <param name="context"></param>/// <returns></returns>bool CanHandle(RedisContext context);/// <summary>/// 處理/// </summary>/// <param name="context"></param>/// <returns></returns>Task HandleAsync(RedisContext context); }

3.4 統(tǒng)一Redis和Signal客戶端操作接口

在Signal和Redis訂閱之后,我們將他們的連接包裝為統(tǒng)一接口的IClient對(duì)象,IClient提供PublishAsync()方法用于發(fā)布消息。

/// <summary> /// 定義客戶端的接口 /// </summary> public interface IClient {/// <summary>/// 獲取唯一標(biāo)識(shí)/// </summary>string Id { get; }/// <summary>/// 獲取連接時(shí)間/// </summary>DateTime ConnectedTime { get; }/// <summary>/// 獲取客戶端類型/// </summary>[JsonConverter(typeof(JsonStringEnumConverter))]ClientType ClientType { get; }/// <summary>/// 發(fā)送消息/// </summary>/// <param name="message"></param>/// <returns></returns>Task<bool> SendMessageAsync(Message message); }

3.5 IClient管理器

我們還需要維護(hù)一份單例的IClient管理器對(duì)象,用于維護(hù)正在訂閱的客戶端,在發(fā)布消息時(shí),從這個(gè)管理器里查找IClient,并調(diào)用SendMessageAsync()方法發(fā)布消息內(nèi)容。

3.6 SignalR部分

由于SignalR的內(nèi)容非常簡單,官方文檔細(xì)節(jié)齊全,這里將不作任何講解了。

4 總結(jié)

由于要講解的內(nèi)部比較多,篇幅和時(shí)間都有限,本文就只從思路上大概講解Kestrel在多協(xié)議連接的場景的使用方式。一句話,中間件的使用,使得這些場景變得簡單,那問題來了,什么是中間件,你理解了嗎?

總結(jié)

以上是生活随笔為你收集整理的深入理解kestrel的应用的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 欧洲亚洲女同hd | 日本午夜三级 | 三八激情网| 国产白浆一区二区 | 欧美黑人精品一区二区 | 国模精品一区二区三区 | 一级黄色片片 | 91爱爱.com | 日韩精品一卡 | 亚欧日韩| 婷婷色一区二区三区 | 亚洲一区视频网站 | 久久er99热精品一区二区介绍 | a级特黄视频 | 日韩夜色| 成人福利午夜 | 精品综合在线 | 亚洲无人区码一码二码三码 | 黄色av大全 | 奇米四色在线观看 | 日中文字幕 | 一区二区三区 中文字幕 | 婷婷影音 | 在线视频免费观看 | 99在线观看免费视频 | 特黄aaaaaa私密按摩 | 超碰五月天| 亚洲国产成人精品无码区99 | 轻轻色在线观看 | 亚洲专区一 | 波多野吉衣一二三区乱码 | 人妻在线一区 | 久久高潮视频 | 性色av一区二区三区在线观看 | 亚洲乱码国产乱码精品 | 国产夫妻性生活视频 | 亚洲精品国产精品国自产在线 | 欧美高清性xxxxhdvideosex | 欧美日韩经典 | 在线观看免费成人 | 欧美精品三级 | 免费日批视频 | 中文字幕乱码亚洲精品一区 | 美女网站污 | 国产精品日韩在线观看 | 亚洲av日韩av永久无码下载 | 少妇人妻一区 | 91精选视频 | 性奶老妇 视频 | 国偷自产av一区二区三区麻豆 | 国产aⅴ激情无码久久久无码 | 日韩国产精品久久 | 黄色在线播放 | 婷婷激情社区 | 久久婷婷婷 | av资源在线看 | 粉嫩精品久久99综合一区 | 亚洲最新在线视频 | 高清成人免费视频 | 亚洲天堂免费观看 | 99久久精品免费看国产四区 | 亚洲熟妇无码爱v在线观看 九色福利 | proumb性欧美在线观看 | 善良的公与媳hd中文字 | 东京av男人的天堂 | 伊人成人在线观看 | 久久夜色精品国产欧美乱极品 | 91在线视频播放 | 国产三级久久 | 亚洲无卡视频 | 天天干天天操天天爱 | 国模杨依粉嫩蝴蝶150p | 亚洲美女在线观看 | 激情欧美综合 | 少妇导航av | 传媒av在线 | 无码视频在线观看 | 人妻内射一区二区在线视频 | 免费的性爱视频 | 国产av天堂无码一区二区三区 | 99热8 | 性高潮久久久久 | 99视屏 | 一本色道久久综合狠狠躁 | 亚洲乱码国产乱码精品天美传媒 | 国产欧美不卡 | av在线资源网站 | 成人在线国产视频 | 亚洲经典一区 | 天堂在线视频tv | 妺妺窝人体色www在线小说 | 能看av的网址 | 日韩在线小视频 | 久久午夜鲁丝片午夜精品 | 久久免费国产 | 国产伦精品 | 精品国产一区二区三区四 | 操比视频网站 | 免费在线观看av的网站 |