微服务架构之.Net技术栈
.Net 技术栈
虽然在国内.Net 技术受到互联网 Java 阵营挤压,但在国外.Net 技术还是蛮吃香的。之前发了一篇 Java 微服务技术栈,同样配一篇.Net 微服务技术栈。
相关套件开源地址:
Ocelot | 基于 .NET 5.0 编写的开源网关 |
Consul | 配置中心、注册中心组件 |
Refit | 一个声明式自动类型安全的 RESTful 服务调用组件,用于同步调用其他微服务 |
SkyAPM.Agent.AspNetCore | Skywalking .NET 5.0 探针,性能链路监测组件 |
Castle DynamicProxy | 动态代理,AOP 开源实现组件 |
Pomelo.EntityFrameworkCore.MySql | EFCore ORM 组件 |
Dapper | 轻量级 ORM 组件 |
Z.EntityFramework.Plus.EFCore | 第三方高性能的 EfCore 组件 |
NLog | 日志记录组件 |
AutoMapper | 模型映射组件 |
Swashbuckle.AspNetCore | APIs 文档生成工具 (swagger) |
StackExchange.Redis | 开源的 Redis 客户端 SDK |
CAP | 实现事件总线及最终一致性(分布式事务)的一个开源的组件 |
RabbitMq | 异步消息队列组件 |
Polly | 一个 .NET 弹性和瞬态故障处理库,允许开发人员以 Fluent 和线程安全的方式来实现重试、断路、超时、隔离和回退策略 |
FluentValidation | 一个 .NET 验证框架,支持链式操作,易于理解,功能完善,组件内提供十几种常用验证器,可扩展性好,支持自定义验证器,支持本地化多语言 |
Maxscale | Mariadb 开发的一款成熟、高性能、免费开源的数据库中间件 |
AspNetCore.HealthChecks | 健康监测组件, 搭配 consul 的健康监测 |
详细介绍
2.1 服务注册和发现
Consul
主要用来注册服务,及服务发现,以及服务的健康检查,我们可以根据需要针对某些业务服务进行自动扩容,添加服务器及扩张服务集群,一台服务挂了,Consul 会自动选择可用的服务节点进行连接使用,这样整体电商系统稳定性大大增大。
需要了解Consul
更加详细的特性和搭建,可以点击5 分钟看懂微服务架构下的 Consul 特性及搭建 一文阅读。
2.2ORM 框架
微服务中使用的 ORM Dapper ,而使用的的第三方开源组件是core-data
,开源作者对 dapper 进行了一次封装,开源框架源代码地址:https://github.com/overtly/core-data
core-data
主要优势:
- 官方建议使用 DDD 领域驱动设计思想开发
- 支持多种数据库,简单配置添加链接的配置即可
- 多数据库的支持
- 支持分表操作,自定义分表策略的支持
- 支持表达式方式编写,减少写 Sql 语句机械性工作
- 可对 Dapper 进行扩展
- 性能依赖于 Dapper 本身的性能,Dapper 本身是轻量级 ORM ,官方测试性能都强于其他的 ORM
2.3 分布式跟踪系统
随着微服务架构的流行,一些微服务架构下的问题也会越来越突出,比如一个请求会涉及多个服务,而服务本身可能也会依赖其他服务,整个请求路径就构成了一个网状的调用链,而在整个调用链中一旦某个节点发生异常,整个调用链的稳定性就会受到影响,所以会深深的感受到 “银弹” 这个词是不存在的,每种架构都有其优缺点 。
对以上情况, 我们就需要一些可以帮助理解系统行为、用于分析性能问题的工具,以便发生故障的时候,能够快速定位和解决问题,这时候 APM(应用性能管理)工具就该闪亮登场了。
目前主要的一些 APM 工具有: Cat、Zipkin、Pinpoint、SkyWalking,这里主要介绍 SkyWalking ,它是一款优秀的国产 APM 工具,包括了分布式追踪、性能指标分析、应用和服务依赖分析等。
2.4 系统日志集成
庞大的系统中离不开日志系统,排查问题,记录相关敏感信息等都需要一个日志系统,这里选择使用 ExceptionLess 日志系统,日志写入到 ES 中,并支持可视化 UI 进行日志管理,查询,平常遇到问题,直接通过日志管理后台进行排查。
2.5 消息队列
消息队列中间件是分布式系统中重要的组件,主要解决应用耦合,异步消息,流量削锋等问题。实现高性能、高可用、可伸缩和最终一致性架构。使用较多的消息队列有 ActiveMQ、RabbitMQ、ZeroMQ、Kafka、MetaMQ、RocketMQ。
2.6 任务调度
这里主要使用的是 Quartz.Net 进行作业任务调度,任务调用有什么用处呢?,比如我们需要统计一个数据,但是实时统计需要一大堆的连表查询,并且比较损耗数据库的性能,因此可以选择使用任务调度的方案进行数据统计作业,半夜某个时间点去统计前一天的数据。
2.7 NoSql
Nosql 主要是非关系型数据库,比如 MongDB、 Redis、Memcache 等,可以用来在 API 网关和数据库层面做一层数据缓存,访问一些不是经常更新的数据,把它缓存起来,每次网络请求过来就可以先通过从分布式缓存中进行数据读取,减少对数据库的查询压力,提高系统的吞吐量。
2.8 可视化数据管理及分析(Kibana)
Kibana 是为 Elasticsearch 设计的开源分析和可视化平台。你可以使用 Kibana 来搜索,查看存储在 Elasticsearch 索引中的数据并与之交互。你可以很容易实现高级的数据分析和可视化,以图标的形式展现出来。
Kibana 的使用场景,应该集中在两方面:
实时监控
通过 histogram 面板,配合不同条件的多个 queries 可以对一个事件走很多个维度组合出不同的时间序列走势。时间序列数据是最常见的监控报警了。
问题分析
关于 elk 的用途,可以参照其对应的商业产品 splunk 的场景:使用 Splunk 的意义在于使信息收集和处理智能化。而其操作智能化表现在:
搜索,通过下钻数据排查问题,通过分析根本原因来解决问题;
实时可见性,可以将对系统的检测和警报结合在一起,便于跟踪 SLA 和性能问题;
历史分析,可以从中找出趋势和历史模式,行为基线和阈值,生成一致性报告。
2.9 Prometheus
Prometheus 是一套开源的系统监控报警框架。Prometheus 作为新一代的云原生监控系统,相比传统监控监控系统(Nagios 或者 Zabbix)拥有如下优点。
优势
- 易于管理
- 轻易获取服务内部状态
- 高效灵活的查询语句
- 支持本地和远程存储
- 采用 http 协议,默认 pull 模式拉取数据,也可以通过中间网关 push 数据
- 支持自动发现
- 可扩展
- 易集成
好了到了这里,大多已经介绍完了,其他几个大家都是比较常见常使用的技术,就不一一介绍了。
2.10 .Net Core 虚拟化
.Net Core 新一代的.Net Core 跨平台开发框架,可以脱离 windows 环境,搭建在 linux 等平台上,那怎样搭建呢?当然可以使用当前比较流行的 Docker 容器,把.net core 项目虚拟化 搭建在 Docker 容器中运行,不依赖于任何平台和环境,只需要通过命令制作好镜像即可,同时也可以借助K8s
来进行多容器应用部署、编排、更新等。
什么是 k8s 呢?
Kubernetes 是一个开源的,用于管理云平台中多个主机上的容器化的应用,Kubernetes 的目标是让部署容器化的应用简单并且高效(powerful),Kubernetes 提供了应用部署,规划,更新,维护的一种机制。
Kubernetes 一个核心的特点就是能够自主的管理容器来保证云平台中的容器按照用户的期望状态运行着(比如用户想让 apache 一直运行,用户不需要关心怎么去做,Kubernetes 会自动去监控,然后去重启,新建,总之,让 apache 一直提供服务),管理员可以加载一个微型服务,让规划器来找到合适的位置,同时,Kubernetes 也系统提升工具以及人性化方面,让用户能够方便的部署自己的应用(就像 canary deployments)。
现在 Kubernetes 着重于不间断的服务状态(比如 web 服务器或者缓存服务器)和原生云平台应用(Nosql), 在不久的将来会支持各种生产云平台中的各种服务,例如,分批,工作流,以及传统数据库。
在 Kubenetes 中,所有的容器均在 Pod 中运行, 一个 Pod 可以承载一个或者多个相关的容器,在后边的案例中,同一个 Pod 中的容器会部署在同一个物理机器上并且能够共享资源。一个 Pod 也可以包含 O 个或者多个磁盘卷组(volumes), 这些卷组将会以目录的形式提供给一个容器,或者被所有 Pod 中的容器共享,对于用户创建的每个 Pod, 系统会自动选择那个健康并且有足够容量的机器,然后创建类似容器的容器, 当容器创建失败的时候,容器会被 node agent 自动的重启, 这个 node agent 叫 kubelet, 但是,如果是 Pod 失败或者机器,它不会自动的转移并且启动,除非用户定义了 replication controller。
用户可以自己创建并管理 Pod,Kubernetes 将这些操作简化为两个操作:基于相同的 Pod 配置文件部署多个 Pod 复制品;创建可替代的 Pod 当一个 Pod 挂了或者机器挂了的时候。而 Kubernetes API 中负责来重新启动,迁移等行为的部分叫做“replication controller”,它根据一个模板生成了一个 Pod, 然后系统就根据用户的需求创建了许多冗余,这些冗余的 Pod 组成了一个整个应用,或者服务,或者服务中的一层。一旦一个 Pod 被创建,系统就会不停的监控 Pod 的健康情况以及 Pod 所在主机的健康情况,如果这个 Pod 因为软件原因挂掉了或者所在的机器挂掉了,replication controller 会自动在一个健康的机器上创建一个一摸一样的 Pod, 来维持原来的 Pod 冗余状态不变,一个应用的多个 Pod 可以共享一个机器。
我们经常需要选中一组 Pod,例如,我们要限制一组 Pod 的某些操作,或者查询某组 Pod 的状态,作为 Kubernetes 的基本机制,用户可以给 Kubernetes Api 中的任何对象贴上一组 key:value 的标签,然后,我们就可以通过标签来选择一组相关的 Kubernetes Api 对象,然后去执行一些特定的操作,每个资源额外拥有一组(很多) keys 和 values, 然后外部的工具可以使用这些 keys 和 vlues 值进行对象的检索,这些 Map 叫做 annotations(注释)。
Kubernetes 支持一种特殊的网络模型,Kubernetes 创建了一个地址空间,并且不动态的分配端口,它可以允许用户选择任何想使用的端口,为了实现这个功能,它为每个 Pod 分配 IP 地址。
现代互联网应用一般都会包含多层服务构成,比如 web 前台空间与用来存储键值对的内存服务器以及对应的存储服务,为了更好的服务于这样的架构,Kubernetes 提供了服务的抽象,并提供了固定的 IP 地址和 DNS 名称,而这些与一系列 Pod 进行动态关联,这些都通过之前提到的标签进行关联,所以我们可以关联任何我们想关联的 Pod,当一个 Pod 中的容器访问这个地址的时候,这个请求会被转发到本地代理(kube proxy), 每台机器上均有一个本地代理,然后被转发到相应的后端容器。Kubernetes 通过一种轮训机制选择相应的后端容器,这些动态的 Pod 被替换的时候,Kube proxy 时刻追踪着,所以,服务的 IP 地址(dns 名称),从来不变。
所有 Kubernetes 中的资源,比如 Pod, 都通过一个叫 URI 的东西来区分,这个 URI 有一个 UID,URI 的重要组成部分是:对象的类型(比如 pod),对象的名字,对象的命名空间,对于特殊的对象类型,在同一个命名空间内,所有的名字都是不同的,在对象只提供名称,不提供命名空间的情况下,这种情况是假定是默认的命名空间。UID 是时间和空间上的唯一。
2.11 自动化集成部署
为什么需要自动化集成部署?
我从以下几点来分析为什么需要自动化集成部署:
- 你要相信的是所有的人工部署、发布、更新都是不可靠的,自动化智能部署可以减少事故率。
- 人为备份、发布更新都是效率非常低的。
- 如果某个项目需要更新,但是这个微服务有十几台负载,那你人为一台一台服务器更新发布是不是很繁琐,更加容易出事故呢?
什么是自动化集成部署?
通过jenkins
、gitlab
、docker
等工具,以及依赖事先写好的脚本监听代码提交动态、自动化构造项目镜像、推送镜像到镜像仓库、Docker 拉起镜像、启动项目等系列自动化脚本处理,可以平滑的一台一台服务停止并且更新;一切操作无需人为的干预,甚至出现问题可以一键回滚操作。
自动化集成部署有哪些优势
- 一切自动化,无需人为干预,提高效率,专业的人做专业的事情,开发做好开发的事情即可,运维做好运维的事情。
- 发布可追溯
- 随时人为干预回滚(通过脚本回顾上一步自动化备份的项目镜像)
- 平滑发布,不影响用户体验,一台一台服务器切断,发布更新。
其他自行百度。