为什么推荐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. Elasticsearch 索引生命周期管理 ILM 实战指南

    文章转载自:https://mp.weixin.qq.com/s/7VQd5sKt_PH56PFnCrUOHQ 1.什么是索引生命周期 在基于日志.指标.实时时间序列的大型系统中,集群的索引也具备类似 ...

  2. 如何在 Docker 之上使用 Elastic Stack 和 Kafka 可视化公共交通

    文章转载自:https://blog.csdn.net/UbuntuTouch/article/details/106498568 需要掌握的知识点: 1.使用docker-compose方式部署一套 ...

  3. Readsh中文版初始设置

    B站视频教程网址:https://space.bilibili.com/630285695/video 安装成功后,打开浏览器输入http://ip:5000如果出现如下画面,即告安装成功. 初始设置 ...

  4. 组合总和 II

    组合总和 II 题目介绍 给定一个候选人编号的集合 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合. candidates ...

  5. MySQL学习(1)---MySQL概述

    什么是数据库 概述 数据库(Database)是长期存储在计算机内有组织.大量.共享的数据集合.它可以供各种用户共享,具有最小冗余度和较高的数据独立性.数据库管理系统DBMS(Database Man ...

  6. DophineSheduler上下游任务之间动态传参案例及易错点总结

    ​   作者简介 ​ 淡丹 数仓开发工程师 5年数仓开发经验,目前主要负责百得利MOBY新车业务 二手车业务及售后服务业务系统数仓建设   业务需求 在ETL任务之间调度时,我们有的时候会需要将上游的 ...

  7. [题解] Atcoder ABC 213 H Stroll DP,分治FFT

    题目 令\(dp_{i,j}\)表示从点1到达点i,路径长度为j的方案数.转移为\(dp_{i,j}=\sum_{(i,v,w)\in E}dp_{v,j-w}p_{i,v,w}\). 显然只能从长度 ...

  8. Leetcode刷题笔记(双指针)

    1.何为双指针 双指针主要用来遍历数组,两个指针指向不同的元素,从而协同完成任务.我们也可以类比这个概念,推广到多个数组的多个指针. 若两个指针指向同一数组,遍历方向相同且不会相交,可以称之为滑动窗口 ...

  9. Linux命令全解

    strace 获取某个可执行文件执行过程中用到的所有系统调用 :strace -f g++ main.cpp &| vim 查看g++编译过程调用了哪些系统调用,通过管道符用vim接收 :%! ...

  10. POJ1185 [NOI2001] 炮兵阵地 (状压DP)

    又是一道有合法性检测的状压题. dp[i][j][k]表示第i行状态为j,i-1行状态为k时前i行放置的最大数量. 注意22行统计二进制数中1的个数时的巧妙方法. 1 #include<cstd ...