我眼中的ASP.NET Core之微服务

前言

前几天在博客园看到有园友在分享关于微软的一个微服务架构的示例程序,想必大家都已经知道了,那就是eShopOnContainers。

我们先不看项目的后缀名称 OnXXX ,因为除了 OnContainers 还有 OnAzure,OnWeb,OnKubernetes 以及 OnServiceFabric。

我们就还是来先说说 eShop 这个项目吧,eShop 是 ASP.NET Core 发布之后微软新开源出来的一个示例项目,想必大家之前也都知道微软放出来的关于 Web 的示例项目还有 PetShop, Music Store 这两个项目。关于这两个项目我们就不做过多的介绍了,但是关于这两个项目的架构风格我们不得不提起。

PetShop:WebFrom 的示例程序。典型的三层架构风格的应用程序。

MusicStore: 针对于 MVC3-5 框架和 EF 的一个示例程序。无明显架构风格。

eShop: 针对于 ASP.NET Core 的示例程序。它是一个 Rest 架构风格的应用程序。

我们从微软放出来的这些示例程序中也许可以看出些许东西,那就是近些年来关于架构风格的演变,或者叫微软架构风格的演变,在这里我不打算讨论关于软件架构更加深层次的一些这种东西,我们只从我们能够理解的东西看起。

微软架构风格

我不知道有没有人看过这本书,目前已经绝版了,它是早年间关于微软架构风格的一本指南书,里面描述了微软体系的架构风格的一些汇总。

这本书中列出来了以下这些架构风格:

  • Client/Server Architectural Style

  • Component-Based Architectural Style

  • Domain Driven Design Architectural Style

  • Layered Architectural Style

  • Message-bus Architectural Style

  • N-Tier / 3-Tier Architectural Style

  • Object-Oriented Architectural Style

  • Service-Oriented Architectural Style

我们可以看到微软所开源出来的这些示例程序其实都是在遵循这些架构风格中的某一种或者是多种。 PetShop 属于 N-Trie ,Music Store 属于 Layered,eShop 属于 Service-Oriented。
当然在 eShop 中微软不但使用了 Service-Oriented ,其中还包括 Domain Driver Design(DDD), Message-bus 也都应用到了示例程序中。

由此,我们可以看出,在现代的应用程序架构风格中,已经不是某一种架构风格可以独自独领风骚了,它一定是多种架构风格的混合体,互相补充来构建更加强大的应用程序解决方案。

下面进入到我们本篇博客的主题微服务。不,应该是 ASP.NET Core 中的微服务,有同学可能会说了,微服务是一种架构风格,它并不和某一种语言相关,也不是只有.NET 中才有微服务。在这里我想说的是我不想去讨论大众眼中的微服务,因为太多人去说这些东西了,不就你打开 InfoQ 或者 cnBeta 这些网站,满屏的都是微服务的东西。 所以你可以说我的微服务叫 Savorboard 式微服务。

既然要说 ASP.NET Core 中的微服务,那就必须又要说到 eShop 这个项目了,之前没有给大家分享关于 eShop 这个项目的一些信息其实是有原因的,因为这个项目有很多东西它没有实现完,或者是叫它还是一个半成品,给大家分享的话大家又运行不起来,所以就一直在等一个合适的时间来做。

ASP.NET Core 微服务

ASP.NET Core 其实是一个非常适合做微服务的一个 Web 框架,它足够的轻量级并且拥有超高的性能。并且对于 Rest 这些风格的接口支持的非常的友好。更多好处我其实不太愿意去说,因为只有你自己去体会才会知道。还不如来点实在的,去教你们怎么在 ASP.NET Core 中构建一个或者叫一组微服务集群。在我看来,有时候讲那么多理论也都是扯淡的。那就废话不多说,开始吧。

在开始之前还是要说一句,你的架构一定要符合你的业务和需求,不要为了架构而架构。举个例子,你的网站每天的访问量就那么几百号人,以后也不会大量的增加,你又是分布式又是大数据又是docker集群的这不没事给自己找事干么。切记。

第一步,业务拆分。

业务拆分其实有时候是需要经验积累的,有时候不仅仅是需要你有软件架构经验,还需要你有行业知识的经验。这时候你的业务拆分的才足够合理,不会随着时间的推移导致你的微服务变“大”。

如果你对 DDD 中领域建模这种软件建模方式在行的话可能会帮助你解决大量的潜在问题,如果你不会也没关系,因为你可以去学呀~ 2333

第二步,建模。

在微服务架构中,建模仍然是重要的一步,因为你使用的是 EF Code First , 建模质量的好坏肯定是和你以后的代码质量挂钩了。如果你不使用 EF,那我们就不能愉快的做朋友了。

给大家个小提示,如果你的项目中全是增删改查,没有什么业务算法或者逻辑可言的话,就让你的模型尽量的符合你的界面上的显示字段,这样可以最大化的提升开发效率。

第三步,写代码。

这个时候我希望你抛弃掉三层架构这种架构风格的设计,不是说那种不好,而是有更加便捷的方式了,你需要知道,你写的每一个 Action 都应该是尽量的简单,再去调用 BLL 层绕一大圈子就为了一个增删改查纯粹是给自己找活干,那样并没有提高项目的可维护度。

前段时间在 QQ 群听学姐说过这么一句话,就是佛家的人生三重境界之说, 即:“看山是山, 看水是水; 看山不是山, 看水不是水; 看山还是山, 看水还是水。”

这一句话对于软件架构的设计过程中同样适用,在最初的时候,我们对于软件程序不懂就按照官方给的示例程序来进行设计,即看山是山;随着我们的知识,见解,经验的积累我们有了自己的一些看法理解,出了自己的各种框架,即看山不是山;随着时间的推移,我们已经悟到了其中的精髓,又回到了官方示例,大道至简,即看山还是山。

第四步,重构。

当你写完代码之后,我认为有一个比较重要的步骤就是对写的代码进行一番重构,重构一般从两方面下手,第一方面是代码的命名以及格式,第二方面是代码的组织结构。

针对于代码命名以及格式的重构其实是有方法和技巧的,比如方法的命名以及方法的拆分等可以从<<重构>>这些书中来获取一些指导意见等,对于代码格式的话基本上现代的IDE都提供了很好的格式化工具,使用便是。

针对于组织结构的重构有时候是需要依赖很多你的经验的,经验丰富的程序员知道如果的去对写过的代码进行抽象,然后利用某种设计模式或者是面向对象的原则来让代码更加的利于维护和扩展,这种技能往往更难掌握,需要你去阅读很多的别人优秀的代码,然后去思考和学习。

OK,以上就是在构建单个微服务程序的个人总结的一些指导原则吧。

部署方式

指导原则可以帮助我们在构建系统的时候使其保持一个良好的结构,但是你还需要从整体上来把控整个微服务的布局。什么意思呢?

我们知道,微服务最良好的部署方式就是使用 Docker 容器进行部署,因为这样便于管理和配置。
在以前的单体结构的项目中也可以使用Docker进行整块的部署,我们可能部署到多个容器中,然后前置一个负载均衡器进行路由的转发,这样也是可以的。

通常情况下,即使我们的程序架构风格不是微服务,那么在组织代码结构时,也会进行模块的划分,比如划分为会员,商品,库存等。下面是一个单体应用整块部署使用Docker的部署图:

但是这种模式其实与容器的初衷是有一点违背的,容器所倡导的是一个容器只做一件事情。整块部署有一个明显的缺点是,如果随着应用程序的扩展那么每次代码的修改都要全部进行重新发布,但是我们经常修改的代码可能就是某一快的功能,而另外一些代码则永远不会动,这样不但发布程序的时候发布包很大,也容易出错,出问题造成的影响也比较广。

比如,在一个电商网站中,有一些模块是经常发生变化的,比如一些促销,产品等页面,这些页面的访问量也很大,而另外一些页面比如用户中心积分查看,历史订单查看这些功能则不会经常变动,并且访问量要小很多。那么如果他们都在一个系统中,势必会引起这些问题:1、性能优化,如果访问量很高的模块出现性能问题,那么你只能针对整个程序进行扩展部署,而不是单个模块。2、测试,由于模块的依赖,那么在修改一块地方的时候,必须重新对整个应用程序进行一次测试,并且重新部署所有这些实例。3、无法进行扩展,你无法简单的进行接口或者服务的扩展,这会使SOA变得很困难。

那么我们就再顺便说一下SOA,我们知道大多数的公司在 .NET FX 时代使用 WCF 技术进行项目的 SOA 化,比如常见简单的会使用 SOAP ,HTTP,MQ等进行通讯,他们也会把系统进行划分(子系统)和分层。听起来可能和微服务有点像,那么他们有什么区别呢? 想必这是一个很多人讨论过的话题,那么直接说结论吧。 微服务它来自于SOA,但是和SOA不同的是它并没有那么重量级,什么意思呢?比如它没有SOA中的像集群的Broker, 那么大的组织的划分,中央负责人, 还有企业服务总线 (ESB)等。

然后就是我们的主题微服务,微服务架构的定义就是一组小型的服务。每一个服务都位于自己的进程中,并且使用诸如HTTP, WebSockets,或者 AMQP 之类的协议进行通讯。它很小,并且专注于做好一件事,这个很重要,它看起来像OOP中的单一职责原则,如果你2周之内不能完成一个微服务模块,那么可能你对于边界划分出了点问题。

关于微服务的优缺点不做过多的介绍了,有兴趣的同学可以看一下在我博客里面的 Martin Fowler 的 这篇文章。

这篇文章提到了『微服务设计』这本书,如果你想对微服务有更多了解的话可以看一下这本书,建议购买。

微服务中的一些技术挑战

下面需要说的是个人对于在构建微服务的过程中会面临的一些问题,或者说叫做挑战吧。

1、微服务的边界怎么定义。

上一篇文章已经提到过了,在定义微服务边界的过程中,DDD中的指导原则会帮助你大忙。 这可能是你在构建微服务过程中遇到的第一个难题,一个良好的微服务能够对其他微服务尽可能少的依赖,同一个应用程序中你需要用不同的上下文进行解耦,每个上下文有可能是使用不同的程序语言的。这些上下文应该被独立的定义和管理。比如一个User,在 Identity 上下文可能是一个用户,在 CRM 中是一个客户,在订单上下文是一个买家,等等。

2、如何跨微服务进行查询。

因为我们已经微服务化了,所以我们的应用程序数据可能分布在不同的数据库中,那么如何实现从多个为微服务器数据库中查询数据成为一个难题了。

比如,我们前台的数据展示页面需要一个销售统计的报表,其中的数据分别来源于订单,库存和商品。那么我们应该怎么样来处理这种复杂性呢? 目前流行的解决方案有以下几种:

API网关。 使用API网关来对多个微服务器的数据库进行聚合。 但是在实现这种模式的时候你需要非常的小心,它有可能是你系统中性能的瓶颈,甚至它有可能违背微服务的自治原则。为了尽可能避免这个陷阱,你需要设计多个细粒度的 API 网关,每个网关关注系统一个垂直领域的“切片”区域,或者是一个业务领域。现在大部分的云提供商都提供的有 API 网关相关服务,比如AWS的 Amazon API Gateway,Azure 的 Establish API Gateways 等,借助于这些服务可以方便的对 API 进行管理。

CQRS与读表。 不知道大家有没有听说话物化视图(Materialized View)这个名词。你可以理解为远程视图,使用这种方法,你可以提前准备好一个只读表,其中包括多个微服务的数据,这个只读表的结构和你展示给客户的页面数据是对应的。

那么有同学可能会存在这样一个问题,假如我基于不同的数据库建立一个物化视图,那么在我建立物化视图的过程中,我应该怎么样进行查询,因为对于单个数据库的查询可能仍然是复杂的。确实如此,在以前单个应用程序的时候,我们在呈现个客户端需要的数据的时候,可能会是一个复杂的SQL Join连接查询的结果。那么这里的解决方案就是,我们需要建立一个和我们业务无关的一个单独的数据库,然后这个数据库中会包含一些和界面上需要的数据进行一一对应的一些查询用的表,然后我们应用程序中引入 CRQS 这种模式,将需要的数据写入到这些查询表中。

这不仅解决了跨微服务查询这个难题,并且也提高了性能。但是引入CQRS也就意味着你需要拥抱最终一致性

数据中心的 “冷数据”。 对于一些不需要做实时数据的复杂查询或者报表,通常是将微服务的“热数据”作为“冷数据”导出到数据中心以供报表。这个数据中心可能是一个基于大数据的系统,比如 Hadoop,AWS的Redshit,Azure的SQL Data warehosue等。

同步的过程你可以使用事件驱动这种通讯技术,或者是一些数据库提供的基础设施中的导入/导出工具等。如果使用事件驱动的话,其过程有点类似上面的CRQS查询过程。

3、如何实现多个微服务的数据一致性。

我们知道在每个微服务都是具有高内聚的特点的,外部想访问微服务的数据只能通过API访问,那么我们在实现一个微服务到另外一个微服务这种业务流程的时候,怎么同时保持多个微服务之间的一致性呢?

我们回到 eShop 这个微软的示例项目上来,来看看怎么处理的。 首先,Catelog 这个微服务是负责维护商品相关的信息,包括库存。 Ordering 这个微服务负责订单的管理,当新创建一个订单的时候,它必须验证这个订单的商品是否具有足够的库存(如果不够可能涉及到缺货登记),所以它就必须要和Catelog微服务打交道。在以前单服务的程序中可以简单的使用ACID事务来进行检查并且直接更新可用库存。但是现在不能这样了,每个微服务都拥有自己的数据库,当前的服务不能直接去操作其他服务的数据库的,这个时候我们为了实现我们需要的功能怎么办呢?我们可以使用异步通讯,比如消息或者事件驱动这种方式,这也是 eShop使用的方式。

这里就涉及到一个理论知识,就是 CAP定理。也就是说你必须要在可用性和ACID强一致性之间做出选择。大多数基于微服务的场景都需要可用性和高可扩展,而不是强一致性。所以为了保证在关键场景下应用程序能够正常响应,我们一般会选择牺牲强一致行从而追求最终一致性。

4、如何跨微服务进行通讯。

微服务之间的通讯,是一个比较大的技术挑战。这个时候你不应该去关注你应该使用什么协议,比如是使用 Http、Rest、AMQP
、消息、或者其他东西。相反,你应该了解每种协议的优缺点,你使用该协议想达到什么样的一个目的,以及这种协议怎么样和你的微服务更好的进行耦合。根据耦合程度,当发生故障的时候,是不是对系统有非常大的影响。

像微服务这种分布式系统中,是由许多的组件在很多的服务器之间共享的。这些组件最终可能会发生故障,当这些组件故障的时候,你需要考虑的是是否会引起更大的故障,所以你需要在设计你的微服务的时候充分考虑到这些通讯过程中常见的风险。

目前一种比较流行的做法是使用基于 HTTP 协议 REST 方式的微服务,这是因为它们很简单。而且基于 HTTP 的这种方式是完全可以接受的,当然这也取决于你当前的使用场景。 假如说你是在客户端或者是API网关中使用 HTTP 进行请求和相应以及进行微服务交互,那么它足够用了。但是,假如你是跨微服务之间进行HTTP的调用长链的话,就像在使用数据库事务那样使用,那么你的应用程序最终会遇到麻烦的问题。

事实上,如果你在内部微服务之间通讯也是通过HTTP的方式,那么我可以理解为你正在使用的是一个单机的应用程序,只是他们是基于进程之间的HTTP,而不是进程内的通讯。

因此,我们在设计微服务的时候,为了其具有更好的弹性,我们应该尽量减少这种跨微服务的通讯。这种情况下,我们可以使基于消息或者事件的异步通讯方式来达到目的。

那么在 .net 中有没有什么现成的解决方案可以用呢? 答案是肯定的,请向下看。

总结

这一篇主要是对上一篇的一个补充,以及涵盖了微服务的部署方式以及在构建服务器的过程中会遇到的一些技术挑战。

下一节,我们将说一下 基于消息的异步通讯, 我将会给出在 .NET Core 中的具体的解决方案,敬请期待。

相关文章:

原文地址:http://www.cnblogs.com/savorboard/p/aspnetcore-microservice2.html


.NET社区新闻,深度好文,微信中搜索dotNET跨平台或扫描二维码关注

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/324513.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

形象的解释神经网络激活函数的作用是什么

转载自 形象的解释神经网络激活函数的作用是什么 神经网络中激活函数的作用 查阅资料和学习&#xff0c;大家对神经网络中激活函数的作用主要集中下面这个观点&#xff1a; 激活函数是用来加入非线性因素的&#xff0c;解决性模型所不能解决的问题。 下面我分别从这个方面…

CSS3中的动画示例

大家好&#xff0c;欢迎来到雄雄的小课堂&#xff0c;上一期我们分享了几个CSS变形案例&#xff0c;大家还记得有哪几个吗&#xff1f;原文在这里&#xff1a;CSS3的几个变形案例……今天&#xff0c;我们来看看CSS的过渡&#xff1a;过渡简单的来讲&#xff0c;就是元素由一种…

ASP.NET Core之跨平台的实时性能监控(2.健康检查)

前言 上篇我们讲了《如何使用App Metrics 做一个简单的APM监控》,最后提到过健康检查这个东西. 这篇主要就是讲解健康检查的内容. 没看过上篇的,请移步:ASP.NET Core之跨平台的实时性能监控 首先我们来了解一下什么是健康检查(health checks)? 1.什么是健康检查? 健康检查…

​通俗理解神经网络BP反向传播算法

转载自 ​通俗理解神经网络BP反向传播算法 通俗理解神经网络BP反向传播算法 在学习深度学习相关知识&#xff0c;无疑都是从神经网络开始入手&#xff0c;在神经网络对参数的学习算法bp算法&#xff0c;接触了很多次&#xff0c;每一次查找资料学习&#xff0c;都有着似懂非…

CSS动画示例(上一篇是CSS过渡…)

大家好&#xff0c;欢迎来到雄雄的小课堂&#xff0c;前面&#xff0c;我们将CSS的变形和过渡都整理了&#xff0c;有需要的可以移步这里看&#xff1a;CSS3中的动画示例CSS3的几个变形案例……今天&#xff0c;我们来看看CSS3的动画。CSS3使用动画分为两个步骤&#xff1a;1.通…

Health Check in eShop -- 解析微软微服务架构Demo(五)

引言 What is the Health Check Health Check&#xff08;健康状态检查&#xff09;不仅是对自己应用程序内部检测各个项目之间的健康状态&#xff08;各项目的运行情况、项目之间的连接情况等&#xff09;&#xff0c;还包括了应用程序对外部或者第三方依赖库的状态检测。 W…

为什么梯度反方向是函数下降最快的方向

转载自 为什么梯度反方向是函数下降最快的方向 为什么梯度反方向是函数下降最快的方向&#xff1f; 刚接触梯度下降这个概念的时候&#xff0c;是在学习机器学习算法的时候&#xff0c;很多训练算法用的就是梯度下降&#xff0c;然后资料和老师们也说朝着梯度的反方向变动&a…

javaweb中实现分页,持续更新……

大家好&#xff0c;欢迎来到雄雄的小课堂&#xff0c;昨天分享了个分页工具类一个简单的分页工具类&#xff0c;其实&#xff0c;也是为今天的分享做的铺垫&#xff0c;今天&#xff0c;给大家带来的是javaweb实现分页的全过程&#xff01;前言&#xff1a;为什么需要分页&…

Redis(入门)

文章目录一、 Redis简介二、 基于Docker安装Redis单机版三、 Redis常用命令1 Key操作2 字符串值(String)&#xff08;值的长度不超过512MB&#xff09;3 哈希表(Hash)4 列表&#xff08;List&#xff09;5 集合(Set)6 有序集合&#xff08;Sorted Set&#xff09;四、 Redis持久…

浅析神经网络为什么能够无限逼近任意连续函数

转载自 浅析神经网络为什么能够无限逼近任意连续函数 神经网络为什么能够无限逼近任意连续函数&#xff1f; 下面通过一个分类例子一步一步的引出为什么神经网络能够无限逼近任意函数这个观点&#xff0c;并且给出直观感觉! 我们首先有这个需求&#xff0c;需要将下面的数据…

前端模块化工具--webpack学习心得

话说前头 webpack前段时间有听说一下&#xff0c;现在已经到了3.x的版本&#xff0c;自己没去接触。因为之前使用gulp来作为自己的项目构建工具。现在感觉gulp使用的趋势在减少。现在这段时间去接触了webpack&#xff0c;感觉很不错&#xff0c;它的模块化打包机制&#xff0c…

基于.NET CORE微服务框架 -谈谈surging的服务容错降级

一、前言 对于不久开源的surging受到不少.net同学的青睐&#xff0c;也受到.net core学习小组的关注&#xff0c;邀请加入.NET China Foundation 以方便国内.net core开源项目的推广&#xff0c;我果断接受邀请加入了队伍进行互相交流学习&#xff0c;最近也更新了surging新的…

java中部的分页实现(二)

大家好&#xff0c;欢迎来到雄雄的小课堂&#xff0c;昨天分享了关于分页查询的理论知识&#xff0c;今天我们就来结合代码和案例实际的应用一下&#xff0c;方便大家理解。前言&#xff1a;我们都知道&#xff0c;实现分页需要三个步骤。第一&#xff0c;确定页大小&#xff0…

SpringSecurity授权(访问控制)

一、 访问控制url匹配 在前面讲解了认证中所有常用配置&#xff0c;主要是对httpSecurity.formLogin()进行操作。而在配置类中httphttpSecurity.authorizeRequests()主要是对url进行控制&#xff0c;也就是我们所说的授权&#xff08;访问控制&#xff09;。httpSecurity.autho…

剥析surging的架构思想

1、前言 前面第一篇阐述了采用基于.NET CORE微服务架构&#xff0c;应用surging服务端与客户端之间进行通信的简单示例以及对于surging服务化框架简单介绍。在这篇文章中&#xff0c;我们将剥析surging的架构思想。 surging源码下载 2、通信机制 2.1 简介 在单体应用中&am…

javaweb实现分页(二)

前言&#xff1a;我们都知道&#xff0c;实现分页需要三个步骤。第一&#xff0c;确定页大小&#xff08;每页显示的数据量&#xff09;。第二&#xff0c;计算显示的总页数。第三&#xff0c;写分页的sql语句。这三步已经在昨天的推文中详细说明&#xff0c;需要的可以点击这里…

滴滴出行基于RocketMQ构建企业级消息队列服务的实践

转载自 滴滴出行基于RocketMQ构建企业级消息队列服务的实践 本文整理自滴滴出行消息队列负责人 江海挺 在Apache RocketMQ开发者沙龙北京站的分享。通过本文&#xff0c;您将了解到滴滴出行&#xff1a; 1. 在消息队列技术选型方面的思考&#xff1b; 2. 为什么选择 RocketMQ…

[信息安全] 1.密码工具箱

0. 何谓安全&#xff1f; 对于信息安全性的重要性&#xff0c;我想大家都不会否认。那么具体来说应该具有哪些特性才能称之为安全呢&#xff1f;举个简单的例子&#xff1a;我给你发送一条消息“借给我100元”&#xff0c;当你收到这条消息并且处理后你的账户里面会少出来100块…

深入理解TCP/IP协议-TCP建立与终止连接

转载自 深入理解TCP/IP协议-TCP建立与终止连接 一、引言 TCP 是一个面向连接的协议。无论哪一方向另一方发送数据之前&#xff0c;都必须先在双方之间建立一条连接。连接创建与终止的状态变化图如下&#xff1a; 二、三次握手建立连接 过程如下&#xff1a; 客户端发送一个 SY…

在Docker中运行asp.net core 跨平台应用程序

概述 Docker已经热了有一两年了&#xff0c;而且我相信这不是一个昙花一现的技术&#xff0c;而是一个将深远影响我们日后开发和部署、运营应用系统的一种创新&#xff08;很多人将其作为devops的一种非常重要的基石&#xff09;。学习docker的最好方式&#xff0c;莫过于它的…