我开发了一个库,它实现了工作项的生产者/消费者模式.工作已经出列,并且每个出列的工作项都会出现一个单独的任务,其中包含失败和成功的延续.
任务继续在工作项完成(或失败)后重新排队.
整个库共享一个中心CancellationTokenSource,在应用程序关闭时触发.
我现在面临重大的内存泄漏.如果使用取消令牌作为参数创建任务,则任务似乎保留在内存中,直到触发取消源(并稍后处置).
这可以在此示例代码(VB.NET)中重现.主要任务是包装工作项的任务,继续任务将处理重新安排.
Dim oCancellationTokenSource As New CancellationTokenSource
Dim oToken As CancellationToken = oCancellationTokenSource.Token
Dim nActiveTasks As Integer = 0
Dim lBaseMemory As Long = GC.GetTotalMemory(True)
For iteration = 0 To 100 ' do this 101 times to see how much the memory increases
Dim lMemory As Long = GC.GetTotalMemory(True)
Console.WriteLine("Memory at iteration start: " & lMemory.ToString("N0"))
Console.WriteLine(" to baseline: " & (lMemory - lBaseMemory).ToString("N0"))
For i As Integer = 0 To 1000 ' 1001 iterations …Run Code Online (Sandbox Code Playgroud) .net vb.net memory-leaks task-parallel-library cancellation-token
我目前正在研究C#中使用CQRS和事件源的原型,并且在我对SQL数据库的预测中遇到了性能瓶颈.
我的第一个原型是使用Entity Framework 6构建的,代码优先.这个选择主要是为了开始,因为读取方将受益于LINQ.
每个(适用的)事件都由多个投影使用,这些投影可以创建或更新相应的实体.
这样的投影目前看起来像这样:
public async Task HandleAsync(ItemPlacedIntoStock @event)
{
var bookingList = new BookingList();
bookingList.Date = @event.Date;
bookingList.DeltaItemQuantity = @event.Quantity;
bookingList.IncomingItemQuantity = @event.Quantity;
bookingList.OutgoingItemQuantity = 0;
bookingList.Item = @event.Item;
bookingList.Location = @event.Location;
bookingList.Warehouse = @event.Warehouse;
using (var repository = new BookingListRepository())
{
repository.Add(bookingList);
await repository.Save();
}
}
Run Code Online (Sandbox Code Playgroud)
这不是很好的表现,很可能是因为我调用DbContext.SaveChanges()了这个IRepository.Save()方法.每个活动一个.
我接下来应该探索哪些选择?我不想花几天时间追逐那些可能只是稍微好一点的想法.
我目前看到以下选项:
我希望看到数百万个事件,因为我们计划采用大型遗留应用程序并以事件的形式迁移数据.新的预测也会经常添加,因此处理速度是一个实际问题.
基准:
更新的基准
TableAdapter(每次迭代时都是新的DataSet和新的TableAdapter):~2.500次插入/秒.没有使用投影管道进行测试,而是单独测试TableAdapter,SELECT插入后不插入:~3000插入/秒
TableAdapter10.84行的单线程ADO.NET …我正在研究CQRS / ES体系结构。我们将多个异步投影并行运行到读取存储中,因为某些投影可能比其他投影慢得多,并且我们希望与写入端保持更多同步,以实现更快的投影。
我正在尝试了解有关如何生成读取模型以及可能需要进行多少数据重复的方法。
让我们以带有物料的订单作为简化示例。一个订单可以有多个项目,每个项目都有一个名称。项目和订单是单独的汇总。
我可以尝试以更规范的方式保存读取的模型,在该模型中,我为每个项目创建实体或文档并订购,然后对其进行引用-或者我可能想以更规范化的方式在有订单的情况下保存它其中包含项目。
归一化
{
Id: Order1,
Items: [Item1, Item2]
}
{
Id: Item1,
Name: "Foosaver 9000"
}
{
Id: Item2,
Name: "Foosaver 7500"
}
Run Code Online (Sandbox Code Playgroud)
使用更规范的格式将允许单个投影处理影响/影响物品和订单的事件并更新相应的对象。这也意味着项目名称的任何更改都会影响所有订单。例如,客户可能会收到与相应发票不同的其他物品的交货单(显然,该模型可能不够好,并导致我们面临与非规范化相同的问题...)
非正规化
{
Id: Order1,
Items: [
{Id: Item1, Name: "Foosaver 9000"},
{Id: Item2, Name: "Foosaver 7500"},
]
}
Run Code Online (Sandbox Code Playgroud)
但是,反规范化将需要一些可以在其中查找当前相关数据的源(例如项目)。这意味着我要么必须传输事件中可能需要的所有信息,要么必须跟踪为非规范化而获取的数据。这也意味着我可能需要为每个投影执行一次操作(即,我可能需要一个非规范化的ItemForOrder以及一个非规范化的ItemForSomethingElse),它们都只包含每个非规范化实体或文档所需的最基本的属性(无论它们是什么时候)创建或修改)。
如果我要在读取存储中共享相同的物料,则最终可能会从不同的时间点混合物料定义,因为物料和订单的预测可能不会以相同的速度运行。在最坏的情况下,项目的投影可能尚未创建我需要为其属性来源的项目。
通常,在处理事件流中的关系时我有什么方法?
更新2016-06-17
目前,我正在通过针对每个非规范化读取模型及其相关数据运行单个投影来解决此问题。如果我有多个必须共享相同相关数据的读取模型,那么我可能会将它们放在同一投影中,以避免重复查找所需的相同相关数据。
这些相关的模型甚至可能已被标准化,优化,但是我必须访问它们。我的投影是唯一读取和写入它们的东西,因此我确切地知道如何读取它们。
// related data
public class Item
{
public Guid Id {get; set;}
public string Name {get; set;}
/* and whatever else …Run Code Online (Sandbox Code Playgroud) 我们目前的设置是
我们希望为客户(即第三方客户)提供访问受限(单独的声明集/子集)的 API。这些客户端大多是下载数据的非交互式脚本。
这意味着我们不能使用任何(偶尔)需要用户交互的流程。个人访问令牌,如在 github 中,或其他一些生成一次,需要长时间重用API 密钥或令牌。
长令牌生命周期不会是一个安全问题,因为令牌应该只允许访问少数只读 API 并且只允许访问该客户的数据 - 因此处理令牌的责任落在了客户身上。
客户应该能够根据他们的声明创建和撤销此类 API 访问令牌。一些用户可能只声称访问某些 API。
如果我们以后可以防止用户因为许可要求而对多个客户端重复使用相同的令牌,那将会很好,但这可能是一个全新的问题
我怎么能做到这一点?
我想通过自定义授权来做到这一点,类似于委托授权:用户使用应用程序,它调用 asp.net 核心 API,使用该自定义授权执行身份验证,将该令牌保留在某处(只是数据库中的一个普通表)仅限客户 api 的令牌?我不确定)并将其显示给用户 - 用户也可以稍后从存储中检索它。
我正在考虑通过我们的 API 进行“委托”身份验证,这样我们就不会将机密泄露到 Angular 应用程序中。
我认为我们应该能够通过该自定义授权获得长期访问令牌或至少刷新令牌。
我们想要一个过程,用户在我们的应用程序中生成一些东西(即通过我们的客户端),然后用户的第三方客户端可以使用这些东西来访问 API - 或者请求访问令牌然后访问 API。
我们希望此访问与用户相关联。这包括 - 残疾用户 - 锁定 - 特定索赔(例如租户)
这并不适合直接发布访问令牌的解决方案,因为即使用户被禁用或锁定,令牌仍将保持有效。这意味着我们不能使用自定义授权或IdentityServerTools直接发行代币。
因此,我们应该使用客户端凭据授权或类似的东西,因为这可能会产生新的、短期的访问令牌。
UserManager)假设写这样的资助足够安全和容易,我们应该能够涵盖我们需要的一切。当然,我可能完全忽略了一些东西:)
当谈到 Kendo 中的绑定行为时,似乎有一个相当奇特的设计决定。
我正在尝试将一个可为空的值绑定到一个下拉列表。如果(远程来源)值为空,则 Kendo 将生成对象以绑定到该值,例如,使用下拉列表的数据值字段/值。这使得保存修改后的视图模型非常不可靠,因为现在将传输整个对象而不是简单的数据类型。
示例:
Schedule.WeekNumber是null。从下拉菜单中选择一个值后
<select data-role="dropdownlist" name="scheduleWeekOfMonth"
data-bind="value:WeekNumber">
<option value="">Every week</option>
<option value="0">First week of month (1.-7.)</option>
<option value="1">Second week of month (8.-14.)</option>
<option value="2">Third week of month (15.-21.)</option>
<option value="3">Last week of month (22.+)</option>
</select>
Run Code Online (Sandbox Code Playgroud)
然后值 (JSON)Object {text: "First week of month (1.-7.)", value: "0"}代替"0"
有没有人对此有好的解决方案?- 除了在加载时替换视图模型的所有空值,例如:
function deNull(obj) {
if(obj !== null && typeof obj === "object") {
$.each(obj, function(index, value) {
if(value !== null && typeof value …Run Code Online (Sandbox Code Playgroud) 我在一个设置为ASP.NET MVC和WebApi应用程序的项目中使用OWIN cookie身份验证中间件(即我添加了OWIN).
偶尔,当我做了一些更改并开始调试时,我得到一个异常,这个异常发生在每个请求上好一分钟左右,直到网站突然工作,没有任何问题.我在我的本地IIS中托管应用程序.
System.NullReferenceException: Object reference not set to an instance of an object.
at FooWeb.Startup.<>c.<Configuration>b__0_3(CookieExceptionContext context) in C:\ws\Foo\Main\Main\FooWeb\Startup.cs:line 138
at Microsoft.Owin.Security.Cookies.CookieAuthenticationHandler.<ApplyResponseGrantAsync>d__f.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.Owin.Security.Infrastructure.AuthenticationHandler.<ApplyResponseCoreAsync>d__b.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.Owin.Security.Infrastructure.AuthenticationHandler.<ApplyResponseAsync>d__8.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task …Run Code Online (Sandbox Code Playgroud) 我有一个 WiX 设置,其中有
<MajorUpgrade Schedule="afterInstallInitialize"
DowngradeErrorMessage="A later version of [ProductName] is already installed. Setup will now exit." />
Run Code Online (Sandbox Code Playgroud)
如果升级过程中发生错误,安装程序将回滚并恢复以前安装的版本。但是,通过自定义操作创建的计划任务会丢失并且永远不会恢复。
我用于创建/删除/回滚任务的自定义操作是:
<!-- task scheduling -->
<CustomAction Id="CreateScheduledTask" Return="check" Directory="SystemFolder"
ExeCommand=""[SystemFolder]SCHTASKS.EXE" /Create /RU "[TASK_DOMAIN]\[TASK_USERNAME]" /RP [TASK_PASSWORD] /SC DAILY /TN "Maintenance" /TR "[\\]"[SERVICELOCATION]Maintenance.exe[\\]"" /ST [TASK_TIME]"
Execute= "deferred"/>
<!-- rollback in case something went wrong -->
<CustomAction Id="CreateScheduledTask_Rollback" Execute="rollback" Return="ignore" Directory="SystemFolder" ExeCommand=""[SystemFolder]SCHTASKS.EXE" /Delete /TN "Maintenance" /F" />
<!-- removal of task -->
<CustomAction Id="RemoveScheduledTask" Return="ignore" Directory="SystemFolder" ExeCommand=""[SystemFolder]SCHTASKS.EXE" /Delete /TN "Maintenance" /F" Execute= "immediate"/>
Run Code Online (Sandbox Code Playgroud)
其排队为 …
.net ×2
c# ×2
projection ×2
api-key ×1
asp.net-mvc ×1
cookies ×1
cqrs ×1
data-binding ×1
kendo-ui ×1
memory-leaks ×1
mvvm ×1
owin ×1
rdbms ×1
rollback ×1
vb.net ×1
wix ×1