为什么推荐Kestrel

网络框架千千万万,在dotnet平台,我们可以直接手撸Socket,也可以基于dotnetty来开发,或者选择某些第三方类似于dotnetty的网络库,为何我要推荐Kestrel呢?

1 使用框架

网络编程是简单的,简单到大概就 new Socket(),Send()发送数据,Receive()接收数据,这大概是初学者的大致感受。

网络编程是复杂的,让Send()和Receive()稳定工作,花了老夫一年时间,每让服务器的性能提高10%又各花老夫两年时间,这大概是手撸过Socket的大哥的感受。

网络编程是抽象的传输层加高效的缓冲区管理,我们需要把它提升到框架来,而不能停留在原始的Socket工具级别。这大概是我从dotnetty和kestrel里悟出的道理。

2 框架的支撑者

选择某个框架,咱首先要看看这个这个框架背后的支撑者的力量。Kestrel是asp.netcore的Server部分,如果asp.netcore说它是dotnet平台上第二出名的应用框架,那没其它框架敢说第一是自己。我们可以通过commits来查看有哪些大牛在孜孜不倦地维护kestrel,其中@JamesNK、@BrennanConroy、@davidfowl等世界级大牛一直很活跃。反观其它网络框架,只有少量的社区力量甚至作者单个人的力量在贡献。

3 Kestrel的影响

三流的框架在自诩,二流的框架在吸取新鲜技术的养分,一流的框架在推动相关领域技术前行。

3.1 推动System.Net.Socket

在dotnet core 2.0或以前,Kestrel使用Libuv取代dotnet的Socket来操作网络,因为彼时dotnet的Socket性能,要比Libuv要差一些,特别在unix上的表现。也正是因为asp.netcore的kestrel对Socket性能有强烈的需求,在2.1时runtime层开始对Socket的性能大力改进,Task和ValueTask的异步发送和接收内部实现融入了SocketAsyncEventArgs,Socket甚至为NetworkStream开了路灯,让Socket与Libuv的性能直接平级。

3.2 推动System.IO.Pipelines

Pipelines诞生于.NET Core团队为使Kestrel成为业内最快的Web服务器之一所做的工作。最初是Kestrel内部的一个实现细节,后来发展成为一个可重用的API,它在dotnet coreapp 2.1 中作为一流的 BCL API(System.IO.Pipelines)提供给所有 .NET 开发人员。

正确解析来自Stream或Socket的数据的工作其实非常复杂,沉长和复杂的代码让人难以阅读和维护。再加上要实现高性能这条要求的话,就让人更加吐血,而Pipelines旨在解决这种复杂性。

有关Pipelines的好,我就不班门弄斧了,这是@davidfowl写的Pipelines介绍

3.3 对普通开发者的影响

曾经一个小小SocketAwaitableEventArgs class,让多少开发者眼前一亮,惊叹无比。这不,现在已经不是最初实现了ICriticalNotifyCompletion接口了,转为实现了IValueTaskSource<SocketOperationResult>,大家慢慢品吧。

4 Kestrel的魅力

4.1 单应用层多传输层

支持一个应用监听多个端口,每个端口走不同传输层,最后到达同一个应用协议层。比如下面的配置,传输层分别是tcp和tls over tcp,应用层都是http,不管是哪种传输最终都是被我们的application层统一处理http,简称殊途同归。

"Kestrel": {
"Endpoints": {
"http": {
"Url": "http://localhost:5000"
},
"https": {
"Url": "https://localhost:5001"
}
},
"Certificates": {
"Default": {
"Path": "",
"Password": ""
}
}
}

4.2 单传输层多应用层

我们也可以使用某个监听端口对应的传输层,分支不同的路由来实现多个应用协议application。常见的比如kestrel使用websocket做传输层,应用协议层为mqtt或signalr等。

// Mqtt over WebSocket
app.MapConnectionHandler<MqttConnectionHandler>("/mqtt"); // SingalR over Websocket
app.MapHub<SingalRHub>("/signalr");

4.3 自定义应用层

我们这里说所的应用层协议,往往是我们在这层协议上构建了业务,而不拿它来做传输协议,而实际中,一种协议往往即可以做广义的传输协议,也可以直接做构建业务的应用层协议(典型的WebSocket,甚至http也可以做传输协议)。在asp.netcore中,SingalR就是典型的一个不太复杂的应用层协议(相对http),我们也可以基于kestrel来开发telnet over tcp的服务,telnet做为应用层,tcp做传输层。

public class TelnetConnectionHandler : ConnectionHandler
{
/// <summary>
/// 收到Telnet连接后
/// </summary>
/// <param name="connection"></param>
/// <returns></returns>
public override async Task OnConnectedAsync(ConnectionContext connection)
{
var input = connection.Transport.Input;
var output = connection.Transport.Output; // 从input解析telnet协议
...
}
}
public static class ListenOptionsExtensions
{
/// <summary>
/// 使用TelnetConnectionHandler
/// </summary>
/// <param name="listen"></param>
public static void UseTelnet(this ListenOptions listen)
{
listen.UseConnectionHandler<TelnetConnectionHandler>();
}
}
var section = context.Configuration.GetSection("Kestrel");
kestrel.Configure(section).Endpoint("Telnet", endpoint => endpoint.ListenOptions.UseTelnet());

4.4 增加传输层

假设我们需要telnet应用增加支持tls安全传输,我们可以再增加一个Telnets的EndPoint。在telnet协议之前插入https(实际准确是的叫tls)中间件。现在不管是未加密的telnet请求还是tls加密的telnet请求,我们的应用层TelnetConnectionHandler都能收到telnet请求内容。

var section = context.Configuration.GetSection("Kestrel");
kestrel.Configure(section).Endpoint("Telnets", endpoint => endpoint.ListenOptions.UseHttps().UseTelnet());

4.5 自定义传输层

在Stream设计模式里,往往需要开发TransportStream,其包装原始Stream且在自身的Read/Write方法里做必要的数据解码/编码操作,比如SslStream(Stream inner),向SSlStream写入[1,2,3,4]的数据,实际上是向inner Stream写入了[1,2,3,4]加密后的数据。

Kestrel的传输层是IDuplexPipe类型的抽象对象,我们可以把IDuplexPipe对象转换为Stream对象,然后与既有的Stream套娃模式结合,再把最后的Stream转为IDuplexPipe类型,替换到kestrel的连接对象的传输层。

这是一个高阶但不太常用的功能,想了解更多可以查看KestrelApp.Transforms这个项目示例。

5 如何学习Kesrel

为了大家能学习Kestrel,我在github上开源了一个kestrel开发综合示例项目。

喜欢拿代码说话的同学,可以直接食用;喜欢理论指导行动的同学,可以先慢慢看项目上的文档链接,然后再一步步慢慢深入。

项目地址: https://github.com/xljiulang/KestrelApp

为什么推荐Kestrel作为网络开发框架的更多相关文章

  1. Linux学习笔记——重点推荐的Linux网络在线学习资源

     首先非常感谢百度,感谢网络的搜索引擎技术,也非常感谢学习资源的贡献者和组织! 1:http://billie66.github.io/TLCL/book/zh/ 2:http://www.ha97. ...

  2. 转:Android开源项目推荐之「网络请求哪家强」 Android开源项目推荐之「网络请求哪家强」

    转载自https://zhuanlan.zhihu.com/p/21879931 1. 原则 本篇说的网络请求专指 http 请求,在选择一个框架之前,我个人有个习惯,就是我喜欢选择专注的库,其实在软 ...

  3. Android框架之网络开发框架Volley

    1. Volley简单介绍 我们平时在开发Android应用的时候不可避免地都须要用到网络技术.而多数情况下应用程序都会使用HTTP协议来发送和接收网络数据.Android系统中主要提供了两种方式来进 ...

  4. nodejs的精简型和全栈型开发框架介绍

    总体来说你可以将Node.js开发框架归结为两类: - 精简型框架 - 全栈型框架 下面我们就对这两种框架进行探讨. 精简型框架 精简型框架提供的是最基本的功能和APIs,这类框架本身就是被设计成用来 ...

  5. Android okHttp网络请求之Get/Post请求

    前言: 之前项目中一直使用的Xutils开源框架,从xutils 2.1.5版本使用到最近的xutils 3.0,使用起来也是蛮方便的,只不过最近想着完善一下app中使用的开源框架,由于Xutils里 ...

  6. iOS网络-03-NSURLSession与NSURLSessionTask

    简介 NSURLSession也能完成网络请求 NSURLConnection在iOS9中不推荐使用,NSURLSession是iOS9中推荐使用的网络请求方式 NSURLSession需要与NSUR ...

  7. muduo网络库使用心得

    上个月看了朋友推荐的mudo网络库,下完代码得知是国内同行的开源作品,甚是敬佩.下了mudo使用手冊和035版的代码看了下结构,感觉是一个比較成熟并且方便使用的网络库.本人手头也有自己的网络库,尽管不 ...

  8. UNIX网络编程 卷2:进程间通信

    这篇是计算机类的优质预售推荐>>>><UNIX网络编程 卷2:进程间通信(第2版)> UNIX和网络专家W. Richard Stevens的传世之作 编辑推荐 两 ...

  9. 最流行的Node.js应用开发框架简介

    最流行的Node.js应用开发框架简介 快速开发而又容易扩展,高性能且鲁棒性强.Node.js的出现让所有网络应用开发者的这些梦想成为现实.但是,有如其他新的开发语言技术一样,从头开始使用Node.j ...

  10. 当今最流行的Node.js应用开发框架简介

    快速开发而又容易扩展,高性能且鲁棒性强.Node.js的出现让所有网络应用开发者的这些梦想成为现实.但是,有如其他新的开发语言技术一样,从头开始使用Node.js的最基本功能来编写代码构建应用是一个非 ...

随机推荐

  1. Kubernetes 上部署应用-- 以Wordpress 为例

    用一个 Wordpress 示例来尽可能将前面的知识点串联起来,我们需要达到的目的是让 Wordpress 应用具有高可用.滚动更新的过程中不能中断服务.数据要持久化不能丢失.当应用负载太高的时候能够 ...

  2. K8S ingress控制器

    文章转载自: K8S ingress控制器 (一)https://blog.51cto.com/u_13760351/2728917 K8S ingress控制器 (二)https://blog.51 ...

  3. [题解] Topcoder 15279 SRM 761 Div 1 Level 3 SpanningSubgraphs DP,容斥

    题目 考虑DP.\(f(msk,i)\) 表示集合 \(msk(一定包含0号点)\) ,选了恰好i条边的连通方案数.转移用容斥,用这个点集内部所有连边方案减去不连通的.令\(|e_{msk}|\)表示 ...

  4. Flask 框架:运用Echarts绘制图形

    echarts是百度推出的一款开源的基于JavaScript的可视化图表库,该开发库目前发展非常不错,且支持各类图形的绘制可定制程度高,Echarts绘图库同样可以与Flask结合,前台使用echar ...

  5. count(*), count(1), count(列名)的区别

    1.从结果上来看 count(1)和count(*)之间没有区别,因为count(*)count(1)都不会去过滤空值,但count(列名)就有区别了,因为count(列名)会去过滤空值. 2.从执行 ...

  6. 从源码分析 MGR 的流控机制

    Group Replication 是一种 Shared-Nothing 的架构,每个节点都会保留一份数据. 虽然支持多点写入,但实际上系统的吞吐量是由处理能力最弱的那个节点决定的. 如果各个节点的处 ...

  7. Linux 下配置 hosts 并设置免密登录

    Linux 下配置 hosts 并设置免密登录 作者:Grey 原文地址: 博客园:Linux 下配置 hosts 并设置免密登录 CSDN:Linux 下配置 hosts 并设置免密登录 说明 实现 ...

  8. JSP中使用response对象实现定时跳转网页

    5秒后跳转到登录页面 <% response.setHeader("refresh","5;URL="login.jsp"); %>

  9. Silky微服务框架之服务引擎

    构建服务引擎 在注册Silky微服务应用一节中,我们了解到在ConfigureServices阶段,通过IServiceCollection的扩展方法AddSilkyServices<T> ...

  10. TCP 序列号和确认号是如何变化的?

    大家好,我是小林. 在网站上回答了很多人的问题,我发现很多人对 TCP 序列号和确认号的变化都是懵懵懂懂的,只知道三次握手和四次挥手过程中,ACK 报文中确认号要 +1,然后数据传输中 TCP 序列号 ...