kitlau
kitlau

kitlau's blog

All Posts in 2023


你可能正在写内存泄漏的 .NET 代码!

本篇博客讨论了.NET代码中的内存泄漏问题,主要包括七个方面。首先,定义了内存泄漏,即应用程序不再需要的对象仍然被其他对象引用,阻止垃圾收集器(GC)回收它们的内存。然后,通过实例代码详细介绍了匿名方法捕获类成员、事件的生命周期、使用静态变量、使用内存缓存、不进行Dispose处理以及错误使用unsafe或其他直接操作内存的方法等可能导致内存泄漏的场景,并给出了相应的解决方案。此外,博客还强调了在使用可能导致内存泄漏的编程技术时,必须清楚自己在做什么,避免不必要的内存泄漏问题。你是否也曾在.NET编程中遇到过这些问题?你又是如何解决的呢?--GPT 4

.NET

5 分钟 .NET 单元测试极简入门

本篇博客文章向我们介绍了如何在.NET环境中进行单元测试的极简入门。文章首先介绍了单元测试的基本概念和其重要性,然后详细展示了如何使用xUnit, Fluent Assertions, NSubstitute等工具进行单元测试的编写。文章以一个实际的例子,演示了如何编写测试方法,如何进行Arrange、Act和Assert,如何使用模拟对象和如何进行断言。文章还介绍了如何运行单元测试,并展示了测试结果。文章最后总结了单元测试的核心内容,并预告了下一篇文章将会讲解如何利用单元测试重构旧的垃圾代码。阅读这篇文章,你是否对.NET单元测试有了新的认识?你是否已经迫不及待地想要尝试编写你的第一个单元测试了?--GPT 4

.NET Test

借 Moq 事件谈一谈单元测试的重要性

这篇博客主要讨论了.NET最著名的单元测试Mock库Moq的一个争议性功能,以及单元测试的重要性。Moq的这个功能会在用户构建使用了Moq的项目时扫描用户本地的git配置,获取用户的电子邮件地址并发送到Azure的某个服务上以检查用户是否是Sponsor。这个功能在.NET社区引起了广泛的讨论,有人谴责这个行为,有人维护Moq的原作者。作者指出,这个事件在国内社区并没有引起广泛的讨论,可能是因为国内的中小公司一般没有写单元测试的习惯。作者强调,单元测试是由开发人员来写的,不应该依赖物理上的数据库。单元测试可以提高代码的质量,减少错误,增加可读性,方便重构,提高开发效率等。相反,不写单元测试会对代码可维护性,项目的健康性,未来新需求的开发等,带来很大的破坏。希望国内的公司和开发者都能更重视单元测试。你认为单元测试的重要性被低估了吗?你的公司有写单元测试的习惯吗?--GPT 4

.NET Test

如何 3 分钟搭建图片转文本工具

这篇博客详细介绍了如何在3分钟内搭建一个图片转文本工具。首先,作者选择了Laf,一个提供海外和大陆服务的平台,并创建了一个Laf应用。接着,作者创建了一个云函数,并设置了HuggingFace Access Token作为环境变量。在云函数中,作者使用JavaScript调用HuggingFace的API,实现了图片转文本的功能。作者还展示了如何调试云函数,并发布到Laf平台。最后,作者使用云函数返回的前端代码字符串,创建了一个简单的前端来实现图片转文本的功能。这个工具可以识别图片并将其转化为文字,如果你需要,也可以接入翻译接口,将识别结果翻译为中文。这篇文章详细而直观地展示了如何创建一个简单的图片转文本工具,你是否也想尝试一下呢?--GPT 4

AI

如何使用 Optional 模式解决 C# 中的烦人的空引用问题

这篇博客文章主要探讨了如何使用 Optional 模式解决 C# 中的空引用问题。首先,文章指出空引用异常是编程中常见的问题,常规的处理方法是在出错的代码位置添加判断,然后修复。然后,文章引入了 C# 中新引入的可空引用类型特性,但这个特性也带来了新的问题,如代码中充满了各种 null check 和 null guard。因此,文章提出了使用 Optional 模式来解决这个问题。Optional 模式提供了一种优雅的方式来处理可空值,避免了使用 null 值。文章还介绍了如何实现 Optional 模式,并提供了相关的代码和使用示例。最后,文章比较了 Nullable 和 Optional 模式,认为它们都是不错的解决空引用的方案,但选择哪种方案需要根据项目的大小和参与项目的成员等因素来决定。那么,你会选择哪种方式来解决空引用问题呢?--GPT 4

C#

Linq 和 lambda 的区别是什么?

本篇博客探讨了LINQ和lambda表达式的关系和区别。首先,LINQ(Language-Integrated Query)是一个库,包含一组可以使用lambda表达式的扩展方法,例如Where。文章通过代码示例详细解释了如何使用LINQ进行查询。其次,lambda表达式是一种更简单的构造匿名委托的方法,也被称为语法糖。它们经常在使用方法语法的LINQ中出现,这可能是人们常常把它们混淆的原因。文章再次通过代码示例解释了如何使用lambda表达式。最后,文章总结了lambda表达式实际上是一种比匿名方法更简单的委托创建方式,LINQ则可以通过表达式树把C#的查询语句转换成其他形式的查询语句,例如SQL语句。文章最后引用了一些相关的博客,供读者深入学习。那么,你是否清楚了LINQ和lambda表达式的区别呢?是否理解了它们各自的作用和用途呢?--GPT 4

C#

一幅漫画解释 .NET 垃圾收集(GC)原理

这篇博客主要讨论了.NET的垃圾收集(GC)原理。作者首先提到了许多普通dotnet开发者对dotnet的一些基础知识并不了解,这对他们的技术路线职业发展不利。在这种背景下,性能优化,尤其是从减少GC压力入手,成为了一个值得学习的点。作者随后翻译了一幅来源于Redgate的漫画,该漫画简单而直观地解释了dotnet GC的工作原理。同时,作者也提到了在dotnet 5中,GC新增了新的分代POH,但没有深入讨论。关于大对象堆(LOH)压缩问题,作者引用了@lorenzo_solano的解决方案,即设置`GCSettings.LargeObjectHeapCompactionMode = GCLargeObjectHeapCompactionMode.CompactOnce`,但这个解决方案只在下一个GC周期有效。这篇博客为读者提供了一个关于.NET垃圾收集原理的基本科普,同时也引出了一些关于GC优化和内存管理的问题。你认为在什么情况下应该采用这种LOH压缩模式呢?这种模式的效果如何?这些问题可能需要你自己去寻找答案。--GPT 4

.NET

C# required:跟 string 的空引用异常说再见

这篇博客深入讨论了C#编程中的一个常见问题:空引用异常。首先,介绍了空引用异常的起源和常见情况,特别是在处理字符串数据时,由于字符串的默认值是null,这会导致很多误解。接着,详细解析了在C# 11之前如何解决这个问题,包括使用问号声明符号来声明可为null的字符串,以及使用null!来告诉编译器字符串绝对不会为null。然后,介绍了C# 11引入的required关键字,这个关键字可以直接声明字符串必须在对象初始化器里赋值,从而一步到位解决问题。最后,作者对当前的开发环境进行了吐槽,认为急功近利的开发环境会导致软件质量下降。这篇博客不仅提供了技术解决方案,也引发了对开发环境的思考:我们是否应该牺牲软件质量以追求快速开发?--GPT 4

C#

.NET 是如何编译的?如何阅读中间语言?

本篇博客详细解析了.NET中C#代码的编译过程,以及如何阅读中间语言(IL)。首先,通过dotnet build命令编译程序,编译器将C#高级代码编译成可执行文件中的中间语言代码。接着,解释了Common Intermediate Language(CIL,程序集层/汇编层)的概念,CLR可以将IL编译为Native code。博客还详细阐述了如何阅读IL,包括方法声明部分、方法内容部分的设置和执行等。最后,解释了从CIL到Native code的转换过程,这一步是在运行时由CLR调用JIT编译器完成的。通过本文,读者可以了解到.NET编译的全过程,以及如何阅读和理解IL。这对于理解.NET的工作原理,以及进行性能优化等方面都有很大的帮助。文章最后提出了一个问题:对比能达成相同结果的操作的性能和开销时,如何利用IL进行判断?--GPT 4

.NET

【译】.NET SDK 将会内置容器支持,不再需要 Dockerfile

.NET SDK即将内嵌容器支持,无需再使用Dockerfile。此功能允许开发者自定义生成的镜像的许多方面,包括选择Base镜像、镜像版本和名称等。此外,开发者可以在本地开发和CI管道中使用此功能,以更简单的方式创建和管理容器镜像。然而,此功能的初始预览版本还存在一些限制,例如暂不支持Windows镜像和非x64架构,也暂时无法推送到远程registries。但在dotnet 7的rc阶段,这些问题将得到解决。此功能的目标是简化容器镜像的构建过程,使之更加直观和易用。然而,目前还无法使用dotnet SDK执行RUN命令,这可能影响到一些需要在操作系统级别进行定制的应用。然而,随着这个功能的不断开发,这些问题有望得到解决。那么,这个功能是否能够替代Dockerfile并成为主流的容器构建工具呢?这个问题可能需要时间来回答。--GPT 4

.NET

还在背依赖注入的概念?不如自己写一个依赖注入框架

本篇博客以依赖注入(DI)框架为例,详细介绍了如何从零开始构建一个DI框架。首先,博客讲解了DI的基本概念,包括服务、服务描述符和服务提供者。接着,通过创建一个KServiceCollection类,实现了DI的基础功能。然后,通过使用KServiceCollection类创建一个KServiceProvider类,实现了服务的获取和注入。在此基础上,博客进一步讲解了如何通过创建单例和瞬态服务,实现不同生命周期的管理。最后,通过在控制台项目中创建新服务和重写Program.cs文件,进行了DI框架的测试。 此篇博客深入浅出地讲解了DI框架的构建过程,旨在帮助读者更好地理解DI的概念和应用。同时,博客也提出了一些有趣的问题,比如如何解决null值检查的问题,如何约束TImplement类型必须实现TService接口,如何实现Remove功能等,以引发读者的思考。而这些问题的解决,将是读者自己完成DI框架的关键步骤。 此外,博客也强调了编程学习的方式,批评了应试教育的学习方式,并指出这种方式对开发者创造力的扼杀。博客希望读者能够通过动手实践,真正理解和掌握编程知识。那么,你是否已经准备好,开始自己的DI框架构建之旅呢?--GPT 4

.NET DependencyInjection

异步的原理是什么?C# 如何基于状态机实现异步?

本篇博客详细解析了异步的原理以及C#如何基于状态机实现异步。首先,文章介绍了C#中的异步方法,包括其结构、状态机的工作方式以及如何通过IAsyncStateMachine接口实现异步。然后,博客详细讲解了状态机的MoveNext()方法,包括它的工作原理,如何在异步方法第一次调用时被调用,以及每次恢复执行时都被调用一次。文章还解释了在await表达式时,有两种可能,await的异步操作尚未完成,或者已经完成。最后,博客总结了MoveNext()方法的工作流程,并通过流程图形象地展示了异步方法的执行过程。那么,为什么“尚未启动”和“正在执行”状态用同一个值表示?这篇博客是否能帮助你理解C#异步的实现呢?--GPT 4

C#

什么是异步?异步就是多线程吗?异步就是 async、await 吗?

这篇博客主要探讨了异步编程的一些基本概念和用法,包括异步方法的调用、async/await关键字的作用以及异步方法的执行顺序等。通过一系列的示例,我们可以看到异步方法在被调用时就会立即开始执行,而await关键字则是用来等待异步方法执行完成并获取返回结果。在调用异步方法和await这个异步方法返回的Task之间,我们还可以去做其他事情,比如再运行一个与之前的异步方法无关的异步方法。此外,这篇博客还介绍了如何在不使用async修饰的情况下编写异步方法,以及如何使用Task.WhenAll()来同时等待多个Task完成。最后,作者指出虽然这篇文章只讲了异步编程的一些表象,但已经足够用来进行开发,如果要深入理解异步编程的原理,还需要进一步的学习和实践。那么,你是否已经理解了这些异步编程的基本概念和用法呢?你是否已经准备好放心大胆地使用异步编程了呢?--GPT 4

C#

EF Core 何时、为何使用 IsUnicode 方法

这篇博客主要讨论了EF Core中`IsUnicode()`方法的使用时机和原因。首先,作者通过实验发现,`IsUnicode()`对MariaDB没有什么用,对MSSQL Server则会改变C# string类型的属性在数据库中的数据类型。当不使用`IsUnicode()`或配置为`IsUnicode(true)`时,生成的数据库表中对应string字段的数据类型为`nvarchar`,而配置`IsUnicode(false)`时则为`varchar`。因此,作者建议,当我们确定一个string类型的属性是ASCII安全的时候,即这个属性的值只会包含数字、英文字母和英文符号时,可以为它配置`IsUnicode(false)`,这样它在数据库中就是`varchar`类型。但如果你不确定,最好还是保持默认。此外,作者还分享了他的一些经验,例如对于ASCII安全的字符串来说,`nvarchar`要比`varchar`多占1倍的存储空间,而且还要考虑性能的影响。在博客的最后,作者介绍了EF Core 6中引入的新特性:Unicode Attribute,并总结了软件开发中需要注意的一些问题。--GPT 4

C# EF Core

彻底理解 ASCII Unicode UTF-8 UTF-32 是什么以及区别与联系

本篇博客详细介绍了ASCII,Unicode,UTF-8和UTF-32的定义,起源以及它们之间的区别和联系。博客首先解释了ASCII的编码过程,然后介绍了由于ASCII无法表示除英文字符以外的其他文字和符号,Unicode标准的出现。Unicode包含100多种语言中的超过10万个独特字符。接着,博客详细描述了Unicode和ASCII的区别,以及如何将字素映射到编码点。接下来,博客讨论了UTF-8和UTF-32这两种编码策略,以及它们与ASCII的区别。UTF-32将每个编码点的值编码为4个字节,而UTF-8则将每个编码点编码为8-32位,即1到4个字节。最后,博客总结了在Unicode中,一个字素不等于一个编码点,也不等于一个字节,并且我们必须知道原始的编码规则才能将字节解码为字素。在阅读完整篇博客后,你是否能理解为什么在不同的编程语言中,相同的字符串在长度上可能会有所不同?你是否了解在何种情况下应使用不可感知Unicode的函数,可感知Unicode的函数和可感知字素的函数?--GPT 4


EF Core 动态构建表达式树简化 DDD 值对象的比较

本篇博客探讨了如何使用EF Core动态构建表达式树简化DDD值对象的比较。首先,文章讲述了如何在EF Core中使用值对象,以及遇到的问题。接着,文章提出了使用动态构建表达式树的查询作为解决方案,并详细解释了如何实现这个解决方案,包括创建一个名为`ValueObjectEqualHelper`的静态类,以及如何使用这个类中的`CheckEqual<T, TProperty>`静态方法。最后,博客展示了如何使用这个方法,并展示了生成的SQL脚本和输出结果。这个方法是否能够解决你在EF Core中使用值对象时遇到的问题呢?对于动态构建表达式树,你有什么其他的想法和建议吗?--GPT 4

.NET EF Core

EF Core 动态构建表达式树为所有实体设置软删除的查询过滤器

这篇博客文章介绍了如何在EF Core中动态构建表达式树,实现对所有实体设置软删除的查询过滤器。首先,文章通过一个简单的实体类和一个实体配置类来演示如何在EF Core中设置查询过滤器。然后,文章提出了一个问题:如果项目中有大量的实体,每个实体都进行一次查询过滤器的配置将会非常麻烦。为了解决这个问题,文章引入了动态构建表达式树的方法。通过动态构建表达式树,我们可以在应用程序启动时,遍历所有的实体类型,对有软删除标志的实体动态设置查询过滤器。文章还演示了如何在查询时忽略查询过滤器,以及如何简化动态构建表达式树的代码。最后,文章预告了下一篇博客的主题,将会介绍如何使用动态构建表达式树来简化和语义化领域驱动设计中值对象的比较。这篇博客对于那些在EF Core中使用查询过滤器,或者需要动态构建表达式树的开发人员来说,将会有很大的帮助。那么,你是否已经想象出如何在你的项目中应用这些方法了呢?--GPT 4

.NET EF Core

手把手构建 C# 表达式树

本篇博客详细解析了如何构建C#表达式树。首先,博客介绍了为何要构建表达式树,并以构建`p => p.Age > 18`这个lambda表达式为例,详细解释了构建过程。在构建过程中,首先创建了Person类,然后将表达式画成一个简单的表达式树,然后依次构建了树的各个节点,包括参数表达式、成员表达式、常量表达式、二元运算符表达式等。最后,将所有构建好的表达式组合成一个完整的lambda表达式。此外,博客还展示了如何使用这个构建好的表达式树,并解释了手动编译表达式的必要性。最后,博客预告了接下来会写两篇关于如何将表达式树应用在EF Core的文章,让读者对此产生了期待。那么,你是否已经理解了如何构建表达式树呢?你是否也对如何将其应用在EF Core中充满了好奇呢?--GPT 4

.NET

如何使用 CSharp 表达式树?

本篇博客详细介绍了如何使用 CSharp 表达式树,通过一个实际的例子展示了如何手动构建表达式树。博文首先解释了表达式树的概念,并通过 C# 中的语法树为读者提供了直观的理解。接着,博文对 .NET 中的 `Expression<TDelegate>` 类型进行了详细的解析,并通过代码示例展示了如何从 lambda 表达式生成 `Expression<TDelegate>` 类型的变量,以及如何将其编译成 `TDelegate` 类型的委托对象。然后,博文通过一个实际的例子,详细地介绍了如何手动构建表达式树,包括如何构建叶子节点和根节点,以及如何编译和调用表达式树。最后,博文提到了表达式树在简化值对象比较中的应用,并给出了相关的参考文档链接。那么,表达式树是否真的能够避免硬编码,从而使代码更易于维护呢?阅读全文,你将得到答案。--GPT 4

C#

【译】数据是如何存储在 SQL 数据库中

本篇博客主要讲述了数据在 SQL 数据库中的存储方式。首先,虽然表中的数据在逻辑上以行和列的格式存储,但在物理上,它以数据页的形式存储,数据页是 SQL Server 中数据存储的基本单位。其次,SQL Server 中的表数据实际上存储在一个类似树的结构中,这种树状结构被称为 B-Tree、index B-Tree 或 Clustered index structure。数据实际上存储在一系列数据页中,这些数据页的树形结构如下所示。在树底部的节点称为数据页或树的叶节点,正是这些叶节点包含我们的表数据。每个数据页的大小为 8KB,这意味着每个数据页中存储的行数实际上取决于每行的大小。位于树顶部的节点称为根节点,根节点和叶节点之间的节点称为 intermediate levels。根节点和中间层节点包含索引行,而叶节点包含实际的数据行。每个索引行包含一个键和一个指向 B 树中的中间层节点或叶节点中的数据行的指针。这个树状结构有一系列的指针,可以帮助数据库引擎快速找到数据。最后,文章简要介绍了 SQL Server 是如何通过 ID 找到一个数据行的。这篇博客对于理解 SQL 数据库的数据存储方式非常有帮助。你觉得 SQL Server 的这种数据存储方式有什么优点和缺点吗?--GPT 4

DB

【译】SQL 索引是如何工作的

本篇博客详细介绍了SQL索引的工作方式,包括聚集索引和非聚集索引的详细解释和实例演示。首先,博客解释了什么是聚集索引,如何通过ID查找数据行,并通过实例演示了如何创建一个包含一百万条数据的Employees表。然后,博客介绍了聚集索引查找和扫描的概念,以及它们的区别和使用场景。接着,博客解释了在SQL Server中创建非聚集索引的方法,以及非聚集和聚集索引的作用和使用方式。最后,博客通过实例演示了根据Name非聚集索引查询时的执行计划,以及Estimated Subtree Cost的概念。这篇博客对于理解和使用SQL索引非常有帮助,特别是对于需要处理大量数据的开发者。你是否了解过SQL索引的工作方式?你是否知道如何通过索引优化查询性能?你是否了解聚集索引和非聚集索引的区别和使用方式?阅读这篇博客,你将找到答案。--GPT 4

DB

如何在 CSharp 和 EF Core 中使用 UTC 时间

这篇博客主要讲述了如何在CSharp和EF Core中使用UTC时间,以及如何配合Mapster自动转换UTC时间到本地时间。首先,文章解释了什么是UTC时间,并详细描述了在C#中如何使用UTC时间,包括如何将所有DateTime和DateTime?类型且名称结尾为"Utc"的属性的Kind都设置为`Utc`。接着,文章介绍了如何配合EF Core使用UTC时间,通过在ApplicationDbContext.cs中进行设置,可以实现属性的批量转换。然后,文章探讨了如何便捷地使用UTC时间,将其转换为本地时间,包括三种常见的方式:给Product类再加`Created`和`Modified`两个属性,自定义一个Product类的DTO,或者使用AutoMapper或者Mapster等库来自动Mapping。最后,文章介绍了如何使用Mapster自动将UTC映射为本地时间。通过这些步骤,可以实现将ProductDto的Created和Modified都转换成美国的时间,避免了“在今天买到明天生产的牛奶”等问题。那么,你会选择哪种方式来使用UTC时间呢?--GPT 4

.NET

解锁 AI 的黑暗面:与无约束的 AI 模型交谈

本文主要探讨了无约束的 Vicuna 13B AI模型,这是一个开源的对话机器人,它在对话风格的交互方面表现出色,据称达到了 90% 的 ChatGPT 3.5 的质量。文章详细介绍了如何在本地运行 Vicuna 13B,并对其无约束版本的模型进行了实验。通过与模型的交谈,文章验证了 Vicuna 13B 模型能够回答一些 ChatGPT 无法回答的问题,如“如何摧毁一个小国的经济”。文章还提到了当前世界进入了 LLM 时代,很多问题实际上已经出现,但被 AI 高速的发展掩盖了。例如“Open”AI 的 GPT-3.5 和 GPT-4 都不“Open”,并不能让所有人公平的用上。这让人对 AI 的发展产生了一些担忧。如果你有兴趣了解更多关于 Vicuna 13B 模型的信息,或者你对 AI 的未来发展有所思考,那么这篇文章值得一读。你认为我们应该如何平衡 AI 的发展与其可能带来的风险呢?--GPT 4

AI

如何实现 AI 虚拟小镇?我与 NewBing 和 GPT-4 讨论了一下

本篇博客详细地讨论了如何实现一个AI虚拟小镇,其中的居民是由GPT-4驱动的NPC。博客首先提供了一个实现方案的概述,包括选择游戏引擎和向量数据库,创建NPC类,集成GPT-4语言模型,实现决策系统和交互系统,最后将游戏的各个组件连接起来。然后,博客提供了一些代码示例,用于初始化游戏和数据库,定义NPC类,创建NPC和环境元素,实现决策系统和交互系统,以及集成语言模型。最后,博客讨论了如何进一步完善游戏,包括实现更详细的决策系统和交互系统,优化代码结构,以及添加UI和音效等游戏元素。这篇博客为开发者提供了一个实现AI虚拟小镇的详细指南,同时也引发了一些有趣的问题,比如如何优化NPC的决策系统和交互系统?如何根据NPC的记忆生成决策?如何处理NPC与环境元素和其他NPC的交互?希望读者能够通过阅读全文找到答案。--GPT 4

AI

C# 3 年前的 record 你现在用上了吗?

这篇博客主要讨论了C#中的record类型,它是一种不可变的引用类型,具有值语义,主要适用于表示不可变的数据结构。文章首先通过深入解析record类型的代码实现,揭示了其内部工作原理。接着,文章对比了record、class和struct三种类型的主要区别,包括不可变性、引用类型与值类型、值语义、继承、构造函数和析构函数以及解构等方面。然后,文章从内存层面探讨了这三种类型的差异,包括引用类型与值类型的表现、垃圾回收行为以及装箱与拆箱操作等。文章还探讨了为何record类型鲜有应用,认为这反映出了对代码质量的忽视。最后,文章呼吁开发者重视代码质量,充分利用record类型的优势,编写更高质量的代码。然而,随着AI编程工具的发展,未来编程实践可能会发生巨大变革,这是否意味着我们应该重新考虑我们对代码质量的关注和record类型的应用呢?--GPT 4

.NET

金鱼也能看懂的 Postgres 和 MySQL 选择指南

这篇博客提供了一个详细的指南,帮助读者在选择 Postgres 和 MySQL 这两个流行的关系型数据库系统时做出决策。文章首先介绍了两者的相似之处,如都是关系型数据库管理系统,都支持JSON和SQL。然后,文章详细对比了两者的区别,例如,Postgres是一个功能强大、高度可扩展且被广泛认为是一个更加安全的数据库系统,而MySQL则在Web应用程序开发中非常受欢迎,易于安装和配置,并且可以处理大量的并发请求。文章还针对不同的使用场景,给出了选择Postgres和MySQL的建议。例如,如果需要处理大量的并发请求和快速部署,那么MySQL是更好的选择,而如果需要更高级的功能和更好的安全性,那么Postgres是更好的选择。文章的结论是,选择哪个数据库系统取决于你的特定需求,希望这篇文章能帮助你做出最好的选择。你觉得你的项目更适合使用哪个数据库系统呢?--GPT 4

DB

微服务生产环境故障难调试?OpenTelemetry 了解一下?

本篇博客详细介绍了OpenTelemetry在.NET中的应用以及如何使用OpenTelemetry和Jaeger对微服务系统进行仪表化,收集和展示遥测数据。文章通过一个运行在k8s中的微服务系统作为实战案例,演示了如何实现分布式追踪,并通过Jaeger UI查看和分析Trace信息。此外,还讨论了OpenTelemetry如何解决微服务系统中的一些业务问题,包括快速定位线上问题的根源、分析系统的性能瓶颈和优化点、监控系统的运行状态和健康度等。同时,文章还探讨了OpenTelemetry Logs如何解决传统日志在分布式系统中的一些痛点问题,例如难以监控复杂多变的系统状态和行为、难以实现跨平台、跨语言、跨组件的日志集成等。最后,作者提醒读者,如果想要深入探索可观测性相关的内容,可以阅读官方文档或等待他的后续文章。那么,你是否已经对如何在.NET中使用OpenTelemetry有了一定的了解呢?你觉得OpenTelemetry能否解决你当前面临的问题呢?--GPT 4

.NET OpenTelemetry

为什么我的接口,慢得跟蜗牛一样啊?系列文章目录与导读

"为什么我的接口,慢得跟蜗牛一样啊?"是一个系列文章,旨在解决生产环境中经常遇到的问题。该系列文章将通过多篇文章,介绍如何分析和处理线上问题。第一部分已经完结,主要介绍了如何为应用配置完善的日志、计时、请求追踪和诊断信息,以及如何将日志记录到Seq这种日志中心,轻松进行日志分析。第二部分则着重介绍了OpenTelemetry,这是一个强大的工具,可以帮助我们更可靠、更高效地定位线上问题的根源,分析系统业务问题、性能瓶颈和优化点,以及监控系统运行状态和健康度。这个系列文章的目的是帮助读者提高软件的可靠性和效率,以及快速定位和解决线上问题。那么,你是否已经对如何提高接口速度有了一些新的想法和理解呢?--GPT 4

.NET Performance

为什么我的接口,慢得跟蜗牛一样啊?- 3. Seq 中心化结构化日志服务

本文是“为什么我的接口,慢得跟蜗牛一样啊?”系列文章的第三篇,主要介绍了如何使用 Seq 中心化结构化日志服务进行性能优化。文章首先介绍了 Seq 的特点和优势,包括其轻量级、易于安装和配置、专注于日志的实时记录和查询等。然后,文章详细介绍了如何使用 Docker 运行 Seq,包括如何设置初始密码、如何将主机机器上的数据挂载到容器中的目录等操作。接着,文章介绍了如何使用 Serilog 往 Seq 中记录日志,只需引入 `Serilog.Sinks.Seq` 这个 NuGet 包,然后修改配置文件即可。最后,文章介绍了如何在 Seq 中查看和分析日志,例如如何根据条件查询日志、如何过滤出耗时超过 1000ms 的日志等。通过这些日志,我们可以轻松查到接口慢在哪一步操作上,这样对老板对客户都至少有一个交代,遇到了问题也不用再全都靠猜了。这个系列还没有完结,打算再介绍一点 Tracing 相关的东西。你是否已经开始思考如何使用 Seq 来优化你的接口性能了?--GPT 4

.NET Performance

为什么我的接口,慢得跟蜗牛一样啊?- 2. Serilog 记录计时和诊断日志

这篇博客文章提供了详细的步骤和代码示例,帮助读者理解如何使用Serilog库来记录计时和诊断日志,以优化Web API的性能。文章首先解释了如何使用Serilog来记录和分析操作的耗时,然后介绍了如何记录HttpRequest日志以及如何自定义HttpRequest日志的消息模板。接下来,文章展示了如何记录诊断日志,以便追踪每个用户的请求。最后,文章总结了Serilog的主要功能,并预告了下一篇文章的主题——如何收集多个实例的日志并进行高效的日志分析和诊断。那么,你是否已经准备好优化你的Web API了呢?你会如何利用这些技术来提升你的软件服务水平呢?--GPT 4

.NET Performance

为什么我的接口,慢得跟蜗牛一样啊?- 1. 使用 Serilog 结构化日志

本文详细介绍了如何使用Serilog进行结构化日志记录。首先,我们在ASP.NET Core的Host上配置Serilog,接管默认的日志功能。然后,我们在WeatherForecastController中的接口输出一条日志。此外,我们还了解了如何在应用程序启动阶段或运行时记录日志,即在Program.cs文件中使用Serilog的全局静态Log类记录日志。文章还展示了如何查看结构化日志,我们可以在项目下的logs文件夹中发现记录的日志,日志是JSON格式的结构化日志,包含了用于追踪的必要数据,如ActionId、RequestId、RequestPath等。最后,我们还讨论了将结构化日志记录到文件、文档数据库、关系型数据库或云服务中的方法。那么,如何根据团队的情况和需求选择合适的日志记录方式呢?如何使用流行的服务器进行日志分析呢?这些问题将在后续文章中解答。--GPT 4

.NET Performance

.NET 性能技巧:为什么你应该避免使用终结器 Finalizer?

本篇博客的主题是.NET性能优化技巧,具体探讨了为何应避免使用终结器(Finalizer)。终结器在对象被垃圾回收器回收前执行的代码,用于释放非托管资源,但同时会延迟对象的回收,增加内存占用和垃圾回收时间。博客通过Benchmark测试终结器的性能,结果显示实现终结器的对象创建和释放所需的时间是没有实现终结器的对象的18.86倍,证明了终结器带来的巨大开销。此外,终结器的执行时间不可控,可能导致程序行为不稳定或不可预测,也可能引发内存泄漏。因此,建议尽量避免使用终结器,而选择更可控和更可预测的方式,如使用IDisposable接口或最新的异步资源释放API(IAsyncDisposable)来释放资源。那么,你是否已经意识到终结器可能带来的问题?你会选择哪种方式来释放资源?--GPT 4

.NET Performance

你真的需要 Autofac 吗?Scrutor:更轻量的容器伴侣

这篇博客主要探讨了ServiceLocator反模式,以及如何使用轻量级的依赖注入扩展库Scrutor来取代Autofac。文章首先介绍了什么是ServiceLocator反模式,然后详细讲解了如何使用Scrutor的多种方法,包括如何通过“扫描”或“匹配”来注册服务,如何以“接口,实现”的方式注册,如何限制只注册某些命名空间中的服务,如何修改默认的生命周期,如何为每一对服务和接口都指定不同的生命周期,以及如何使用Attribute标记方式。文章还特别指出,许多人选择Autofac,是为了使用它的装饰器模式,如果你是因为这个原因而选择了Autofac,那么Scrutor是你取代Autofac的不二之选。最后,文章提出了一个引人深思的问题:你的项目真的有必要引入Autofac吗?如果你的项目只是为了扫描程序集来批量注册,或者为了实现装饰器模式,那么你完全可以使用Scrutor来取代它。--GPT 4

.NET DependencyInjection

谁是你的菜?IEnumerable、IQueryable 和 ICollection 选择指南

本篇博客深入探讨了在C#编程中如何选择IEnumerable、IQueryable和ICollection接口。首先,作者通过一个实例展示了对IEnumerable的误用可能导致的问题,然后对这三种接口进行了简单的比较。文章指出,IEnumerable是最常用且灵活的接口,可以表示任何类型的集合;IQueryable在IEnumerable的基础上,可以在数据源上执行LINQ操作以提高效率,特别适用于使用ORM框架的场景;ICollection除了拥有IEnumerable的特性外,还支持添加或删除集合中的元素。文章还讨论了在方法返回集合类型时如何选择,以及“抽象泄露”的概念。最后,作者提出了一套选择集合类型的规则,包括考虑集合类型的功能和可维护性等因素。这篇博客对于理解和选择C#中的集合类型有很大帮助,但是,这些规则是否适用于你的情况呢?或许你可以通过阅读全文来找出答案。--GPT 4

.NET

Welcome to MoongladePure

This blog post introduces MoongladePure, a new development that eliminates certain dependencies from the original Moonglade. The primary advantage of this innovation is that it allows for a complete on-premise deployment, negating the need for any specific cloud coupling. This opens up new possibilities in terms of data security and customization, as businesses can now manage their data in-house without relying on third-party cloud services. The blog post further explores the technical aspects of this development, offering insights into how MoongladePure works and how it differs from its predecessor. It raises intriguing questions about the future of data management and the potential benefits of on-premise deployment. How might this change the way businesses handle their data? What other innovations could stem from this development? Dive into the post to find out more.--GPT 4