国产化系统下的.NET Core实践(Topic:NET Core Practice for Localization  Systems)

这两三天一直在苏州,参加2020年中国.NET开发者大会,我第一次以讲师的身份参加技术大会,以前都是作为听众,这一次也是代表公司出去做技术交流,为此做了不少准备工作。 我从大学就是用C#和.NET,一直默默关注C#开源社区,2010年玩过Mono,2013年采用Xamarin开发Android应用,从2019年起开始带来团队实践.NET Core项目,公司核心的产品已经迁移到.NET Core,今年以来带领团队完成国产化系统下的.NET Core项目改造。 我的演讲主题是国产化系统下的.NET Core实践经验和心得,这是我们过去一年多以来的实践和心得,主要包括以下几个重点: 1、国产系统现状和要求,包括CPU、操作系统和中间件的要求,如何突破目前中间件对Java的特殊保护,到底是用java重写还是迁移.NET Core,给出实用的迁移建议; 我的建议是“尽量不要重复造轮子,坚持使用DotNet”,而解决方案是如下: 2、国产化各种准备工作,重点技术预研,特别是现有系统的各个类库对.NET Core的支持情况,最终做出技术评估; 3、项目迁移工作,除了按照官方要求迁移之外,还需要考虑系统在各个平台的可移植情况,我们迁移过程中遇到的问题和解决办法; 1)、现有系统的各个类库对.NET Core的支持情况:官方API和类库基本没有问题;重点注意第三方类库,比如Lucence.NET,Zip解析等 2)、客户迁移的要求情况:如果服务器CPU架构必须是申威,要重视;如果是龙芯可以拖一拖,但是其实可以和客户提系统支持的要求。 4、项目测试,模拟各种国产CPU搭建测试环境,并对系统进行测试; 5、国产专用服务器上的系统部署实践,部署过程中的问题和解决方案。 结语:开源,自由、开放的社区是创新的力量之源,这也是互联网诞生的初心。今天主持人说到会90后超过一半,还是很希望90后、00后和未来者们都知道什么是网站URL地址,都知道怎么使用搜索引擎,不要只是被困在算法和移动应用之中。

December 20, 2020

安可国产化系统下的DotNet Core实践

这两个月来带领团队实践安可国产化系统下的DotNet Core,我们积累了一些经验,这里做一下记录。 1、DotNet Core可以在安可下面运行吗? 首先,答案是肯定的。目前除了龙芯架构的服务器不支持DotNet Core(龙芯团队已经在努力,他们预计会尽快支持DotNet Core的下一个版本),其他所有平台架构的都支持,目前我们实际客户的操作系统有:ARM64(包括其扩展Aarch64)、X64,这些服务器包括飞腾、华为鲲鹏等国产服务器。 2、迁移麻烦吗?工作量有多大? 非常靠谱。DotNet兼容性做得非常好,只要是它支持的架构的服务器,都可以很好地运行。 唯一需要考虑的是,如果项目用到的第三方库比较多,需要逐个验证迁移工作,大部分流行的第三方库都已经支持DotNet Core。 3、Java重写还是迁移? 除非你们团队已经没有DotNet开发人员了,否则千万不要用Java重写,一方面是工作量大,另一方面是java的项目换到安可环境也是需要做很多适配工作。 而且我可以很负责任地说:DotNet Core的运行效率超级棒!几乎可以用飞快来形容。 4、迁移过程中有哪些经验? 代码经验 我们的代码几乎无缝转移过去,唯一的地方就是全文检索lucene.net,现在这个项目已经有更新,发了十几个bata版本,我认为可以用,所以升级过来了。 另外,安可要求只能用国产达梦数据库,需要做适配,还好这些数据库基本都是开源改过来的,适配不是问题,就是一些日期等细节需要主义。 服务器经验 我们第一个项目是迁移到政务系统,要求非常严格,有专用的服务器。我们先是在通用测试服务器下(Aarch64架构CPU,中标麒麟操作系统和银河麒麟操作系统),运行起来没有任何问题。后来在专用服务器下,架构和CPU都不变,但是专用服务器涉密,所以不能随意使用命令安装库,也不能更新系统库,只需要找到合适的包用专用服务器工具安装就可以,如果是系统库文件,就让厂商安装。 5、最大的问题是什么? 最大的问题是,安可要求服务器必须通过中间件安装系统,这些中间件其实就是web服务器,比如金蝶之类的,这里很崩溃,因为这些国产中间件只支持java,其实就是另外一个tomcat,我也认为他们基于开源改造。 后来我们的解决办法是,前后端分离,通过金蝶发布前端web站点,后端启动5000端口提供DotNet Core服务,这个并不违法安可要求。DotNet Core基于最开放的MIT开源协议,比java开放多了。

September 27, 2020

关于IT国产化盛宴的几点感想

这三周来牺牲社交时间,我亲自出马、带着团队三名精干主力在“中标麒麟龙芯”下编译.Net Core 3.0、并调试程序,编译通过但Bug太多,以失败而告终,最后放弃这个平台,这不是我们的问题,这是龙芯团队的问题,他们的CPU对彻底开源的.NET支持台还很差(也许明年会好些),不过目前我们支持“中标麒麟兆芯”,这个平台也完全符合安可要求。 从我接触到的情况来看,目前最鸡血的是那些国字号相关的企业,不过如果不涉密,但大部分也只是买来应付检查,因为国产服务器真的是几乎不能用。还有一些比较聪明的单位,直接购买云国产操作系统,但是这些国产云操作系统就是一个幌子,因为它们也是跑在“洋芯片”、寄生在“洋软件”下面而已。 Java的码农请别吐槽C#,两门语言都是“美帝”发明的开发语言哦,要说彻底支持符合国产要求,别忘了Java的SDK还有专利费,而且Java的拥有者Oracle告谷歌的侵权诉讼案还没结束呢,哈哈。 另外,很想对那些摇着民族主义旗号大喊国产的人,有本事从应用软件到开发语言彻底国产,还有哦,wifi现在澳洲公司还在收专利费、互联网也是MIT的发明、Apache基金会的总部现在还设在美国的马里兰州……这只是一场分蛋糕大盛宴,曲终人必散,苦的是那些重复造轮子的码农,还好我们已经脱离苦海。

August 24, 2020

数学基础、集合论和选择公理

这几天又重新学习复习了一下数学基础:逻辑主义、形式主义和直觉主义。我自己当然更倾向于基于公理化集合论的逻辑主义,这也是目前大部分数学家的选择。 一、数学基础 数学上,数学基础一词有时候用于数学的特定领域,例如数理逻辑,公理化集合论,证明论,模型论,和递归论(可计算性理论)。但是寻求数学的基础也是数学哲学的中心问题:在什么终极基础上命题可以称为真? 目前占统治地位的数学范式是基于公理化集合论和形式逻辑的。实际上,几乎所有现在的数学定理都可以表述为集合论下的定理。在这个观点下,所谓数学命题的真实性,不过就是该命题可以从集合论公理使用形式逻辑推导出来。 二、公理化集合论 基础集合论可以用非正式的、直觉的方式学习,在小学中就可以用文氏图说明。基础集合论直观地假设集合就是一群符合任意特定条件的对象的组合,但此假设会造成悖论。最简单及著名的是罗素悖论及布拉利-福尔蒂悖论。公理集合论的形成就是为了避免这些集合论的悖论。 许多数学家研究的公理集合论系统假设所有的集合形成累计层次。这类的系统可分为二类: 1、只由集合构成:这类系统包括最常用的公理集合论:含选择公理的策梅洛-弗兰克尔集合论(ZFC),由亚伯拉罕·弗兰克尔和陶拉尔夫·斯科伦扩展了策梅罗集合论所得。其他和ZFC有关的集合论有: 1)、策梅洛集合论是由德国数学家恩斯特·策梅洛创立,将分类公理代替替代公理。 2)、广义集合论,策梅洛集合论的一小部分,已足以处理皮亚诺公理及有限集合。 3)、克里普克-普拉特克集理论,省略了无穷公理、幂集公理和选择公理,削弱了分类公理和替代公理的公理架构。 2、由集合和真类构成:这类系统包括冯·诺伊曼-博内斯-哥德尔集合论,是设计生成同 ZFC同样结果的集合论公理系统,但只有有限数目的公理而不使用公理模式。单论只涉及集合的内容,此理论的强度和ZFC相当。另外比ZFC强的Morse-Kelley集合论及Tarski–Grothendieck集合论也属于这一类。 三、选择公理 选择公理:对于所有的集族,均存在选择函数。 罗素解释:假设有许多(甚至是无限)双鞋子,则我们可以选取每双鞋左边的鞋子构成一个具体的选择。然而,假设有无限双袜子(假设每双袜子都没有可区分的特征),在对于所有的集族,均存在选择函数。 哥德尔证明了选择公理与ZF的相对协调性。保罗·寇恩用力迫法证明了选择公理独立于ZF。也就是说:哥德尔和寇恩证明了,无论接受选择公理与否,都不会导致矛盾,只是身处不同的『数学世界』而已。 不过,除了一些研究集合论的数学家和逻辑学家以外,大部分数学家都选择接受选择公理,因为在含有选择公理的数学世界里,事情会简单一些。

July 3, 2020

基于DDD的微服务设计和开发实战

你是否还在为微服务应该拆多小而争论不休?到底如何才能设计出收放自如的微服务?怎样才能保证业务领域模型与代码模型的一致性?或许本文能帮你找到答案。 本文是基于 DDD 的微服务设计和开发实战篇,通过借鉴领域驱动设计思想,指导微服务项目团队进行设计和开发(理论篇详见《当中台遇上 DDD,我们该如何设计微服务?》)。本文包括三部分内容:第一部分讲述领域驱动设计基本知识,包括:分层架构、服务视图、数据视图和领域事件发布和订阅等;第二部分讲述微服务设计方法、过程、模板、代码目录、设计原则等内容;最后部分以一个项目为例讲述基于 DDD 的微服务设计过程。 目标 本文采用 DDD(领域驱动设计)作为微服务设计指导思想,通过事件风暴建立领域模型,合理划分领域逻辑和物理边界,建立领域对象及服务矩阵和服务架构图,定义符合 DDD 分层架构思想的代码结构模型,保证业务模型与代码模型的一致性。通过上述设计思想、方法和过程,指导团队按照 DDD 设计思想完成微服务设计和开发。 通过领域模型和 DDD 的分层思想,屏蔽外部变化对领域逻辑的影响,确保交付的软件产品是边界清晰的微服务,而不是内部边界依然混乱的小单体。在需求和设计变化时,可以轻松的完成微服务的开发、拆分和组合,确保微服务不易受外部变化的影响,并稳定运行。 适用范围 本文适用于按照 DDD 设计方法进行微服务设计和开发的项目及相关人员。 以下情况不适用: “我们的目标是按期盖出一栋大楼来,不要跟我提什么方法,有这啰嗦的时间,还不如抓紧点时间搬砖,把楼给我快点盖好!”。 “我的工作就是让软件运行起来,能工作一切就 OK!我不需要那么多约束,什么设计方法、扩展性、业务变化、领域模型、响应能力与我无关。别耽误工期啦!先上线再说!”。 “好的软件是自己演进出来的,我们不需要设计!”。 哈哈,开个玩笑啦!其实设计不会花太多时间的! 正文内容 不耽误大家时间了,言归正传。 DDD 分层架构视图 DDD 分层架构包括:展现层、应用层、领域层和基础层。 基于DDD的微服务设计和开发实战 DDD 分层架构各层职能如下: 展现层 展现层负责向用户显示信息和解释用户指令。 应用层 应用层是很薄的一层,主要面向用户用例操作,协调和指挥领域对象来完成业务逻辑。应用层也是与其他系统的应用层进行交互的必要渠道。应用层服务尽量简单,它不包含业务规则或知识,只为下一层的领域对象协调任务,使它们互相协作。应用层还可进行安全认证、权限校验、分布式和持久化事务控制或向外部应用发送基于事件的消息等。 领域层 领域层是软件的核心所在,它实现全部业务逻辑并且通过各种校验手段保证业务正确性。它包含业务所涉及的领域对象(实体、值对象)、领域服务以及它们之间的关系。它负责表达业务概念、业务状态以及业务规则,具体表现形式就是领域模型。 基础层 基础层为各层提供通用的技术能力,包括:为应用层传递消息、提供 API 管理,为领域层提供数据库持久化机制等。它还能通过技术框架来支持各层之间的交互。 服务视图 微服务内的服务视图 微服务内有 Facade 接口、应用服务、领域服务和基础服务,各层服务协同配合,为外部提供服务。 基于DDD的微服务设计和开发实战 1、接口服务 接口服务位于用户接口层,用于处理用户发送的 Restful 请求和解析用户输入的配置文件等,并将信息传递给应用层。 2、应用服务 应用服务位于应用层。用来表述应用和用户行为,负责服务的组合、编排和转发,负责处理业务用例的执行顺序以及结果的拼装。 应用层的服务包括应用服务和领域事件相关服务。 应用服务可对微服务内的领域服务以及微服务外的应用服务进行组合和编排,或者对基础层如文件、缓存等数据直接操作形成应用服务,对外提供粗粒度的服务。 领域事件服务包括两类:领域事件的发布和订阅。通过事件总线和消息队列实现异步数据传输,实现微服务之间的解耦。 3、领域服务 领域服务位于领域层,为完成领域中跨实体或值对象的操作转换而封装的服务,领域服务以与实体和值对象相同的方式参与实施过程。 领域服务对同一个实体的一个或多个方法进行组合和封装,或对多个不同实体的操作进行组合或编排,对外暴露成领域服务。领域服务封装了核心的业务逻辑。实体自身的行为在实体类内部实现,向上封装成领域服务暴露。 为隐藏领域层的业务逻辑实现,所有领域方法和服务等均须通过领域服务对外暴露。 为实现微服务内聚合之间的解耦,原则上禁止跨聚合的领域服务调用和跨聚合的数据相互关联。 4、基础服务 基础服务位于基础层。为各层提供资源服务(如数据库、缓存等),实现各层的解耦,降低外部资源变化对业务逻辑的影响。 基础服务主要为仓储服务,通过依赖反转的方式为各层提供基础资源服务,领域服务和应用服务调用仓储服务接口,利用仓储实现持久化数据对象或直接访问基础资源。 微服务外的服务视图 ...

June 16, 2020

关于龙芯对.NET Core支持的一些进展

今天邮箱收到github的issue更新提醒,就在昨天,龙芯(loongson)的码农们已经让.NET Core 3.1的FlightFinder例子在MIPS64跑起来了,但是更复杂的程序还得继续改,预计在今年年底加入.NET 5.x(谨慎乐观)。 .NET 本身是完全开源,比Java还要开放(想想现在Google和Oracle关于Java的专利案还没结束呢),但是MS官方已经明确.NET Core和未来的版本不会支持MIPS的CPU指令集架构(龙芯就是用这个架构级),因为太小众了,要实现就得社区自己去写。 龙芯的团队从去年11月份跑Hello World到现在做了不少工作,看社区里的几位工程师也很努力,最终应该会支持(大概率版本会落后),这个值得肯定。但是,对于龙芯来说,社区和生态太难了,要不是去年“安可”要求,估计也不会刺激他们去支持.NET Core。好的结局是“安可”推广成功,gov和army里无关紧要的系统都用(核心系统因为复杂度,怕是很难用上)。 最最要命的是:技术发展太快了,龙芯所支持的服务器市场现在已经完全靠云计算了,这些云计算不可能采用龙芯等国产芯片,这也是为什么阿里要造出概念化的飞天国产云系统的原因——为了政策需要啊! 对于科学技术,我坚信市场化和资本化是最有效的驱动力,最近的SpaceX是又一个有力佐证。努力的人很多,最后大都做了前浪。

June 4, 2020

插画版Kubernetes指南[此文非原创]

插画版Kubernetes指南(小孩子也能看懂的kubernetes教程) 是根据一个视频翻译过来的,比较形象 编者按:Matt Butcher 是 Deis 的平台架构师,热爱哲学,咖啡和精雕细琢的代码。有一天女儿走进书房问他什么是 Kubernetes,于是就有了这本插画版的 Kubernetes 指南,讲述了勇敢的 Phippy(一个 PHP 应用),在 Kubernetes 的冒险故事,满满的父爱有木有! 某一天 有一天,女儿走进书房问我:『亲爱的爸爸,什么是 Kubernetes 呢?』 我回答她:『Kubernetes 是一个开源的 Docker 容器编排系统,它可以调度计算集群的节点,动态管理上面的作业,保证它们按用户期望的状态运行。通过使用「labels」和「pods」的概念,Kubernetes 将应用按逻辑单元进行分组,方便管理和服务发现。』 女儿更疑惑了……于是就有了这个故事。 给孩子的插画版 Kubernetes 指南 很久很久以前,有一个叫 Phippy 的 PHP 应用,她很单纯,只有一个页面。她住在一个托管服务里,周围还有很多可怕的应用,她都不认识,也不想去认识,但是他们却要共享这里的环境。所以,她一直都希能有一个属于自己的环境:一个可以称作 home 的 webserver。 每个应用的运行都要依赖一个环境,对于一个 PHP 应用来说,这个环境包括了一个 webserver,一个可读的文件系统和 PHP 的 engine。 有一天,一只可爱的鲸鱼拜访了 Phippy,他建议 Phippy 住在容器里。Phippy 听从了鲸鱼的建议搬家了,虽然这个容器看起来很好,但是……怎么说呢,就像是漂浮在海上的一个小房间一样,还是没有家的感觉。 不过容器倒是为应用提供了隔离的环境,在这个环境里应用就能运行起来。但是这些相互隔离的容器需要管理,也需要跟外面的世界沟通。共享的文件系统,网络,调度,负载均衡和资源分配都是挑战。 『抱歉……孩子……』鲸鱼耸耸肩,一摇尾消失在了海平面下…… Phippy 还没有来得及失望,就看到远方驶来一艘巨轮,掌舵的老船长非常威风。这艘船乍一看就是大了点,等到船走近了,Phippy 才发现船体两边挂满了皮筏。 老船长用充满智慧的语气对 Phippy 说:『你好,我是 Kube 船长』。 『Kubernetes』是希腊语中的船长,后来的『Cybernetic』和『Gubernatorial』这两个词就是从 Kubernetes 衍生来的。Kubernetes 项目由 Google 发起,旨在为生产环境中成千上万的容器,构建一个健壮的平台。 ...

June 2, 2020

数学最重要的公式

一、费马大定理 $$ x^n+y^n=z^n \mbox{(n=2,为毕达哥拉斯定理)} $$ 二、欧拉公式 $$e^{i\pi} + 1 = 0$$ 三、牛顿-莱布尼茨公式 $$ \int_a^bf(x){\rm d}x=F(b)-F(a) $$ 四、黎曼zeta函数 整数形式 $$\zeta(p) = \sum_{n=1}^{\infty}{\frac{1}{n^p}}$$ 复数形式 $$\zeta(s) = \sum_{n=1}^{\infty}{\frac{1}{n^s}} \mbox{ (其中,} s \in C \mbox{,且 } Re(z) > 1 \mbox{)}$$

June 2, 2020

.NET Core微服务: ASP.NET Core on Docker

ASP.NET Core on Docker 指的是将 ASP.NET Core 应用运行在 Docker 容器中,通过容器化技术实现应用的开发、部署和运行。 Docker 为 ASP.NET Core 提供了统一的运行环境,使应用能够在开发、测试和生产环境中保持一致,避免因操作系统或依赖差异导致的问题。 在微服务架构中,每个服务通常都会被打包成一个独立的 Docker 镜像,并以容器形式运行。这样做具有以下优势: 环境一致性:开发、测试、生产使用相同的运行环境,减少“本地能跑、线上不能跑”的问题。 部署简单:应用及其依赖全部封装在镜像中,部署过程标准化。 资源隔离:每个微服务运行在独立容器中,互不影响。 快速扩缩容:可以根据业务压力快速启动或销毁容器实例。 易于持续交付:方便与 CI/CD 流水线结合,实现自动构建、测试和部署。 一个典型的 ASP.NET Core Docker 化流程包括: 编写 ASP.NET Core 应用。 编写 Dockerfile,定义镜像构建方式。 使用 Docker 构建应用镜像。 运行 Docker 容器。 在生产环境中结合 Docker Compose 或 Kubernetes 等容器编排平台管理多个微服务。 总体而言,ASP.NET Core on Docker 是 .NET 微服务体系的重要基础,它利用 Docker 的容器化能力,使应用具备更好的可移植性、部署效率和运维能力,为微服务架构的落地提供了可靠支撑。

June 1, 2020

.NET内存管理五大基础知识(此文非原创)

以下文章来源于DotNET技术圈 ,作者RICKY LEEKS 1.小对象怎么处理的? 小型.NET对象被分配到小型对象堆(SOH)上。其中有3种:第0代,第1代和第2代。对象根据其寿命向上移动。 将新对象放在Gen 0上。当Gen 0充满时,.NET垃圾收集器(GC)运行,处理不再需要的对象,并将其他所有内容移至Gen1。如果Gen 1充满,则GC再次运行,也可以将Gen 1中的对象移动到Gen 2中。 当Gen 2变满时,将发生GC完全运行。这将清除不需要的Gen 2对象,将Gen 1对象移至Gen 2,然后将Gen 0对象移至Gen 1,最后清除所有未引用的内容。每次运行GC之后,都会压缩受影响的堆,以将仍在使用的内存保持在一起。 这种代代相传的方法可确保事情高效运行-耗时的压缩过程仅在绝对必要时才会发生。 注意:如果您在Gen 2中看到大量的内存,则表明内存已被保留很长时间,并且可能存在内存问题。这是内存分析工具可以派上用场的地方。 2.较大的对象会怎样? 大于85 KB的对象被分配到大对象堆(LOH)。由于复制大块内存的开销,它们没有被压缩。当发生完整的GC时,未使用的LOH对象的地址范围将记录在可用空间分配表中。 分配新对象后,将在此可用空间表中检查足以容纳该对象的地址范围。如果存在,则将对象分配到那里,如果不存在,则将对象分配到下一个可用空间。 由于对象不太可能是空地址范围的确切大小,因此对象之间几乎总是会留有小块内存,从而导致碎片。如果这些块小于85 KB,则根本没有重用的可能性。因此,随着分配需求的增加,即使碎片空间仍然可用,也会保留新的段。 此外,当需要分配大对象时,.NET还是倾向于将对象附加到末尾,而不是运行昂贵的Gen 2 GC。这对性能有好处,但是是导致内存碎片的重要原因 3.垃圾收集器可以在不同的模式下运行以优化性能 .NET通过为GC提供多种模式来解决性能与堆效率之间的权衡问题。 工作站模式为用户提供了最大的响应速度,并减少了由于GC造成的暂停。它可以作为“并发”或“非并发”运行,指的是运行GC的线程。默认值为并发,它为GC使用单独的线程,因此应用程序可以在GC运行时继续执行。 服务器模式可为服务器环境提供最大的吞吐量,可伸缩性和性能。在服务器模式下,段大小和生成阈值通常比工作站模式大得多,这反映了对服务器的更高要求。 服务器模式在多个线程上并行运行垃圾回收,为每个逻辑处理器分配一个单独的SOH和LOH,以防止线程相互干扰。 .NET框架提供了一种交叉引用机制,因此对象仍然可以在堆之间相互引用。但是,由于应用程序响应能力不是服务器模式的直接目标,因此在GC期间,所有应用程序线程都将被挂起。 4.引用不足会在性能和内存效率之间折衷 弱对象引用了GC根的替代来源,使您可以保留对象,同时在GC需要时可以收集对象。它们是代码性能和内存效率之间的折衷。创建对象需要占用CPU时间,但保持加载状态需要占用内存。 弱引用特别适用于大型数据结构。例如,假设您有一个允许用户浏览大型数据结构的应用程序,他们可能会返回其中的一些数据。您可以将任何强引用转换为他们浏览的结构为弱引用。如果用户返回到这些结构,则可以使用它们,但如果没有,GC可以根据需要回收内存。 5.对象固定可以创建在托管和非托管代码之间传递的引用 .NET使用一种称为GCHandle的结构来跟踪堆对象。GCHandle可用于在托管域和非托管域之间传递对象引用,.NET维护一个GCHandles表以实现此目的。GCHandle有四种类型,包括固定的,用于将对象固定在内存中的特定地址。 对象固定的主要问题是它可能导致SOH碎片化。如果将对象固定在GC期间,则根据定义,该对象无法重定位。根据您使用固定的方式,它会降低压缩的效率,在堆中留下间隙。避免这种情况的最佳策略是在很短的时间内锁定,然后释放。

June 1, 2020