dotnetty 新的篇章- 开源
一、前言
因为微服务引擎依赖于dotnetty组件,很多协议都是针对于dotnetty 进行扩展,然后对于老版本https://github.com/azure/dotnetty 停止更新后,本人下载源码进行修改更新,并且大家要求独立仓库进行开源,所以今天整理了代码开源至https://github.com/microsurging/DotNetty, 也希望大家一起贡献代码,让dotnetty 生态更强大。
HttpFlv:http://demo.kayakiot.cn:281/httpflv.html (黑衣人)
HttpFlv:http://demo.kayakiot.cn:281/httpflv1.html (大红包)
HttpFlv:http://demo.kayakiot.cn:281/httpflv2.html (鹿鼎记)
rtmp:rtmp://demo.kayakiot.cn:76/live1/livestream2 (黑衣人)
rtmp:rtmp://demo.kayakiot.cn:76/live1/livestream3 (大红包)
rtmp:rtmp://demo.kayakiot.cn:76/live1/livestream4(鹿鼎记)
注:测试服务器带宽只有8MB, httpflv 缓冲做的没有rtmp好,然后httpflv卡就多刷新几次
凯亚 (Kayak) 是什么?
凯亚(Kayak)是基于.NET8.0软件环境下的surging微服务引擎进行开发的, 平台包含了微服务和物联网平台。支持异步和响应式编程开发,功能包含了物模型,设备,产品,网络组件的统一管理和微服务平台下的注册中心,服务路由,模块,中间服务等管理。还有多协议适配(TCP,MQTT,UDP,CoAP,HTTP,Grpc,websocket,rtmp,httpflv,webservice,等),通过灵活多样的配置适配能够接入不同厂家不同协议等设备。并且通过设备告警,消息通知,数据可视化等功能。能够让你能快速建立起微服务物联网平台系统。
凯亚物联网平台:http://demo.kayakiot.cn:3100(用户名:fanly 密码:123456)
链路跟踪Skywalking V8:http://117.72.121.2:8080/
surging 微服务引擎开源地址:https://github.com/fanliang11/surging(后面surging 会移动到microsurging进行维护)
二、ValueTask扩展支持
IValueTaskPromise:
public interface IValueTaskPromise: IPromise
{
bool IsVoid { get; } bool IsCompleted { get; } bool IsSuccess { get; } bool IsFaulted { get; } bool IsCanceled { get; } bool TryComplete(); void Complete(); bool TrySetException(Exception exception); bool TrySetException(IEnumerable<Exception> exceptions); void SetException(Exception exception); void SetException(IEnumerable<Exception> exceptions); bool TrySetCanceled(); void SetCanceled(); bool SetUncancellable(); IPromise Unvoid();
}
DefaultValueTaskPromise:
public class DefaultValueTaskPromise: IValueTaskPromise
{
private readonly CancellationToken _token;
#if NET
private readonly TaskCompletionSource _tcs;
#else
private readonly ManualResetValueTaskSource<object> _tcs;
#endif private int v_uncancellable = SharedConstants.False; public DefaultValueTaskPromise()
{
_token = CancellationToken.None;
#if NET
_tcs = new TaskCompletionSource();
#else
_tcs = new ManualResetValueTaskSource<object>();
#endif
} public DefaultValueTaskPromise(object state)
{
#if NET
_tcs = new TaskCompletionSource(state);
#else
_tcs = new ManualResetValueTaskSource<object>(state);
#endif
} public DefaultValueTaskPromise(CancellationToken cancellationToken)
{
_token= cancellationToken;
} public ValueTask ValueTask
{
[MethodImpl(InlineMethod.AggressiveOptimization)]
get => _tcs.AwaitVoid(_token);
} public bool IsVoid => false; public bool IsSuccess => ValueTask.IsCompletedSuccessfully; public bool IsCompleted => ValueTask.IsCompleted; public bool IsFaulted => ValueTask.IsFaulted; public bool IsCanceled => ValueTask.IsCanceled; public Task Task => ValueTask.AsTask(); public virtual bool TryComplete()
{
#if NET
return _tcs.TrySetResult();
#else
return _tcs.SetResult(0);
#endif
} public virtual void Complete()
{
#if NET
_tcs.SetResult();
#else
_tcs.SetResult(0);
#endif
}
public virtual void SetCanceled()
{
if (SharedConstants.False < (uint)Volatile.Read(ref v_uncancellable)) { return; }
_tcs.SetCanceled();
} public virtual void SetException(Exception exception)
{
if (exception is AggregateException aggregateException)
{
SetException(aggregateException.InnerExceptions);
return;
}
_tcs.SetException(exception);
} public virtual void SetException(IEnumerable<Exception> exceptions)
{
_tcs.SetException(exceptions.FirstOrDefault());
} public virtual bool TrySetCanceled()
{
if (SharedConstants.False < (uint)Volatile.Read(ref v_uncancellable)) { return false; }
_tcs.SetCanceled();
return true;
} public virtual bool TrySetException(Exception exception)
{
if (exception is AggregateException aggregateException)
{
return TrySetException(aggregateException.InnerExceptions);
}
_tcs.SetException(exception);
return true;
} public virtual bool TrySetException(IEnumerable<Exception> exceptions)
{
_tcs.SetException(exceptions.FirstOrDefault());
return true;
} public bool SetUncancellable()
{
if (SharedConstants.False >= (uint)Interlocked.CompareExchange(ref v_uncancellable, SharedConstants.True, SharedConstants.False))
{
return true;
}
return !IsCompleted;
} public override string ToString() => "TaskCompletionSource[status: " + ValueTask.AsTask().Status.ToString() + "]"; public IPromise Unvoid() => this; }
ManualResetValueTaskSource:
internal interface IStrongBox<T>
{
ref T Value { get; } bool RunContinuationsAsynchronously { get; set; }
} public enum ContinuationOptions
{
None, ForceDefaultTaskScheduler
} public class ManualResetValueTaskSource<T> : IStrongBox<ManualResetValueTaskSourceLogic<T>>, IValueTaskSource<T>, IValueTaskSource
{
private ManualResetValueTaskSourceLogic<T> _logic;
private readonly Action _cancellationCallback; [MethodImpl(MethodImplOptions.AggressiveInlining)]
public ManualResetValueTaskSource(ContinuationOptions options = ContinuationOptions.None)
{
_logic = new ManualResetValueTaskSourceLogic<T>(this, options,null);
_cancellationCallback = SetCanceled;
} public ManualResetValueTaskSource(object state, ContinuationOptions options = ContinuationOptions.None)
{
_logic = new ManualResetValueTaskSourceLogic<T>(this, options,state);
_cancellationCallback = SetCanceled;
} public short Version => _logic.Version; [MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool SetResult(T result)
{
lock (_cancellationCallback)
{
if (_logic.Completed)
{
return false;
} _logic.SetResult(result);
return true;
}
} [MethodImpl(MethodImplOptions.AggressiveInlining)]
public void SetException(Exception error)
{
if (Monitor.TryEnter(_cancellationCallback))
{
if (_logic.Completed)
{
Monitor.Exit(_cancellationCallback);
return;
} _logic.SetException(error);
Monitor.Exit(_cancellationCallback);
}
} public void SetCanceled() => SetException(new TaskCanceledException()); public T GetResult(short token) => _logic.GetResult(token); void IValueTaskSource.GetResult(short token) => _logic.GetResult(token); public ValueTaskSourceStatus GetStatus(short token) => _logic.GetStatus(token); public bool RunContinuationsAsynchronously { get; set; } = true; public void OnCompleted(Action<object> continuation, object state, short token, ValueTaskSourceOnCompletedFlags flags) => _logic.OnCompleted(continuation, state, token, flags); ref ManualResetValueTaskSourceLogic<T> IStrongBox<ManualResetValueTaskSourceLogic<T>>.Value => ref _logic; [MethodImpl(MethodImplOptions.AggressiveInlining)]
public ValueTask<T> AwaitValue(CancellationToken cancellation)
{
CancellationTokenRegistration? registration = cancellation == CancellationToken.None
? (CancellationTokenRegistration?)null
: cancellation.Register(_cancellationCallback);
return _logic.AwaitValue(this, registration);
} public ValueTask AwaitVoid(CancellationToken cancellation)
{
CancellationTokenRegistration? registration = cancellation == CancellationToken.None
? (CancellationTokenRegistration?)null
: cancellation.Register(_cancellationCallback);
return _logic.AwaitVoid(this, registration);
} public void Reset() => _logic.Reset();
} internal struct ManualResetValueTaskSourceLogic<TResult>
{
private static readonly Action<object> s_sentinel = s => throw new InvalidOperationException(); private readonly IStrongBox<ManualResetValueTaskSourceLogic<TResult>> _parent;
private readonly ContinuationOptions _options;
private Action<object> _continuation;
private object _continuationState;
private object _capturedContext;
private ExecutionContext _executionContext;
private bool _completed;
private TResult _result;
private ExceptionDispatchInfo _error;
private CancellationTokenRegistration? _registration; public ManualResetValueTaskSourceLogic(IStrongBox<ManualResetValueTaskSourceLogic<TResult>> parent, ContinuationOptions options,object state)
{
_parent = parent ?? throw new ArgumentNullException(nameof(parent));
_options = options;
_continuation = null;
_continuationState = null;
_capturedContext = null;
_executionContext = null;
_completed = state != null;
_result =state==null? default(TResult): (TResult)state;
_error = null;
Version = 0;
_registration = null;
} public short Version { get; private set; } public bool Completed => _completed; private void ValidateToken(short token)
{
if (token != Version)
{
throw new InvalidOperationException();
}
} public ValueTaskSourceStatus GetStatus(short token)
{
// ValidateToken(token); return
!_completed ? ValueTaskSourceStatus.Pending :
_error == null ? ValueTaskSourceStatus.Succeeded :
_error.SourceException is OperationCanceledException ? ValueTaskSourceStatus.Canceled :
ValueTaskSourceStatus.Faulted;
} public TResult GetResult(short token)
{
// ValidateToken(token); if (!_completed)
{
return _result;
} TResult result = _result;
ExceptionDispatchInfo error = _error;
Reset(); error?.Throw();
return result;
} public void Reset()
{
Version++; _registration?.Dispose(); _completed = false;
_continuation = null;
_continuationState = null;
_result = default(TResult);
_error = null;
_executionContext = null;
_capturedContext = null;
_registration = null;
} public void OnCompleted(Action<object> continuation, object state, short token, ValueTaskSourceOnCompletedFlags flags)
{
if (continuation == null)
{
throw new ArgumentNullException(nameof(continuation));
} ValidateToken(token); if ((flags & ValueTaskSourceOnCompletedFlags.FlowExecutionContext) != 0)
{
_executionContext = ExecutionContext.Capture();
} if ((flags & ValueTaskSourceOnCompletedFlags.UseSchedulingContext) != 0)
{
SynchronizationContext sc = SynchronizationContext.Current;
if (sc != null && sc.GetType() != typeof(SynchronizationContext))
{
_capturedContext = sc;
}
else
{
TaskScheduler ts = TaskScheduler.Current;
if (ts != TaskScheduler.Default)
{
_capturedContext = ts;
}
}
} _continuationState = state;
if (Interlocked.CompareExchange(ref _continuation, continuation, null) != null)
{
_executionContext = null; object cc = _capturedContext;
_capturedContext = null; switch (cc)
{
case null:
Task.Factory.StartNew(continuation, state, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
break; case SynchronizationContext sc:
sc.Post(s =>
{
var tuple = (Tuple<Action<object>, object>)s;
tuple.Item1(tuple.Item2);
}, Tuple.Create(continuation, state));
break; case TaskScheduler ts:
Task.Factory.StartNew(continuation, state, CancellationToken.None, TaskCreationOptions.DenyChildAttach, ts);
break;
}
}
} public void SetResult(TResult result)
{
_result = result;
SignalCompletion();
} [MethodImpl(MethodImplOptions.AggressiveInlining)]
public void SetException(Exception error)
{
_error = ExceptionDispatchInfo.Capture(error);
SignalCompletion();
} private void SignalCompletion()
{
if (_completed)
{
throw new InvalidOperationException("Double completion of completion source is prohibited");
} _completed = true; if (Interlocked.CompareExchange(ref _continuation, s_sentinel, null) != null)
{
if (_executionContext != null)
{
ExecutionContext.Run(
_executionContext,
s => ((IStrongBox<ManualResetValueTaskSourceLogic<TResult>>)s).Value.InvokeContinuation(),
_parent ?? throw new InvalidOperationException());
}
else
{
InvokeContinuation();
}
}
} private void InvokeContinuation()
{
object cc = _capturedContext;
_capturedContext = null; if (_options == ContinuationOptions.ForceDefaultTaskScheduler)
{
cc = TaskScheduler.Default;
} switch (cc)
{
case null:
if (_parent.RunContinuationsAsynchronously)
{
var c = _continuation;
if (_executionContext != null)
{
ThreadPool.QueueUserWorkItem(s => c(s), _continuationState);
}
else
{
ThreadPool.UnsafeQueueUserWorkItem(s => c(s), _continuationState);
}
}
else
{
_continuation(_continuationState);
}
break; case SynchronizationContext sc:
sc.Post(s =>
{
ref ManualResetValueTaskSourceLogic<TResult> logicRef = ref ((IStrongBox<ManualResetValueTaskSourceLogic<TResult>>)s).Value;
logicRef._continuation(logicRef._continuationState);
}, _parent ?? throw new InvalidOperationException());
break; case TaskScheduler ts:
Task.Factory.StartNew(_continuation, _continuationState, CancellationToken.None, TaskCreationOptions.DenyChildAttach, ts);
break;
}
} public ValueTask<T> AwaitValue<T>(IValueTaskSource<T> source, CancellationTokenRegistration? registration)
{
_registration = registration;
return new ValueTask<T>(source, Version);
} public ValueTask AwaitVoid(IValueTaskSource source, CancellationTokenRegistration? registration)
{
_registration = registration;
return new ValueTask(source, Version);
}
}
然后把DefaultPromise 替换成DefaultValueTaskPromise,如下图所示

三、扩展支持rtmp编解码
如下图所示 :

四、demo展示
开启了三个通道进行推流,cpu,内存都比较稳定

在凯亚物联网平台你也可以创建rtmp组件

视频中心

dotnetty 新的篇章- 开源的更多相关文章
- 「newbee-mall新蜂商城开源啦」GitHub 上最热门的 Spring Boot 项目,我也要做一次靓仔!
没有一个冬天不可逾越,也没有一个春天不会到来. 介绍一下新蜂商城的近况,同时,新蜂商城 Vue 版本目前也在开发中,在这篇文章里我也向大家公布一下新蜂商城 Vue 版本的开发进度,和大家同步一下,在不 ...
- 「newbee-mall新蜂商城开源啦」 前后端分离的 Vue 版本即将开源
新蜂商城 Vue 版本 2019 年 10 月份我在 GitHub 开源仓库中上传了新蜂商城项目的所有源码,至今已经有小半年的时间了,感兴趣的可以去了解一下这个 Spring Boot 技术栈开发的商 ...
- 「newbee-mall新蜂商城开源啦」 页面优化,最新版 wangEditor 富文本编辑器整合案例
大家比较关心的新蜂商城 Vue3 版本目前已经开发了大部分内容,相信很快就能够开源出来让大家尝鲜了,先让大家看看当前的开发进度: 开源仓库地址为 https://github.com/newbee-l ...
- 新数据革命: 开源C#图形化爬虫引擎Hawk5发布
https://ferventdesert.github.io/Hawk/ Hawk是一款由沙漠之鹰历时五年个人业余时间开发的,开源图形化爬虫和数据清洗工具,GitHub Star超过2k+,前几代版 ...
- 新发布 | 微软开源之路最新进展:FreeBSD落地由世纪互联营运的Microsoft Azure
微软和开源,是近几年业界孜孜不倦的讨论话题,微软也在开源之路越走越宽.最近与 FreeBSD 基金更紧密的合作踏出了微软在开源之路上的又一大步. 自2012年开始,微软在 FreeBSD 与其虚拟化平 ...
- 「newbee-mall新蜂商城开源啦」1000 Star Get !仓库Star数破千!记录一下
新蜂商城已经开源了 3 个多月左右的时间,在 2019 年的年末,仓库的 Star 数量冲破了 1000,整理本篇文章的时间是 2020 年 1 月 12 日,目前的 Star 数量是 1180 左右 ...
- 新的篇章--Python
这周已经开始Python的学习了,感觉Python类似于Powershell, 但又有不同点.在此总结一下新学到的资料: 简单的使用变量的方法: name= input("input you ...
- DotNetty 版 mqtt 开源客户端 (MqttFx)
一.DotNetty背景介绍 某天发现 dotnet 是个好东西,就找了个项目来练练手.于是有了本文的 Mqtt 客户端 (github: MqttFx ) DotNetty是微软的Azure ...
- 【开源】OSharp框架解说系列(1):总体设计及系列导航
系列文章导航 [开源]OSharp框架解说系列(1):总体设计 [开源]OSharp框架解说系列(2.1):EasyUI的后台界面搭建及极致重构 [开源]OSharp框架解说系列(2.2):EasyU ...
- Google FlatBuffers——开源、跨平台的新一代序列化工具
前段时间刚试用了一个序列化工具cereal,请看cereal:C++实现的开源序列化库,打算再总结下我对google proto buf序列化库的使用呢, 结果还没动手,大Google又出了一个新的. ...
随机推荐
- [python] 使用Python实现Markdown文档格式转换
本文主要介绍如何利用Python中的MarkItDown库将多种文件高效转换为Markdown文本,以及如何使用Python-Markdown库将Markdown文本转换为HTML(超文本标记语言)文 ...
- [源码系列:手写spring] IOC第十节:bean的初始化和销毁方法
内容介绍 在Spring框架中,你可以使用以下几种方法定义bean的初始化和销毁: 使用注解方式: @PostConstruct:在bean的方法上添加@PostConstruct注解,该方法将在be ...
- 如何查看 linux 发行版本
以 debian 10 buster 为例 有时候我们需要知道当前正在使用的 linux 的发行版本信息...可以通过下面几种方式来查看 使用 lsb_release 命令查看 lsb_release ...
- GStreamer开发笔记(一):GStreamer介绍,在windows平台部署安装,打开usb摄像头对比测试
前言 当前GStreamer是开源的多媒体框架,其适配后可以支持板卡的硬编码.硬解码,还提供RTSP服务器等功能,降低了音视频开发的门槛(转移到gstreamer配置和开发上了,但是跨平台),瑞芯 ...
- jmeter使用json断言校验返回结果
jmeter断言有好几种方式,本案讲json断言 http请求返回数据的格式有json格式,如下图,比如需要验证"ShipperRealName"参数的值 步骤如下: 第一步,选中 ...
- 应对海量数据挑战,如何基于Euro NCAP标准开展高效智驾测试与评估?
一.前言 随着自动驾驶技术的快速发展,庞大的测试数据和复杂的场景需求为性能与安全评估带来了巨大挑战.如何高效管理海量数据.挖掘关键场景,并满足以Euro NCAP(European New Car A ...
- Java 中的 CMS 和 G1 垃圾收集器如何维持并发的正确性?
Java 中的 CMS 和 G1 垃圾收集器如何维持并发的正确性? CMS(Concurrent Mark-Sweep)和 G1(Garbage-First)垃圾收集器是两种低延迟的垃圾回收器,它们通 ...
- Visual Studio 2022 划词翻译插件!该插件可以方便地翻译变量名、类名、方法名等单词,帮助您更轻松地理解和使用代码。
EnTranslate一款简单的划词翻译插件 简介 支持划词翻译(鼠标悬浮到单词上方将自动翻译) 支持播放单词发音 支持调用在线接口翻译 强大的单词拆分能力: 支持驼峰, 下划线形式等各种单词拆分 丰 ...
- markdown文本编辑器--核心功能(解析和渲染)
开源项目地址 GitHub 开源地址(YtyMark-java) 欢迎提交 PR.Issue.Star ️! 1. 简述 YtyMark-java项目分为两大模块: UI界面(ytyedit-mark ...
- [笔记]通过命令行连接MySQL数据库服务器的几种方式总结如下
通过命令行连接MySQL数据库服务器的几种方式总结如下: 1.连接本地数据库,用户名为"root",密码"123456"(注意:"-p"和& ...