原文网址:https://www.infoq.cn/article/UoWc9uUtVIrm-azWOglu
2019 年 1 月 4 日,腾讯宣布成立技术委员会,也代表之前宣布的架构调整终于拉开序幕。那么中小团队要如何搭建自己的团队架构呢?本文将会对此展开讨论……
平时我们看技术大会上的分享大多高大上,亿级流量、超大型研发团队,虽然值得借鉴,但由于应用场景与研发资源的差异,一般企业并不容易落地。其实,中小型研发团队在 IT 行业还是占大多数,他们在技术架构方面的问题较多,技术阻碍业务、跟不上业务发展的情况非常常见。
我是一个有十多年经验的 IT 老兵,曾在两家几千人的技术团队做过架构与技术管理工作,也曾在几十人至几百人的中小研发团队做过首席架构师和 CTO。一个是定制的劳斯莱斯,一个是大众轿车。在互联网大厂做技术研发,大多只是一个螺丝钉。而在中小研发团队,则比较容易掌控全局。
笔者结合近几年的工作经验,摸索出了一套可直接落地、基于开源、成本低、可快速搭建的框架及架构方案。小团队也能构建大网站,中小研发团队架构实践更贴近于一般程序员的实际情况,更具应用参考价值。
如果说运维是地基,那么框架就是承重墙。农村建住房是一块砖一块砖地往上垒,而城市建大 House 则是先打地基,再建承重墙,最后才是垒砖,所以中间件的搭建和引进是建设高可用、高性能、易扩展可伸缩的大中型系统的前提。
框架篇中的每章主要由四部分组成:它是什么、工作原理、使用场景和可直接调试的 Demo。其中中间件及 Demo 是历经两家公司四年时间的考验,涉及几百个应用,100 多个库 1 万多张表,日订单从几万张到十几万,年 GMV 从几十亿到几百亿。
所有中间件与工具都是基于开源。早期我们也有部分自主研发如集中式日志和度量框架,后期在第二家公司时为了快速地搭建、降低成本、易于维护和扩展,全部改为开源。这样不仅利于个人的学习成长、知识重用和职业生涯,也利于团队的组建和人才的引进。
1、集中式缓存 Redis
缓存是计算机的难题之一,分布式缓存亦是如此。Redis 看起来非常简单,但它影响着系统的效率、性能、数据一致性。
用好它不容易,具体包括:缓存时长(复杂多维度的计算)、缓存失效处理(主动更新)、缓存键(Hash 和方便人工干预)、缓存内容及数据结构的选择、缓存雪崩的处理、缓存穿透的处理等。Redis 除了缓存的功能,还有其它功能如 Lua 计算能力、Limit 与 Session 时间窗口、分布式锁等。我们使用 ServiceStack.Redis 做客户端,使用方法详见 Demo。
2、消息队列 RabbitMQ
消息队列好比葛洲坝,有大量数据的堆积能力,然后再可靠地进行异步输出。它是 EDA 事件驱动架构的核心,也是 CQRS 同步数据的关键。为什么选择 RabbitMQ 而没有选择 Kafka,因为业务系统有对消息的高可靠性要求,以及对复杂功能如消息确认 Ack 的要求。
3、集中式日志 ELK
日志主要分为系统日志和应用日志两类。
试想一下,你该如何在一个具有几百台服务器的集群中定位到问题?如何追踪每天产生的几 G 甚至几 T 的数据?集中式日志就是此类问题的解决方案。
早期我们使用自主研发的 Log4Net+MongoDB 来收集和检索日志信息,但随着数据量的增加,查询速度却变得越来越慢。后期改为开源的 ELK,虽然易用性有所下降,但它支持海量数据以及与编程语言无关的特征。下图是 ELK 的架构图:
4、任务调度 Job
任务调度 Job 如同数据库作业或 Windows 计划任务,是分布式系统中异步和批处理的关键。我们的 Job 分为 WinJob 和 HttpJob:
HttpJob 借助集群巧妙地解决了 WinJob 的单点和发布问题,并集中管理所有的调度规则,调度规则有简单规则和 Cron 表达式。HttpJob 它简单易用,但间隔时间不能低于 1 分钟,毕竟通过 URL 方式来调度并不高效。
下图是 HttpJob 的管理后台:
5、度量工具 Metrics
“没有度量就没有提升”,度量是改进优化的基础,是做好一个系统的前置条件。
Zabbix 一般用于系统级别的监控,Metrics 则用于业务应用级别的监控。业务应用是个黑盒子,通过数据埋点来收集应用的实时状态,然后展示在大屏或看板上。它是报警系统和数字化管理的基础,还可以结合集中式日志来快速定位和查找问题。我们的业务监控系统使用 Metrics.NET+InfluxDB+Grafana。
6、微服务 MSA
微服务是细粒度业务行为的重用,需要与业务能力及业务阶段相匹配。
微服务框架是实现微服务及分布式架构的关键组件,我们的微服务框架是基于开源 ServiceStack 来实现。它简单易用、性能好,文档自动生成、方便调试测试,调试工具 Swagger UI、自动化接口测试工具 SoapUI。
微服务的接口开放采用我们自主研发的微服务网关,通过治理后台简单的配置即可。网关以 NIO、IOCP 的方式实现高并发,主要功能有鉴权、超时、限流、熔断、监控等,下图是 Swagger UI 调试工具:
7、搜索引擎 Solr
分库分表后的关联查询,大段文本的模糊查询,这些要如何实现呢?
显然传统的数据库没有很好的解决办法,这时可以借助专业的检索工具。全文检索工具 Solr 不仅简单易用性能好,而且支持海量数据高并发,只需实现系统两边数据的准实时或定时同步即可。下图是 Solr 的工作原理:
8、更多工具
会使用以上框架并不一定能成为优秀的架构师,但一位优秀架构师一定会使用框架。架构师除了会使用工具外,还需要架构设计思想和性能调优技能。此部分以真实项目为背景,思想方法追求简单有效,内容包括企业总体架构、单个项目架构设计、统一应用分层、调试工具 WinDbg。
1、企业总体架构
当我们有了几百个上千个应用后,不仅仅需要单个项目的架构设计,还需要企业总体架构做顶层思考和指导。
大公司与小商贩的商业思维是一样的,但大公司比较难看到商业全貌和本质。而小公司又缺乏客户流量和中间件的应用场景,中型公司则兼而有之,所以企业总体架构也相对好落地。
企业总体架构需要在技术、业务、管理之间游刃有余地切换,它包括业务架构、应用架构、数据架构和技术架构。
附档是一份脱敏感信息后的真实案例,有参考 TOGAF 标准,但内容以解决公司系统的架构问题为导向、以时间为主线,包括企业商务模型、架构现状、架构规划和架构实施。
2、单个项目架构设计
应用架构设计如同施工图纸,能直接指导工程代码的实施。
上一环是功能需求,下一环是代码实施,这是架构设计的价值所在。从功能需求到用例,到用例活动图,到领域图、架构分层,到核心代码,它们之间环环相扣。做不好领域图可能源自没有做好用例活动图,因为用例活动图是领域图的上一环。关注职责、边界、应用关系、存储、部署是架构设计的核心,下图是具体案例参考:
3、统一应用分层
给应用分层这件事情很简单,但是让一家公司的几百个应用采用统一的分层结构,这可不是件简单的事情。它要做到可大可小、简单易用、支持多种场景,我们使用 IPO 方式:I 表示 Input、O 表示 Output、P 表示 Process,一进一出一处理。
应用系统的本质就是机器,是处理设备,也是一进一出一处理,IPO 方式相对于 DDD 而言更为简单实用。
4、诊断工具 WinDbg
生产环境偶尔会出现一些异常问题,而 WinDbg 或 GDB 就是解决此类问题的利器。调试工具 WinDbg 如同医生的听诊器,是系统生病时做问题诊断的逆向分析工具,Dump 文件类似于飞机的黑匣子,记录着生产环境程序运行的状态。
本文主要介绍了调试工具 WinDbg 和抓包工具 ProcDump 的使用,并分享一个真实的案例。
N 年前不知谁写的代码,导致每一两个月偶尔出现 CPU 飙高的现象。我们先使用 ProcDump 在生产环境中抓取异常进程的 Dump 文件,然后在不了解代码的情况下通过 WinDbg 命令进行分析,最终定位到有问题的那行代码。
先工具再框架,然后架构设计,最后深入公共应用。
公共应用因为与业务系统结合紧密,但又具有一定的独立性,所以一般自主开发,不使用开源也不方便开源。公共应用主要包括单点登录、企业支付网关、CTI 通讯网关(短信邮件微信),下面介绍单点登录和企业支付网关。
1、单点登录
应用拆分后总要合在一起,拆分是应用实施层面的拆分,合成是用户层面的合成,而合成必须解决认证和导航问题。单点登录 SSO 即只需要登录一次,便可到处访问,它是建立在用户系统、权限系统、认证系统和企业门户的基础上。
我们的凭证数据 Token 使用 JWT 标准,以解决不同语言、不同客户端、跨 WebAPI 的安全问题。
2、企业支付网关
企业支付网关集中和封装了公司的各大支付,例如支付宝、财付通、微信、预付款等。它统一了业务系统调用各支付接口的方式,简化了业务系统与支付系统的交互。它将各种支付接口统一为支付、代扣、分润、退款、退分润、补差、转账、冻结、解冻、预付款等,调用时只需选择支付类型即可。
企业支付网关将各大支付系统进行集中地设计、研发、部署、监控、维护,提供统一的加解密、序列化、日志记录和安全隔离。
架构要落地、固化和提升,需要通过技术架构与组织架构的对齐来达成。从生产力到生产关系,从架构师到技术管理,你关注的角度也将发生变化。从关注技术到关注技术的商业价值、技术与业务的匹配与融合、技术团队的文化等等。
本部分内容包括技改之路、技术与业务的匹配与融合、研发团队文化是怎么长出来的,重点会介绍以下 3 个。
1、技改之路:从单块应用到微服务
技改是技术改造的简称,是技术的蜕变。这里指的是在公司技术发展的某个瓶颈阶段,按原有开发和组织方式已经无法玩下去,这时公司希望引进架构师或技术牛人,来破解当前困局。
技改之路少讲技术多讲路,我们不过多地关注技术细节和中间件的实现,而重点讲述技术改造的过程和思考。技改是大折腾,于公司于个人而言都是。小改怡情、大改伤身,所以真正高手下棋,应该是通盘无妙招,让正确的事情很容易发生,基于自然的演化来实现技术的演进。
2、技术与业务的匹配与融合
是什么在驱动公司的发展?
技术说“科学技术是第一生产力”,市场说“没有市场,哪来的业务”,运营说他自己。应该说他们都是正确的,但又不全面。这如同盲人摸象一样,引发了不少的争论,也直接或间接地导致了技术与业务的矛盾。
本文先抛出了一个启发性的问题,然后分析问题出在哪里,理解源于彼此的了解,如何去匹配与融合,最后正面回答了该问题。只有尊重事物的发展规律,加强技术与业务的之间合作,才能促进公司发展。
3、研发团队文化是怎么长出来的
从死气沉沉到激情活力,从固步自封到好学分享,这是一个有关团队文化的主题。寺庙文化传承千百年,舌尖上的美食流传至今,它是如何形成和生长的?是参考大公司或从管理书籍上挑选几个词语,还是脚踏实地、土里吧唧,自己一步一步埋头干?
我们要先弄清遇到的问题,然后是找到解决之道,包括管理工具、制度和行为措施,并予以贯彻并形成一种习惯,最后是总结并归纳成几个可以贴到墙上的大字,即「共治分享自视一起拼,简单有效快」,这个过程就如同花朵一般。只有这样「长」出来的文化,才能管人做事,才能成为公司或团队的执行力。
以上目录顺序不仅是架构改造的参考路径,也是架构师的成长路径。照着做,你也能够成为架构师。本文后续还会涉及框架中的其他部分,对内容进行更详细的延展分析。
我们希望能够尽量降低工具对研发人员的门槛,实现简单实用、降低成本。文章中部分 Demo 采用 C# 或 Java 语言,但到了框架与架构层面,与语言本身没有太多关系。
如 RabbitMQ、Job、Redis 和集中式日志 ELK,它们服务端的部署都是一样的,只是客户端语言版本稍有不同。所有 Demo 在一段时间内都可直接运行,服务地址和管理后台亦可直接访问。
以上这些基础工作,希望能够帮助到中小型研发团队,解决大家项目中遇到的实际问题,也愿与你一起在架构方面有所成长,谢谢!
案例参考和 Demo 下载
下载地址:
https://github.com/das2017?tab=repositories
阅读数:57482017 年 12 月 3 日
日志可分为系统日志、应用日志以及业务日志,系统日志给运维人员使用,应用日志给研发人员使用,业务日志给业务操作人员使用。我们这里主要讲解应用日志,通过应用日志来了解应用的信息和状态,以及分析应用错误发生的原因等。
随着系统的日益复杂,大数据时代的来临,需要几十甚至上百台的服务器是常有的事,因此迫切需要有一套针对日志、且能够集中式管理的产品。ELK 就实现了集中式日志管理平台,该平台统一涵盖了分布式日志收集、检索、统计、分析以及对日志信息的 Web 管理等集中化管控。
ELK 是 Elasticsearch、Logstash、Kibana 的简称,这三套开源工具组合起来能搭建一套强大的集中式日志管理平台。
Elasticsearch 是个开源的分布式搜索引擎,提供搜索、分析、存储数据三大功能。它的特点有:分布式、自动发现、索引自动分片、索引副本机制、RESTful 风格接口、多数据源以及自动搜索负载等。
Logstash 是一个开源的用来收集、解析、过滤日志的工具。支持几乎任何类型的日志,包括系统日志、业务日志和安全日志。它可以从许多来源接收日志,这些来源主要包括 Syslog、消息传递(例如 RabbitMQ)和 Filebeat;能够以多种方式输出数据,这些方式主要包括电子邮件、WebSockets 和 Elasticsearch。
Kibana 是一个基于 Web 的友好图形界面,用于搜索、分析和可视化存储在 Elasticsearch 中的数据。它利用 Elasticsearch 的 RESTful 接口来检索数据,不仅允许用户定制仪表板视图,还允许他们以特殊的方式查询、汇总和过滤数据。
下图是集中式日志管理 ELK 的架构图。出于性能的考虑,选择采用了 Beats+EK 的形式来组合搭建集中式日志管理系统。
Elasticsearch 部署完成后,需要更改 elasticsearch.yml 配置文件中的主要属性:cluster.name、node.name、network.host、discovery.zen.ping.unicast.hosts。其中,当部署 Elasticsearch 时是以集群模式部署的,那么 discovery.zen.ping.unicast.hosts 这个属性才会需要被配置。
通过配置 filebeat-pipeline.conf 文件中的 Input、Filter(可选)和 Output 来完成对数据的采集、过滤和输出,如下图所示:
然后以 filebeat-pipline.conf 文件启用 Logstash 服务,如下图所示:
备注:由于采用的是 Beats+EK 这个方案来实现集中式日志管理,所以不需要配 Logstash。
通过更改 kibana.yml 配置文件内容,用来连接正确的 Elasticsearch 服务地址,通常只需要配置 elasticsearch.url 属性即可,请见下图的第一个图。配置完成后,执行【bin/kibana &】命令启用 Kibana 服务,请见下图的第二个图。最后就可以在浏览器中打开 Kibana 管理页面(访问地址:http://139.198.13.12:4800/)来查看日志。
filebeat.yml 配置文件内容主要包含 Filebeat、Output、Shipper(可选)、Logging(可选)四大部分,其中 Filebeat 主要定义监控的日志文件信息,Output 主要配置日志数据的输出目标。
filebeat.yml 文件中,主要属性值的命名规范如下:
filebeat.yml 的配置示例如下图所示:
日志文件存放在哪台服务器中,filebeat 服务就部署在哪台服务器中。在 windows 操作系统上启用 filebeat 服务的步骤:
1、在 windows 下开启搜索,输入 powershell,打开 powershell 所在文件位置,右键 powershell.exe 以管理员身份运行,进入 PowerShell 窗口。
或者以管理员身份启动 cmd.exe,输入命令 powershell,进入 PowerShell 窗口 。
注意:
请务必确保以管理员身份打开 PowerShell 窗口,否则的话在以下第 2 步中运行.ps1 脚本时,就会报没有权限创建 filebeat 服务的错误:
2、导向到 filebeat 执行程序所在目录,例如:cd 'E:\ELK\filebeat-1.3.0-windows',然后执行命令:powershell.exe -ExecutionPolicy UnRestricted -File .\install-service-filebeat.ps1。
3、之后可以在 PowerShell 窗口中通过以下几个命令来查看、启用以及停止 filebeat 服务:
1、日志存放路径规范:{盘符}:\Log4Net{AppID}\,其中 AppID 即为我们所做项目的六位编码。例如:D:\Log4Net\110107\。
2、log4net.config 配置内容:
复制代码
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
注意了:
基于 Kibana 查询日志(访问地址:http://139.198.13.12:4800/),主要通过以下几个步骤实现:
请参考如下图所示:
阅读数:16332018 年 1 月 15 日
生产环境偶尔会出现一些异常问题,WinDbg 或 GDB 就是解决此类问题的利器。调试工具 WinDbg 如同医生的听诊器,是系统生病时做问题诊断的逆向分析工具,Dump 文件类似于飞机的黑匣子,记录着生产环境程序运行的状态。
本文主要介绍了调试工具 WinDbg 和抓包工具 ProcDump 的使用,并分享一个真实的案例。N 年前不知谁写的代码,导致每一两个月偶尔出现 CPU 飙高的现象。我们先使用 ProcDump 在生产环境中抓取异常进程的 Dump 文件,然后在不了解代码的情况下通过 WinDbg 命令进行分析,最终定位到有问题的那行代码。
WinDbg 是在 Windows 平台下的、强大的用户态和内核态调试工具。相比较于 Visual Studio,它是一个轻量级的调试工具,所谓轻量级指的是它的安装文件大小较小,但是其调试功能,却比 VS 更为强大。
它的另外一个用途是可以用来分析 Dump 数据。WinDbg 是 Microsoft 公司免费调试器调试集合中的 GUI 的调试器,支持 Source 和 Assembly 两种模式的调试。
WinDbg 不仅可以调试应用程序,还可以进行 Kernel Debug。结合 Microsoft 的 Symbol Server,可以获取系统符号文件,便于应用程序和内核的调试。
WinDbg 支持的平台包括 x86、IA64、AMD64。虽然 WinDbg 也提供图形界面操作,但它最强大的地方还是有着强大的调试命令,一般情况会结合 GUI 和命令行进行操作,常用的视图有:局部变量、全局变量、调用栈、线程、命令、寄存器、白板等。其中“命令”视图是默认打开的。
DebugDiag 最初是为了帮助分析 IIS 的性能问题而开发的,它同样可以用于任何其他的进程。DebugDiag 工具主要用于帮助解决如挂起、 速度慢、 内存泄漏或内存碎片,和任何用户模式进程崩溃等问题。
该工具包括附加调试脚本,侧重于互联网信息服务(IIS)应用程序、 Web 数据访问组件、 COM+ 和相关 Microsoft 技术、SharePoint 和.NET。它提供可扩展对象模型中的 COM 对象的形式,并具有一个内置的报告框架提供的脚本主机。它由 3 部分组成,包括调试服务、 调试器主机和用户界面。
ProcDump 是 System Internal 提供的一个专门用来监测程序 CPU 高使用率从而生成进程 Dump 文件的工具。ProcDump 可以根据系统的 CPU 使用率或者指定的性能计数器来针对特定进程生成一系列的 Dump 文件,以便调试者对事故原因进行分析。
复制代码
|
|
|
|
|
|
|
|
|
有以下四种方式获取 Dump 文件,具体如下:
1、通过【任务管理器】获取 Dump 文件,这样获取的是 MinDump
2、利用 WinDbg 的 adplus 获取 Dump 文件,这样获取的是 FullDump
3、通过 DebugDiag 创建.NET 异常转储 Dump 文件
4、通过 ProcDump 抓取异常线程 Dump 文件。
现在重点介绍通过 ProcDump 抓取异常线程 Dump 文件,使用方法如下:
4.1、命令行
复制代码
|
|
|
|
|
|
|
|
|
|
|
实例:
复制代码
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
下图是在 WindgbHighCpu 进程中造成 High CPU 时运行 ProcDump 命令的运行效果,可以看到在 CPU 每次持续 5 秒达到 5% 后就会生成相应的 Dump 文件,共生成了 3 份 Full Dump 文件:
注意:
复制代码
|
解决方法是将 Debugging Tools for Windows (WinDbg) 安装目录下的 dbghelp.dll 拷贝到 procdump.exe 所在目录下,然后再运行命令抓取 Dump。
操作步骤如下:
1、抓取异常程序的 Dump 文件。
2、设置符号表
符号表是 WinDbg 关键的“数据库”,如果没有它,WinDbg 基本上就是个废物,无法分析更多问题。所以使用 WinDbg 设置符号表,是必须要走的一步。
a、运行 WinDbg 软件,然后按【Ctrl+S】弹出符号表设置窗。
b、将符号表地址:SRV*C:\Symbols*
http://msdl.microsoft.com/download/symbols 粘贴在输入框中,点击确定即可。点击确定之前,请先确认红色字的文件夹是否已被新建。
注:红色字表示符号表本地存储路径,建议固定路径,可避免符号表重复下载。
3、学会打开第一个 Dump 文件!
使用【Ctrl+D】快捷键,或者点击 WinDbg 界面上的【File=>Open Crash Dump...】按钮,来打开一个 Dump 文件。
当你想打开第二个 Dump 文件时,可能因为上一个分析记录未清除,导致无法直接分析 Dump 文件,此时你可以使用快捷键【Shift+F5】来关闭上一个对 Dump 文件的分析记录。
4、通过简单的几个命令学会分析 Dump 文件
分享一个数据库连接超时的 Dump 案例的分析过程:
当你打开一个 Dump 文件后,可能因为太多信息,让你无所适从,不过没关系,我们只需要关注几个关键信息就可以了。
a. 加载 SOS 扩展命令
加载 SOS 之前,先确定 SOS 的位置和版本,确定方法如下:
如果安装了 Visual Studio,那么先按照如下步骤打开 VS 的命令行:
然后,在打开的 VS 命令行中输入 where sos.dll,使获得 SOS 的位置和版本:
确定完 SOS 位置和版本号后,开始加载 SOS 扩展命令:
复制代码
|
如下图所示:
b. 使用!clrstack 命令来查看当前的调用堆栈信息
如下图所示:
c. 使用!dso 命令来查看堆栈上的所有对象详细信息
如下图所示:
综合以上分析可以大胆地猜测 Common.cs 中第 16 行“Data Source=***;Initial Catalog=***;Persist Security Info=True;User ID=sa;Password=***”的这个数据库连接字符串应该有问题,然后到代码中相应的地方进一步确认和修改就可以了。
分享一个笔者工作过的公司的某业务系统使 CPU 飙高 90% 或以上的 Dump 案例的分析过程,步骤如下:
1、使用 ProcDump 抓包
2、加载 SOS 扩展命令:
复制代码
|
3、分析:
执行!runaway 命令,查看线程使用 CPU 时间情况,如下图所示。着重分析前面几个线程。
执行~22s 命令,进入到线程 22,如下图所示:
执行!clrstack 命令查看当前线程堆栈变量值的信息,从图中可以猜出大概是 ExecuteNonQuery() 这方法有点问题,如下图所示:
再执行!dso 命令可以查看堆栈上的所有对象详细信息,如下图所示:
从图中看,造成 CPU 飙高的罪魁祸首多半由 SQL Server 执行
复制代码
|
这条语句时产生异常引起,然后到源代码中找出相应的语句,经过进一步的确认、修改和重新发布后就解决了 CPU 飙高的问题。
至此,掌握几个简单的 WinDbg 命令之后,基本上绝大多数 Dump 大家都可以独立分析了。当然 WinDbg 是个强大的工具,同时产生 CPU 飙高和内存泄漏的原因也有很多。如果想分析得足够准确,那么就只有多学多练,多去分析。因为掌握 WinDbg 分析除了需要懂得几个命令之外,经验更加重要,最后再补充两点:
阅读数:39972017 年 12 月 11 日
应用监控系统 Metrics 由 Metrics.NET+InfluxDB+Grafana 组合而成,通过客户端 Metrics.NET 在业务代码中埋点,Metrics.NET 会把收集到的数据存储在 InfluxDB 数据库中,然后通过 Grafana 来展示监控数据。
其中,InfluxDB 服务端部署的版本号是 1.3.1,Grafana 部署的版本号是 4.0.1。下面将结合这 3 个工具来介绍如何实现对应用的监控。
Metrics.NET 移植自 Java 的 metrics,它是一个给 CLR 提供度量的工具包。在业务代码中埋点 Metrics.NET 代码后,就可以方便地对各技术指标、业务指标进行度量,如:共花多长时间完成某方法的执行、某方法在被执行的过程中共出现过几次异常、某时间段内共下多少订单量。
Metrics.NET 共提供 5 种度量类型:Gauge、Counter、Meter、Histogram 以及 Timer。其中 Meter 和 Histogram 这两种度量类型目前可以完全满足笔者所在公司的度量需求,所以,下面只介绍了 Meter 和 Histogram 这两种,另外 3 个若有兴趣可自行抽空去了解。
首先为需要收集 Metrics.NET 监控数据的业务项目引用 Metrics.dll。
然后,在项目中的 App.config/Web.config 文件中加上如下配置信息:
复制代码
|
|
|
|
|
|
|
|
|
Meter 用于度量 TPS(每秒处理的请求数)。
示例:模拟统计成功下单量、下单金额、失败下单量。
调用 Meter 对象的 Mark() 方法:
复制代码
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Histogram 用于度量流数据中 Value 的分布情况,它不仅使您能像 Meter 一样测量出 TPS ,还能测量出最小值、最大值和平均值。使用场景如:统计服务器的延迟时间、统计某方法共执行多长时间。
示例:模拟统计航班查询引擎方法的耗时情况。
调用 Histogram 对象的 Update() 方法:
复制代码
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
查阅 Metrics Dashboard Demo 的地址:http://139.198.13.12:4127/。打开这个 Metrics 地址后,如果页面显示已登录状态,那么在开始查阅前,请先确认是否把组织切换到了 Default Org.:
点击位于下图上方的 Home 图标,会下拉弹出 Dashboard 列表:
点击位于上图下方的 Create New 按钮,会进入到新建面板 Panel 页面,点击位于下图上方的保存图标按钮:
在弹出的 Save As... 对话框中输入 Dashboard 名称,如 Arch.OrderCountDemo,然后点击 Save 按钮进行保存:
点击上面创建的【Arch.OrderCountDemo】Dashboard 图标,进入属于这个 Dashboard 的面板(Panel)页面:
点击位于上图的 ADD ROW 按钮,进入下图。其中,Graph 表示以图表(有折线图、柱状图、散点图、梯形图)形式展示数据、Singlestat 表示单个统计、Table 表示以表格形式展示数据、PieChart 表示以饼状图形式展示数据。这几种统计类型的面板设置方式类似,本文将以 Graph 为例进行说明。
2.1、数据设置
点击上图的 Graph 图标创建图表:
点击上图的 Panel Title,在弹出菜单中单击 Edit 打开 Panel 编辑界面,即进入 Metrics 选项卡面板。关于 Meter 的查询数据语句配置一般如下:
关于 Histogram 的查询数据语句配置一般如下:
其中,fill() 一般被设为 null,但当查询时间范围很大时(如 1 天),请用 fill(0);另外,appId、appId、serverIP、$summarize 这 3 个变量是在模板(Templating)中设置,请看第 3 小节的介绍。
2.2、样式配置
2.2.1、General 选项卡用来设置 Panel 样式
主要用来设置 Panel 的标题:
2.2.2、Axes 选项卡用来设置坐标轴
Label 表示设置左侧 Y 轴旁显示什么说明文字,另外,Unit 表示设置左侧 Y 轴数字的单位:
2.2.3、Legend 选项卡用来设置显示样式
2.2.4、Display 选项卡用来设置图表样式
Draw options 子选项卡用来设置图表显示效果:
打开 Templating 设置页面:
新建变量:
新建 serverIP 变量:
(在 Query 文本框处,输的是:SHOW TAG VALUES WITH KEY = "ServerIP")
新建 summarize 变量,其中 Values 值可以自行添加或删除,值与值之间用英文状态的逗号隔开:
新建 adhoc 变量:
一个 Dashboard 中,除了需要显示实时监控数据外,有时还需要显示历史的监控数据,主要目的是要通过对历史监控数据的观察来预测未来的业务量走势,那么需要重写 Time Range,即需要在 Time range 选项卡中进行设置。
例如,在一个 Panel 中需要显示近 24 小时的历史监控数据,那么请在这个 Panel 中加上如下配置:
在 Grafana 当前版本(4.0.1)中,告警目前仅支持 Graph 类型的面板,在将来版本会添加 Singlestat 和 Table 类型面板的支持。另外,由于告警查询语句不支持 template 变量,所以最好是对不使用 template 变量的 Panel 才设置告警。
5.1、设置通知规则
在左侧菜单中选择 Alerting -> Notifications 进入通知列表页:
点击 New Notification 按钮新建一个通知:
在 Name 文本输入框中,输入通知名称,类型 Type 选择 email。设置完成之后单击 Save 按钮,然后点击 Send Test 按钮测试下通知是否能够发送成功。
5.2、设置告警规则
进入需要添加告警的 Panel 的编辑界面,转到 Alert 选项卡,点击 Create Alert 按钮,进入 Alert Config 子选项卡界面进行配置,其中 Evaluate every 表示设置执行频率,Conditions 表示配置何时告警的条件(WHEN 是选择聚合函数的地方,OF 用来设置时间段,IS ABOVE 或者 IS BELOW 用来设置阈值)。对 Alert Config 子选项卡界面的配置参考如下:
然后在 Notifications 子选项卡界面中配置通知规则:
5.3、暂停告警操作
在左侧菜单中点击 Alerting -> Alert List 进入告警规则列表页,点击暂停图标按钮就可以停止该告警:
六、Demo 下载及更多资料
阅读数:79382017 年 11 月 30 日
使用过分布式中间件的人都知道,程序员使用起来并不复杂,常用的客户端 API 就那么几个,比我们日常编写程序时用到的 API 要少得多。但是分布式中间件在中小研发团队中使用得并不多,为什么会这样呢?
原因是中间件的职责相对单一,客户端的使用虽然简单,但整个环境搭起来却不容易。所以对于系列中的几篇中间件文章,我们重点放在解决门槛问题,把服务端环境搭好(后期可云或运维解决),把中间件的基本职责和功能介绍好,把客户端 Demo 写好,让程序员抬抬脚,在调试代码中即可轻松入门。
根据我们以往几年的经验,初次接触也可以自主快速学习,文章和 Demo 以实用为主,以下是消息队列 RabbitMQ 的快速入门及应用。
1、业务系统往往要求响应能力特别强,能够起到削峰填谷的作用。
2、解耦:如果一个系统挂了,则不会影响另外个系统的继续运行。
3、业务系统往往有对消息的高可靠要求,以及有对复杂功能如 Ack 的要求。
4、增强业务系统的异步处理能力,减少甚至几乎不可能出现并发现象:
使用消息队列,就好比为了防汛而建葛洲坝,有大量数据的堆积能力,然后可靠地进行异步输出。例如:
传统做法存在如下问题,请见上图:
使用 MQ 后的好处,请见上图:
定时从数据库获取数据后,存入 MQ 消息队列,然后 Job 会定期扫描 MQ 消息队列,假设 Job 扫描后先预取 5 条消息,然后异步处理这 5 条消息,也就是说这 5 条消息可能会同时被处理。
RabbitMQ 是基于 AMQP 实现的一个开源消息组件,主要用于在分布式系统中存储转发消息,由因高性能、高可用以及高扩展而出名的 Erlang 语言写成。
其中,AMQP(Advanced Message Queuing Protocol,即高级消息队列协议),是一个异步消息传递所使用的应用层协议规范,为面向消息的中间件设计。
RabbitMQ 特点如下:
高可靠:RabbitMQ 提供了多种多样的特性让你在可靠性和性能之间做出权衡,包括持久化、发送应答、发布确认以及高可用性。
高可用队列:支持跨机器集群,支持队列安全镜像备份,消息的生产者与消费者不论哪一方出现问题,均不会影响消息的正常发出与接收。
灵活的路由:所有的消息都会通过路由器转发到各个消息队列中,RabbitMQ 内建了几个常用的路由器,并且可以通过路由器的组合以及自定义路由器插件来完成复杂的路由功能。
支持多客户端:对主流开发语言(如:Python、Ruby、.NET、Java、C、PHP、ActionScript 等)都有客户端实现。
集群:本地网络内的多个 Server 可以聚合在一起,共同组成一个逻辑上的 broker。
扩展性:支持负载均衡,动态增减服务器简单方便。
权限管理:灵活的用户角色权限管理,Virtual Host 是权限控制的最小粒度。
插件系统:支持各种丰富的插件扩展,同时也支持自定义插件,其中最常用的插件是 Web 管理工具 RabbitMQ_Management,其 Web UI 访问地址:
http://139.198.13.12:6233/,
登录账号:flight,密码:yyabc123。
消息从发送端到接收端的流转过程即 RabbitMQ 的消息工作机制,请见下图:
消息发送与接收的工作机制
共有 6 种基本用法:单对单、单对多、发布订阅模式、按路由规则发送接收、主题、RPC(即远程存储调用)。我们将介绍单对单、单对多和主题的用法。
1、单对单:单发送、单接收。请见下图。
2、单对多:一个发送端,多个接收端,如分布式的任务派发。请见下图:
3、主题:Exchange Type 为 topic,发送消息时需要指定交换机及 Routing Key,消费者的消息队列绑定到该交换机并匹配到 Routing Key 实现消息的订阅,订阅后则可接收消息。只有消费者将队列绑定到该交换机且指定的 Routing Key 符合匹配规则,才能收到消息。
其中 Routing Key 可以设置成通配符,如:* 或 #(* 表示匹配 Routing Key 中的某个单词,# 表示任意的 Routing Key 的消息都能被收到)。如果 Routing Key 由多个单词组成,则单词之间用. 来分隔。
交换机名的命名建议:Ex{AppID}.{自定义 ExchangeName},队列名的命名建议:MQ{AppID}.{自定义 QueueName} 。
RabbitMQDemo 下载地址:https://github.com/das2017/RabbitMQDemo
RabbitMQ 的官方网址:http://www.rabbitmq.com
阅读数:37002018 年 1 月 7 日
应用分层这件事情看起来很简单,但每个程序员都有自己的一套,哪怕是初学者。如何让一家公司的几百个应用采用统一的分层结构,并得到大部分程序员的认同呢?这可不是件简单的事情,接下来以我们真实案例与大家一起探讨,先问大家两个技术问题:
服务的调用代码你觉得放到哪一层好呢?
如何组织好 VO(View Object 视图对象)、BO(Business Object 业务对象)、DO(Data Object 数据对象)、DTO(Data Transfer Object 数据传输对象) 呢?
不同的人会有不同的答案,所以要统一公司应用分层,以减少开发维护学习成本。统一应用分层要可大可小、简单易用、支持多种场景,我们采用 IPO 方式:I 是 Input、O 是 Output、P 是 Process,一进一出一处理。应用系统的本质是机器,是处理设备,一进一出一处理。
IPO 原理图
统一应用分层的逻辑架构图
职责说明:
此规范我们用了四年,牵涉几百个应用,200 多个研发人员,是一个成功的实践。接下来就借用本文提供下载的 TripOrderService、TripSellerMVCSite 这两个 Demo 来进行具体规范的说明,以下是截图:
项目命名规则:{产品线英文名全称}.{子系统英文名全称 + 应用名}.{项目职责英文名全称},如:Trip.Seller.DTO。
规范说明:
规范说明:
数据传输对象 DTO 规范
规范说明:
视图对象 VO 规范
规范说明:
业务对象 BO 规范(可选)
BO 实体类名以 Model 为结尾:
规范说明:
数据对象 DO 规范(可选)
规范说明:
规范说明:
规范说明:
规范说明:
问:服务的调用代码应该放到哪一层呢?A 表现层、B 业务逻辑层 、C 数据层、D 公共层。
我们的规范是统一放到数据资源访问层即 C。上层提供服务,下层调用服务,中间处理业务逻辑。
问:如何组织好 VO(View Object 视图对象)、BO(Business Object 业务对象)、DO(Data Object 数据对象)、DTO(Data Transfer Object 数据传输对象) 呢?
通常有两种做法,限定访问范围和不限定访问范围,实际项目中可根据需要选择、折中或裁剪。我们使用后者,将 EntityLayer 作为通用对象放到左侧,具体可参考实体层规约:
“DO 是数据表对象,不是数据访问层对象,不是只能给数据访问层使用;DTO 是网络传输对象,不是表现层对象,不是只能给表现层使用;BO 是内存计算逻辑对象,不是业务逻辑层对象,不是只能给业务逻辑层使用 。如果仅限定在本层访问,则导致单个应用内大量没有价值的对象转换。以用户为中心来设计实体类,可以减少无价值重复对象和无用转换。”
问:应用分层范例代码的编写需要注意些什么?
应用分层范例的代码要想写好,非常不容易,很容易引起争议,很难让所有人满意。我们在具体实践时遵循以下几点:
应用分层范例的主要价值是明确层的职责和交互,每个层的职责是什么,哪些要干,哪些不要干,以及层与层之间依赖和交互;
私人定制:减少通用帮助类的编写,如果每一个应用中有大量相同的帮助类,这在架构层面上是有问题。在我们的几百个线上应用中,尽管减少通用的代码,包括分页帮助类、数据库帮助类、缓存帮助类、MQ 帮助类、日志帮助类、AOP 帮助类、线程帮助类。业务应用的重点是为业务服务,每一个应用都是特别的,都需要私人定制,极少有通用的代码,如果有,那么应该由框架或组件专门解决;
少即是多:应用的场景多,参考人员多,每个人想法不同,牵涉的时间长,所以尽量只做大家都认同的规范、正确的事情,要自底向上、要减少有争议的代码范例,否则一个错误将会放大百倍、一个有争议的规范将会很难推行。
追求简单:代码编写可分为三个层次,简单、复杂、简单。第一简单是不知道的简单,第二个复杂是知道后的复杂,第三个简单是知道后有取舍的简单。范例代码要追求简单,既可轻松扩展支持复杂场景,又要简单到初级程序员也能操作。
内聚大于解耦:内聚是什么,内聚是部门内有共同的目标,然后大家紧密合作。解耦是什么,解耦是部门间各自职责明确,然后减少不必要的连接。一个应用如同一个部门,应有一个共同的目标和职责,然后大家紧密合作。
换句话说,应用内部应减少不必要契约接口(如同公司间才签约合同),减少不必要的依赖注入实现,减少不必要且代价过大的解耦。一切以简单实用为主,以应用价值输出、应用的目标(接口或界面)为导向。
LayerDemo 下载地址:https://github.com/das2017/LayerDemo
阅读数:47022018 年 1 月 1 日
Dapper.NET 是个开源的轻型 ORM。它扩展了 IDbConnection 接口的功能,所以只要某类实现 IDbConnection 接口,那么该类对象就能调用到 Dapper.NET 中的方法。提供的 Dapper.dll,支持.NET Framework 4.0 版本及其上版本。
Performance of SELECT mapping over 500 iterations - POCO serialization:
Performance of SELECT mapping over 500 iterations - dynamic serialization:
提供的 Demo 都是关于 Dapper.NET 的最最基本的用法。首先,在你需要用到 Dapper.NET 的项目中引用 Dapper.dll,请见下图。然后在需要使用 Dapper.NET 的代码文件中加上【using Dapper;】。
提供的 Demo 包括了如下主题:
比如,为了能够从数据库中获取数据,某一个基于 Windows Communication Service 的服务需要将数据库实体对象映射到数据协议对象上。对象—对象映射的一种传统做法就是创建许多数据转换对象。这些对象负责在众多数据对象之间复制数据。对于拥有大量数据对象的程序而言,开发人员需要花费大量的时间精力编写大量的数据转换对象来支持数据对象映射。这一过程非常无聊沉闷,而且容易出现 Bug。而如果你使用对象—对象映射工具,就不需要自己编写那些数据转换对象。
EmitMapper 和 AutoMapper 都是支持对象—对象映射的开源工具,主要负责将一个数据对象的数据映射到另外一个数据对象上。提供的 EmitMapper.dll,支持.NET Framework 3.5 版本及其上版本;提供的 AutoMapper.dll,支持.NET Framework 4.5 版本及其上版本。
首先,在需要使用 EmitMapper 的项目中引用 EmitMapper.dll。
基本的使用方法:采用默认的映射配置器 DefaultMapConfig 完成映射操作,不需要指定任何的映射策略。写法主要如下(完整写法请见 BasicUsageDemo.cs):
复制代码
|
|
|
或者:
复制代码
|
|
|
默认的映射配置器能自动转换以下几种类型:
使用 DefaultMapConfig 的自定义配置方法:
如果默认的转换满足不了需求,那么可考虑调用 DefaultMapConfig 提供的配置方法。下表说明了各配置方法的作用:
首先,在需要使用 AutoMapper 的项目中引用 AutoMapper.dll。
提供的 Demo 主要包括如下主题:
EmitMapper 和 AutoMapper 各有千秋:
EmitMapper 官网上虽然有多年的时间没有更新,但它的性能却十分高(接近硬编码)。下图显示的结果是通过笔者电脑运行出来的结果,发现 EmitMapper 的映射速度比 AutoMapper 的快很多(被比较的 AutoMapper 版本号是 5.1.1)。
AutoMapper 虽然性能比不过 EmitMapper,但官网上一直保持着更新状态。
Autofac 是一款轻量级的开源 IoC 容器,它主要负责管理类之间的依赖关系、管理对象的生命周期等,降低应用程序组件间的耦合性,提高类、组件的扩展性、可重用性。
在我们的软件系统中通常都是通过 N 多个对象(系统、模块、对象)的共同协作来最终实现我们的业务系统。N 多个对象的协作肯定会产生或多或少的耦合(依赖),降低对象之间的耦合是我们软件工程永远追求的目标之一。
a. 上层模块不应该依赖于下层模块,它们应该共同依赖于一个抽象。b. 抽象不应该依赖于具体,具体依赖于抽象。
Inversion of Control:控制反转,反转的是对依赖对象的控制权。
如果 A 依赖 B 的话,按照之前的做法是在类 A 中需要 B 的地方主动实例化一个 B 对象。现在的做法是类 A 中需要一个 B 对象,IoC 容器初始化一个 B 对象传给类 A。创建依赖对象的职责从类 A 转移到了 IoC 容器里面。
可以用不同的方式实现 IoC,其中一种实现策略是依赖注入。那么依赖注入是什么?把耦合从代码中转移到配置文件中,通过一个 IoC 容器,在需要的时候再去形成这个依赖关系,即在程序中把需要的接口实现注入到需要它的类中。这就是依赖注入。
NuGet 是 Visual Studio 的一个扩展。在使用 Visual Studio 开发基于.NET Framework 的应用时,NuGet 能把在项目中添加、移除和更新引用的工作变得更加快捷方便。
1、设置 NuGet 服务器
右键需要添加引用的项目文件 -> 管理 NuGet 程序包,便打开了如下图所示的弹出框,然后点击【设置】按钮:
添加程序包源,即添加公司内部的 NuGet 服务器名和其地址【http://nuget.***.***/nuget】:
2、添加组件引用
在下图左侧的联机列表中,选中在上步设置的 NuGet 服务器名【***NuGet】,然后在下图中间的列表中选中要添加的引用的组件名,再通过点【安装】按钮把相应的组件引用添加到项目中:
3、更新组件引用
在下图左侧的更新列表中,选中在前面步骤中设置的 NuGet 服务器名【***NuGet】,然后在下图中间的列表中选中要重新添加引用的组件名,再通过点【更新】按钮把相应的组件引用重新添加到项目中:
4、包管理
管理包时需要用到 NuGetPackageExplorer,下载地址:位于本文的【下载资源】处。
新建包:
a、打开 NuGet Package Explorer,单击【创建一个新的组件包】:
b、将需要打包的组件引用拖放到【Package contents】区域:
c、单击位于界面左上角的【Edit Metadata】按钮后,进入如下图所示的编辑界面。
在【Package metadata】区域中编辑好组件的相应信息,然后点绿色的勾,然后点击 FILE->Save 保存;其中,包名(即包 Id 号)的命名规范建议是:{产品线英文名全称}.{AppID}.{***}:
d、组件发布
点击 FILE->Publish 后,在弹出如下图的所示框中,发布地址输入:http://nuget.***.***/,在 Publish Key 文本框处输入密码:
更新包:
a、打开 NuGet Package Explorer,单击从【从在线源中打开一个包】:
b、在 Package source 文本框处默认显示了【http://nuget.***.***/nuget】,即公司内部的 NuGet 服务器地址,再单击【Reload】按钮;然后,在出现的包列表中选中将要编辑的包,然后双击它或者单击【open】按钮:
c、单击位于界面左上角的【Edit Metadata】按钮后,进入如下图所示的编辑界面。
在编辑界面的【Package metadata】区域中,在【Version】文本框中增大版本号。然后,在编辑界面的【Package contents】区域中,右键需要更新的引用,然后在弹出的快捷菜单中单击【Replace with...】来完成重新上传最新的包的操作:
d、编辑完成之后,单击位于上图左上角的绿色勾,然后单击 FILE->Publish 进行发布工作。
Dapper.NETDemo 下载地址:https://github.com/das2017/DapperDemo
EmitMapperDemo 和 AutoMapperDemo 下载地址:https://github.com/das2017/ObjectMapperDemo
AutofacDemo 下载地址:https://github.com/das2017/AutofacDemo
NuGetPackageExplorer 下载地址:https://github.com/NuGetPackageExplorer/NuGetPackageExplorer
Dapper.NET:https://github.com/StackExchange/Dapper
EmitMapper:http://emitmapper.codeplex.com/
AutoMapper:https://github.com/AutoMapper/AutoMapper
Autofac 文档:http://docs.autofac.org/en/latest/
Autofac:https://github.com/autofac/Autofac
阅读数:48282018 年 1 月 4 日
当每月发布次数变得越来越多时,如超过 200 次,发布工作人员的工作量会翻倍,此时由人工发布操作失误引起的风险会变得越来越大。为了提高项目的发布效率,也为了降低由人工操作失误带来的风险,需要引进持续集成工具。
Jenkins 是一个用 Java 语言编写的开源持续集成工具,最开始被称作 Hudson。Jenkins 在持续集成领域市场份额中居于主导地位,被各种大小规模的团队用于用各种语言实现的各类项目中,语言包括.NET、Java、Ruby、Groovy、Grails、PHP 等。选择 Jenkins 的理由如下:
1、Jenkins:持续集成工具。
2、Git:源代码管理工具,是目前流行的分布式版本控制系统。需要安装的 Jenkins 插件有:
3、TFS:可选,源代码管理工具。
4、MSBuild:Visual Studio 中自带的一个程序编译组件。需要安装的 Jenkins 插件是 MSBuild Plugin 插件。
5、FTP:可选,通过 FTP 把编译好的发布文件部署到应用服务器中。需要安装的 Jenkins 插件是 Publish Over FTP 插件。
6、Jenkins 角色及权限管理:需要安装的 Jenkins 插件是 Role-based Authorization Strategy 插件。
7、Python 脚本:自写的 Python 脚本放在 Jenkins 服务器中。可以实现 Jenkins 把编译好的发布文件部署到远程应用站点服务器,以及实现回滚操作 Rollback。
8、PxExec.exe 工具:装在 Jenkins 服务器中,利用这个工具,可以在远程服务器中执行命令如 xcopy。
9、SoapUI 自动化测试:用于接口测试自动化,同时需要安装的 Jenkins 插件是 HTML Publisher plugin 插件。
10、回滚操作 Rollback:需要安装的 Jenkins 插件是 Build with Parameters,用于指定哪个项目回滚到哪个备份版本。
Email 是 Jenkins 最基本的通知技术。什么情况下,需要 Jenkins 发送电子邮件通知?例如,在一个构建失败(例如因为编译错误)后。
首先设置全局角色和项目角色,其中 Pattern 是用来设置构建作业名的命名规范,例如:规定了构建作业名的命名规范是{发布环境}.{产品线英文名全称}.{项目名},那么要发到生产环境、属于 Trip 产品线的所有构建作业,其 Pattern 设置的值为【(?i)prod.trip.*】,表示构建作业名必须以 prod.trip 开头,而且不区分大小写,用于发布到生产环境。
然后,分别为 Jenkins 账号分派全局角色和项目角色:
Jenkins 通过运行自写的 Python 脚本把编译好的发布文件部署到远程应用站点服务器中,以及同步到集群内其他应用站点服务器,所以需要新增构建步骤配置,参考如下:
其中,.py 脚本(即 Python 脚本)内容如下:
.py 脚本实现了如下逻辑:
第 1 步、备份:
在远程应用站点服务器中,备份将要部署新版本的那个应用系统的所有文件。利用 PxExec.exe 工具,让 Jenkins 服务器远程连到应用站点服务器。然后在这台应用站点服务器中,利用 xcopy 命令,把将要部署新版本的这个应用系统站点目录之下的所有文件拷贝到这台应用站点服务器中的备份目录下。
第 2 步、部署:
部署到这台远程应用站点服务器。先利用 xcopy 命令,把由 Jenkins 编译好的、位于 Jenkins 服务器的文件拷贝到这台应用站点服务器共享目录之下,以.config 结尾的配置文件不会被拷贝。再利用 PxExec.exe 工具,让 Jenkins 服务器远程连到这台应用站点服务器。然后在这台应用站点服务器中,利用 xcopy 命令,把临时存放目录下的文件拷贝到这个应用系统站点目录之下。
第 3 步、同步:
同步发布文件到该应用系统集群内的其他应用站点服务器。利用 PxExec.exe 工具,让 Jenkins 服务器远程连到这台应用站点服务器,然后在这台应用站点服务器中,利用 xcopy 命令,把该应用系统站点目录下的所有文件拷贝到集群内的其他应用站点服务器的该应用系统站点目录之下。
测试用例提交到版本库(如 Git)后,通过 Jenkins 把它编译,编译后,通过 SoapUI 一键调用,开始自动化测试。一旦自动化测试完成,会生成报表,通过 HTML Report 把它给呈现出来,如下图所示。
General 配置:
构建配置:
选择将要回滚哪个项目以及回滚到哪个备份版本号:
以上三个问题也可以借助其它工具来实现,分别是数据库发布工具、集中式配置服务、流程管理工具甚至邮件确认。
阅读数:52472017 年 11 月 8 日
如果你正好处在中小型研发团队……
中小型研发团队很多,而社区在中小型研发团队架构实践方面的探讨却很少。中小型研发团队特别是 50 至 200 人的研发团队,在早期的业务探索阶段,更多关注业务逻辑,快速迭代以验证商业模式,很少去关注技术架构。
这时如果继续按照原有的架构及研发模式,会出现大量的问题,再也无法玩下去了。能不能有一套可直接落地、基于开源、成本低,可快速搭建的中间件及架构升级方案呢?
我是一个有十多年经验的 IT 老兵,曾主导了两家公司的技术架构升级改造,现抛砖引玉,与大家一起探讨这方面的问题。
在接下来的一段时间里,我会陆续推出此系列文章。
根据我们以往的经验,分享者主讲一个小时左右,业务研发就可以快速地进入项目实战。对于后面新加入的团队成员,也可通过 WIKI 自主快速学习。这是我们之前对自己的要求,尽量降低工具对人员的要求,简单实用、降低成本。
文章中部分 Demo 采用 C# 语言, 但到了框架或架构层面,与语言本身没有太多直接的关系。如 RabbitMQ、Job、Redis 和集中式日志,它们服务端的部署是一样的,只是客户端语言版本稍有不同。
所有 Demo 都可直接运行,服务地址及管理后台也可直接访问。因为部署在公有云,牵涉到成本费用的问题,我计划持续到明年 3 月底。
这些小小的基础工作,希望能够帮到中小型研发团队,解决大家项目中遇到的实际问题。愿与你一起成长,你的分享和点赞是我此次付出的动力,谢谢!
整个系列文章分为三个部分,包括 框架篇、架构篇 和 公共应用篇。
以下是篇章的具体介绍:
如果说运维是地基,那么框架就是承重墙。农村建住房是一块砖一块砖地往上垒,而城市建大 House 则是先打地基,再建承重墙,最后才是垒砖,所以中间件的搭建和引进是建设高可用、高性能、易扩展可伸缩的大中型系统的前提。
框架篇中的每篇主要由四部分组成:它是什么、工作原理、使用场景 和 可直接调试的 Demo。其中 Demo 及中间件历经两家公司四年时间的考验,涉及几百个应用,100 多个库 1 万多张表,日订单从几万张到十几万,年 GMV 从几十亿到几百亿。
所有中间件及工具都是基于开源,早期我们也有部分自主研发如集中式日志和度量框架。后期在第二家公司时为了快速地搭建,降低成本,易于维护和扩展,全部改为开源。这样不仅利于个人的学习成长、知识重用和职业生涯,也利于团队的组建和人才的引进。
缓存是计算机的难题之一,分布式缓存亦是如此。Redis 看起来非常简单,但它影响着系统的效率、性能、数据一致性。
用好它不容易,涉及到的问题包括:缓存时长(复杂多维度的计算)、缓存失效处理(主动更新)、缓存键(Hash 和方便人工干预)、缓存内容及数据结构的选择、缓存雪崩的处理、缓存穿透的处理等。
Redis 除了缓存的功能,还有其它功能如 Lua 计算能力、Limit 与 Session 时间窗口、分布式锁等。
消息队列好比葛洲坝,有大量数据的堆积能力,然后再可靠地进行异步输出。它是 EDA 事件驱动架构的核心,也是 CQRS 同步数据的关键。为什么选择 RabbitMQ 而没有选择 Kafka,因为业务系统有对消息的高可靠性要求,以及对复杂功能如消息确认 Ack 的要求。
日志主要分为系统日志和应用日志两类。试想一下,你该如何在一个具有几百台服务器的集群中定位到问题?如何追踪每天产生的几 G 甚至几 T 的数据?集中式日志就是此类问题的解决方案。
早期我们使用自主研发的 Log4Net+MongoDB 来收集和检索日志信息,但随着数据量的增加,查询速度却变得越来越慢。后期改为开源的 ELK,虽然易用性有所下降,但它支持海量数据以及与编程语言无关的特征。下面是 ELK 的架构图。
任务调度 Job 如同数据库作业或 Windows 计划任务,是分布式系统中异步和批处理的关键。我们的 Job 分为 WinJob 和 HttpJob:WinJob 是操作系统级别的定时任务,使用开源的框架 Quartz.NET 实现;而 HttpJob 则是自主研发实现,采用 URL 方式可定时调用微服务。
HttpJob 借助集群巧妙地解决了 WinJob 的单点和发布问题,并集中管理所有的调度规则,调度规则有简单规则和 Cron 表达式。HttpJob 它简单易用,但间隔时间不能低于 1 分钟,毕竟通过 URL 方式来调度并不高效。下图是 HttpJob 的管理后台。
“没有度量就没有提升”,度量是改进优化的基础,是做好一个系统的前置条件。Zabbix 一般用于系统级别的监控,Metrics 则用于业务应用级别的监控。
业务应用是个黑盒子,通过数据埋点来收集应用的实时状态,然后展示在大屏或看板上。它是报警系统和数字化管理的基础,还可以结合集中式日志来快速定位和查找问题。我们的业务监控系统使用 Metrics.NET+InfluxDB+Grafana。
微服务是细粒度业务行为的重用,需要与业务能力及业务阶段相匹配。微服务框架是实现微服务及分布式架构的关键组件,我们的微服务框架是基于开源 ServiceStack 来实现。
它简单易用、性能好,文档自动生成、方便调试测试,调试工具 Swagger UI、自动化接口测试工具 SoapUI。微服务的接口开放采用我们自主研发的微服务网关,通过治理后台简单的配置即可。网关以 NIO、IOCP 的方式实现高并发,主要功能有鉴权、超时、限流、熔断、监控等,下图是 Swagger UI 调试工具。
分库分表后的关联查询,大段文本的模糊查询,这些要如何实现呢?显然传统的数据库没有很好的解决办法,这时可以借助专业的检索工具。
全文检索工具 Solr 不仅简单易用性能好,而且支持海量数据高并发,只需实现系统两边数据的准实时或定时同步即可。下图是 Solr 的工作原理。
会使用以上框架并不一定能成为优秀的架构师,但一位优秀架构师一定会使用框架。架构师除了会使用工具外,还需要设计思想的提升和性能调优技能。
此篇以真实项目为背景,思想方法追求简单有效,主要内容包括 企业总体架构、单个项目架构设计、统一应用分层、调试工具 WinDbg。
当我们有了几百个上千个应用后,不仅仅需要单个项目的架构设计,还需要企业总体架构做顶层思考和指导。大公司与小商贩的商业思维是一样的,但大公司比较难看到商业全貌和本质。而小公司又缺乏客户流量和中间件的应用场景,中型公司则兼而有之,所以企业总体架构也相对好落地。
企业总体架构需要在 技术、业务、管理 之间游刃有余地切换,它包括业务架构、应用架构、数据架构和技术架构。附档是一份脱敏感信息后的真实案例,有参考 TOGAF 标准。但内容以解决公司系统的架构问题为导向、以时间为主线,包括企业商务模型、架构现状、架构规划和架构实施。
单个项目的架构设计如同施工图纸,能直接指导工程代码的实施。上一环是功能需求,下一环是代码实施,这是架构设计的价值所在。从功能需求到用例,到用例活动图,到领域图、架构分层,到核心代码,它们之间环环相扣。
做不好领域图可能源自没有做好用例活动图,因为用例活动图是领域图的上一环。关注职责、边界、应用关系、存储、部署是架构设计的核心,下图是具体案例参考。
给应用分层这件事情很简单,但是让一家公司的几百个应用采用统一的分层结构,这可不是件简单的事情。它要做到可大可小、简单易用、支持多种场景,我们使用 IPO 方式:I 表示 Input、O 表示 Output、P 表示 Process,一进一出一处理。应用系统的本质就是机器,是处理设备,也是一进一出一处理,IPO 方式相对于 DDD 而言更为简单实用。
生产环境偶尔会出现一些异常问题,而 WinDbg 或 GDB 就是解决此类问题的利器。调试工具 WinDbg 如同医生的听诊器,是系统生病时做问题诊断的逆向分析工具,Dump 文件类似于飞机的黑匣子,记录着生产环境程序运行的状态。
主要介绍调试工具 WinDbg 和抓包工具 ProcDump 的使用,并分享一个真实的案例。N 年前不知谁写的代码,导致每一两个月偶尔出现 CPU 飙高的现象。
我们先使用 ProcDump 在生产环境中抓取异常进程的 Dump 文件,然后在不了解代码的情况下通过 WinDbg 命令进行分析,最终定位到有问题的那行代码。
先工具再框架,然后架构设计,最后深入公共应用。公共应用因为与业务系统结合紧密,但又具有一定的独立性,所以一般自主开发,不使用开源也不方便开源。公共应用主要包括单点登录、企业支付网关、CTI 通讯网关(短信邮件微信),此次分享单点登录和企业支付网关。
应用拆分后总要合在一起,拆分是应用实施层面的拆分,合成是用户层面的合成,而合成必须解决认证和导航问题。单点登录 SSO 即只需要登录一次,便可到处访问,它是建立在用户系统、权限系统、认证系统和企业门户的基础上。我们的凭证数据 Token 使用 JWT 标准,以解决不同语言、不同客户端、跨 WebAPI 的安全问题。
企业支付网关集中和封装了公司的各大支付,例如支付宝、财付通、微信、预付款等。它统一了业务系统调用各支付接口的方式,简化了业务系统与支付系统的交互。
它将各种支付接口统一为支付、代扣、分润、退款、退分润、补差、转账、冻结、解冻、预付款等,调用时只需选择支付类型即可。企业支付网关将各大支付系统进行集中的设计、研发、部署、监控、维护,提供统一的加解密、序列化、日志记录,安全隔离。
阅读数:58322017 年 12 月 26 日
企业总体架构是什么?有什么用?具体怎么做?以我曾任职的公司为案例,一起来探讨这个问题。
这家公司当时有 200 位研发人员和 200 多台服务器,我刚进这家公司时,系统已经玩不下去了,总是出现各种问题,例如日常发布系统时或访问量稍微过大时,系统就会出现很多故障,而且找不到故障发生的根本原因。
我进公司后主要的任务就是对这个系统进行升级改造,花了一个半月的时间写了份企业总体架构文档,文档共有 124 页,直接指导了之后的技术改造,下图是那份文档的目录,文末有相关资料下载地址。
企业商务模型的内容主要包括主营业务、商务模式、商务主体、竞品分析、组织架构、商务运作模型和业务流程等。
主营业务即公司做什么业务。
商业模式即公司怎么赚钱。
商务主体即哪几个人在一起做这门生意。
竞品分析即了解竞争对手的情况。
组织架构即公司部门是怎么划分的,组织架构图中标出人数,根据系统与业务之间对应关系,可以了解系统中哪些模块使用频率高,以及业务与其对应模块的复杂度。
商务运作模型即公司是如何运作的,售前做计划,找供应商把东西买进来后,经过服务和结算,再卖给我们的经销商和采购商,使我们获得利润,售后进行大数据分析最后又指导着我们的售前,整个过程形成良性循环。
可以把一家公司想象成一台机器,输进去的是钱,转一转后,又能够生出更多的钱出来。
最后是业务流程和附档资料,业务流程包括预订流程、订单处理流程、产品供应流程、财务结算流程、账户管理流程。企业商务模型的建立,指导着整个应用系统模型的建立,它是整个应用系统建设的基础和前提,毕竟应用系统是为业务服务的。
架构现状的内容主要包括:功能架构、应用架构、数据设计和物理架构。
功能架构主要包括功能、角色和权限三部分。功能是企业服务,用户使用的每一个功能,就是企业的每一个服务。角色是用户操作的归类,功能与角色的对应关系即权限。了解系统架构的现状,从功能架构开始。
应用就是处理器,应用架构的内容包括现有架构图、Web 应用现状、作业小应用(Job)现状和接口架构。其中,接口是应用层面的关键,它是一个程序与另外一个程序交互的部分。
应用架构图表列出了哪些业务逻辑没有被重用,换句话说业务逻辑被多少个应用调用,就需要被重复开发多少次,一旦改了一个地方,就要同时改多个地方,导致系统开发效率非常低下。
各业务逻辑如预订逻辑,虽然被多个应用调用,但它们与应用是没有关系的,业务逻辑可以独立的存在,也可以寄宿于多个应用。业务逻辑是一个业务操作的抽象,而业务应用与业务部门共同完成了业务操作。
100 多个数据库,一万多张表,能否使用一张 E-R 图来表示呢?它是可以的。
数据设计依赖于企业的数据,而不是数据库的设计,对企业数据适当做归类,会直接导致数据设计,最终画出 E-R 图,数据设计完成后,数据库设计就自然而然出来了。
超越库、超越表去看这张 E-R 图,可以看出它包括产品、订单、结算、用户和基础设施这五类数据。低层的 E-R 图可以变,但是高层的 E-R 图一般不会变化,因为它是根据你的业务模型而定,业务模型稳定,高层 E-R 图也是稳定的。
数据库只要早期设计得好,是可以做到易伸缩、易拆分的。下图从内往外看,一个框既可以是一个库,也可以是一个模块,还可以是一个表。
在业务发展的早期它可以是一个库,里面有 5 个模块,中期可以分为 5 个库,后期以更低级别可以分为更多的库,这与业务阶段及系统复杂度相关。在数据的设计完成后,数据库的设计也就很容易规划和调整。
以上是数据库、数据表之间的静态关系,接下来我们介绍数据的流转状态即状态图。通过数据状态图去了解现有数据流转变迁,如国内订单状态变迁图,这种图的价值不仅在于数据库层,还在于服务化。
图中的从等待支付到支付成功,中间有个支付行为,通过这个支付行为把数据状态变更为支付成功,否则继续等待,直到超时关闭订单。这个支付行为可以做成一个微服务,然后由不同的应用去调用。
物理架构的内容主要包括 IDC 机房、机房之间访问关系、机房内服务器物理部署图、机房与业务分布、网站架构、数据库架构、集群清单和域名清单。
将这些内容以列表和图形方式整理出来,就会很容易了解和发现问题,只有发现问题才能解决问题,特别是在全局体系架构方面,这也是表和图的价值所在。
当时这家公司共有 5 个地区、8 个机房,虽然只有 200 多台服务器,但分布很散,导致物理结构复杂,通讯也很复杂。技改前故障不断,其主要的一个原因就是物理架构不合理,运维要占 60%、70% 的责任,当时却把责任归咎为应用架构,这是个错误的方向。
物理架构的不合理,应用架构是很难合理的,因为物理架构是我们的基础设施,位于最底层,下层为上层服务,运维要为应用服务,应用要为业务服务,业务要为客人服务。
领域模型关注概念,关注职责、关注边界、关注交互,只有先确定职责和边界,交互才会很清晰。领域模型是针对现有问题域提出一个系统解决方案,然后在图表上建立完整的模型,如同用 AutoCAD 画的施工图纸一样。
领域模型属于概要设计阶段,对于单个应用架构设计,首先需要了解业务和功能需求、用例图、用例活动图,然后才是领域模型。业务流程图是对业务操作的抽象,领域图是对业务逻辑代码的抽象。
建立领域词汇是建立领域模型的第一步,它能统一词汇明确概念,以减少一词多义、一义多词的情况。概念一旦确定,再扩展属性和行为,然后把它当作一个单元与其它事物构建在一起,就会很容易形成模型,领域模型与企业商务模型中的业务流程图有参考对应关系。
领域模型在实现时可大可小,在业务的早期,在系统比较小的情况下,它有可能是一个类。当系统做大了以后,它可能是个 DLL 库。再做更大一点的时候,它可能是一个服务,给不同的应用去调用。
每一个方法都有成为服务的潜质,特别是在系统中后期。领域模型是业务逻辑代码的施工图纸,它不仅有利于对现在系统业务逻辑的了解,同时也指导未来的架构改造。
当我们了解了业务、了解了架构的现状,发现现有架构的问题,接下来就可以做中远期架构规划,以及架构的调整和具体实施。架构规划内容包括:顶层架构规划、网站功能规划、应用规划、SOA 规划、分层架构规划、数据库规划和物理规划等。
上图是顶层架构的俯视图和侧视图。第一张图是俯视图,坐在飞机上看,整个顶层架构最外层的是功能,中间的是业务操作,内层的是数据。
功能对应业务系统的用户界面,操作对应业务系统里的服务,数据对应业务系统的数据存储如数据库。
第二张图是剖面图,切一刀来看,上层是应用,中层是服务和框架,下层是基础设施数据中心。从图中的服务层可以看出,服务的归类跟业务流程的归类有很大关系。
网站功能规划就是功能的重新划分,对照着架构现状,未来的功能应该如何调整?如案例中的国内网站功能规划,分别画出了全局功能图、采购商功能图、平台商功能图和供应商功能图。
其实在做网站功能规划的时候,更多需要考虑现状,而不是未来调整的部分,如果没有很大问题,则不做调整,尊重历史。因为有些东西(如名称)用户已经使用很久了,调整往往比较难,合理大于准确。
系统是什么?系统 = 元素 + 关系。应用架构是什么?应用架构 = 应用 + 架构。应用就是系统的最小单元,应用分类和应用编号则构成了应用关系即应用的架构。
如上图中的案例,应用分类新建了框架 FX 和公共业务系统 CBS,在原有的 200 多个应用中并没有这两个产品线,而是分布在了不同的业务线中,从而导致重复建设。
应用编号是给每个应用分配一个六位的数字 ID,就如同我们的身份证一样,头两位表示产品线,中间两位表示子系统,最后两位表示应用,如 100206。应用编号是应用管理、依赖和追踪的基础,集中式日志和监控框架都有使用到应用编号。
SOA 规划就是接口规划,它的归类与商务模型中的业务流程有参考对应关系。上图案例有五个服务中心:预订服务、订单处理服务、产品供应服务、财务结算服务和公共服务。
每个服务只需要实现一套自己的逻辑,我们的前台、后台、接口、作业小应用等都可以调用,服务的逻辑跟我们的业务逻辑是一致的,修改代码的时候只需要改一个地方就可以影响到所有调用到这服务的前端应用。
分层架构看似很简单,但保证整个研发中心都使用统一的分层架构就不容易了。那么要如何去做,以达到提高编写代码效率、保证工程统一性的目的呢?
先简单介绍下当前两种比较流行的分层架构体系,一种是领域架构:仓储层(Repository Layer)、领域层(Domain Layer)、应用服务层(Application Layer)、表现层(Presentation Layer)和基础公共层(Infrastructure Layer),见下图。
另一种是相对传统地分为三层:数据层(Data Layer)、应用逻辑层(Business Layer)和表现层(Presentation Layer),见下图。
领域架构和三层架构之间有什么区别?我们是这样认为的,在早期我们做三层架构的时候,大都以表来做驱动的,在做领域架构的时候,大都以业务逻辑来驱动的,两者的区别确实比较明显。
但到了现在,如果都以业务逻辑为中心的话,实际上两者并没有本质区别。当时,我所在公司采用了第二种分层法,我们希望把分层做得极简,也就是说哪怕刚毕业进来的员工,在分层时基本上也不会乱。
而相对第一种分层法,第二种分层法简单很多。每一个应用的代码量都不应该很大,一旦工程变得过大,我们就会把它适当拆分,而不是全部放在一个单块应用里。
总之,我认为分层越简单,整个软件结构就越清晰,代码就越容易统一。把工程做得极简,才有利于复制,有利于业务的快速构建,有利于规模化、稳定可靠。
数据库是整个信息系统中生命周期最长、最难修改的部分,所以要加强规划。数据库的设计至少要提前两步,具体根据高层 E-R 图和数据设计来新建数据库,早建要比晚建好。
数据库调整的代价大、周期长,长时间产生的问题,需要长时间来解决,先在新库里解决新表,再根据当前业务和应用的需求,逐步调整旧表。
物理架构的规划内容包括集群规划和域名规划。首先是集群规划。
20 倍规划、5 倍设计和 1.5 倍实施:规划和设计要大一些,但实施时小一些,这样不仅便于将来的扩展,也节省了当前的费用。
两个逻辑网络:一个内网和一个外网,两个负载均衡,两个防火墙,安全隔离内外网。
四条产品线:国际、国内、新业务以及公共业务,单点登录和企业支付网关等公共业务也属于一条产品线。
六个集群:Web 集群、SOA 集群、中间件集群、数据库集群、Job 集群和 ITD 集群。
以上横向集群与纵向产品线形成了一个矩阵结构,也基本确定了网络基础架构。对于域名规划。对内的域名该改的改,该停用的停用,该合并的合并。对外的域名要尽量少改,要改的话也要有历史继承性(如跳转),要尽量减小对用户的影响。
除以上架构规划外,还有一些其它重要项,如源代码管理规划、文档管理规划、技术选型和团队分工。为什么还要做这些呢?因为统一了源代码怎么放、每个部门的文档怎么放、将来要用什么工具版本,才利于团队的协作,基于统一的环境才能有更高层次地提升。
对于团队分工,需要逐步对齐组织架构与系统的架构规划。对于技术选型,需要注意中间件的引进,要有节奏性,力量要相对集中,要小规模试点,找非核心项目,试用成功后再进行大规模推广。
做完架构规划后,就是架构实施落地了。我们的架构实施整体思路是:树目标、给地图、立榜样、抓重点、造文化、建制度、整环境、组建架构部。
架构部内招几名老程序员,外招几个架构师。内部走出去,提高眼界。外部牛人请进来,落地了解历史和业务。技术建议是:SOA 服务化、基础设施平台化、公共业务服务化、加强项目概要设计。
当研发团队达到 200 多人、有了几百个应用,且在故障不断的情况下,不能与以前一样没有设计就开始编码,而是做加强项目概要设计及评审。后面的补与前面的防,两手都要抓,两手都要硬。
具体计划是:Roadmap 分步实施,改造一期、改造二期、改造三期,近细远粗、实事求是、逐步细化、逐步完善。不断立技术改造项目,不断将技改与业务研发项目相结合,技改即是工单、工单即是技改。避免对业务过多地影响,并不断有业务价值输出,这是架构改造得以持续实施的关键!
以上简单地介绍了总体架构的编写方法,我们的编写思路是先了解业务,建立企业商务模型,主要包括静态的商务主体、组织架构和动态的商务运作模型和业务流程。
接着了解架构现状,建立现有信息系统模型,主要包括功能架构、应用架构、数据设计和物理架构。一个是商务,一个是电子,两者即是整个公司的电子商务系统。
然后在企业商务模型和现有系统模型之上建立领域模型,领域模型它相对稳定,直接指导着接下来的架构规划,最后一定要落地即架构实施。
附档是去掉敏感信息后的真实案例,它的价值如下:
关于企业总体架构,你可以参考标准 TOGAF(开放组体系结构框架)。其实,我们是在完成那份文档后才知道 TOGAF,它们之间有很多相似之处和不同之处。
TOGAF 的内容主要包括业务架构、应用架构、数据架构和技术架构,而我们当时只是以解决公司系统架构问题为导向、以时间为主线,内容有企业商务模型、架构现状、领域模型、架构规划和架构实施。
方法论很重要,但看到事物本身的特点,深入问题以及找到解决办法更为重要。欢迎点赞和拍砖!
案例参考:
https://github.com/das2017/TopArchDemo
阅读数:65442017 年 12 月 14 日
微服务架构 MSA 是 Microservice Architect 的简称,它是一种架构模式,它提倡将单一应用程序划分成一组小的服务,服务之间互相通讯、互相配合,为用户提供最终价值。它与 SOA 之间的区别如下:
我们的微服务框架 MsaFx.dll 是个基于 ServiceStack 4.0.60 包装实现的.NET Web Services 框架,而 ServiceStack 本身支持通用的轻量级协议和 Metadata。MsaFx 与普通 Web Services 框架如 WCF 相比,主要优势如下:
MSA 服务端的架构请见下图的第一张图,MSA 的 HTTP 客户端架构请见下图的第二张图。MSA 的内部是建立在原生的 ASP.NET IHttpHandler 之上实现的,支持 JSON、XML、JSV、HTML、Message Pack、ProtoBuf、CSV 等消息格式。
MSA 服务端的架构
MSA HTTP Client 的架构
服务端的服务对外提供服务前,必须先要把服务端给托管起来。MSA 提供了通过 IIS、Self-Host 等多种形式把服务端给托管起来,宿主环境可以是控制台应用或 Windows Service 或 ASP.NET Web 应用或 ASP.NET MVC 应用。提供的 MSA Demo 的宿主环境用的是 ASP.NET Web 应用。
A、MSA 自身提供的默认路由是:
复制代码
|
B、创建自定义路由,其创建方法是:使用 RouteAttribute 或在宿主环境中配置。提供的 MSA Demo 采用的是在宿主环境中配置路由这种方式来创建自定义路由。
如果你需要在提交请求参数前,验证请求参数是否必填或是否合法,那么验证逻辑必须写在继承自 MSA 的 AbstractValidator 的类里(参考例子请见 MSA Demo 的 OrderValidator.cs),然后在宿主环境中进行开启验证的配置:
复制代码
|
|
|
创建 MSA 服务时,必须继承来自 MSA 的 Service 类。
5.1、MSA 内置了一些便捷访问的客户端,这些对象都实现了 IServiceClient 接口,其中支持 REST 的客户端还都实现了 IRestClient 接口。
这些客户端对象包括:JsonServiceClient、JsvServiceClient、XmlServiceClient、MsgPackServiceClient、ProtoBufServiceClient、Soap11ServiceClient、Soap12ServiceClient 等。
从名称可以看出,这几种不同之处在于支持的序列化和反序列化格式不同。因为它们实现的是相同的接口,所以它们的用法相同,也可以相互替换。
MSA Demo 中用到了 JsonServiceClient 和 ProtoBufServiceClient 这两种客户端,其中当用到 ProtoBufServiceClient 客户端时,你还需要完成如下工作:
a、除了需要引用 MSA.dll 外,还需要引用 protobuf-net.dll。
b、需要在宿主环境中进行如下配置:
复制代码
|
c、必须分别给 Request DTO 对象和 Response DTO 对象的各属性标上 [DataMember(Order = {0})] 特性,具体写法请见 MSA Demo 的 ProductRequestDTO.cs 和 ProductResponseDTO.cs。
5.2、MSA 内置的客户端提供 Get、Send、Post、Put、Delete 等方法。查询数据一般用 Get 方法,新增操作一般用 Post 方法,更新操作一般用 Put 方法,删除操作一般用 Delete 方法。这些方法都有重载。
以下是 Get 方法的其中一个签名:
复制代码
|
在宿主环境中加如下配置:
复制代码
|
如果需要在 MSA API 可视化说明文档中能够看到各请求参数、响应的含义说明,那么需要为 Request DTO、Response DTO 对象的各属性标上 ApiMember,代码参考如下:
复制代码
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
运行结果如下图所示:
在 MSA API 可视化说明文档中显示各请求参数、响应的含义说明
先运行托管应用(如 MSA Demo 中 ServiceHost 项目),出现下图所示的 Metadata 页。然后再运行客户端来调用微服务;也可通过浏览器查看数据,网址输入格式如:
复制代码
|
或:
复制代码
|
其中,第 1 个网址格式规则就是 MSA Demo 中在宿主环境中所配的自定义路由规则,第 2 个网址格式规则就是由 MSA 提供的默认路由规则。
单击下图所示 Metadata 页中的【MSA API UI】后,进入下图所示的 MSA API 可视化说明文档界面,开发人员可以通过这份由 MSA 自动生成的说明文档进行调试,十分方便。
Metadata 页
MSA API 可视化说明文档界面
在我们自主开发的框架管理系统中,进行接口注册,请见下图。其中,规定内部服务访问名的命名规范是:/{***Service}/ 方法名,如 /OrderService/CreateOrder;规定外部服务访问名 OpenApiName 的命名规范是:{各产品线的缩写英文名}方法名,如 FltCreateOrder,其中 Flt 表示国内机票业务的缩写英文名。
MSA 接口注册页
API Gateway 风格的核心理念是使用一个轻量级的消息网关作为所有客户端的主入口,并且在 API Gateway 层面上实现通用的非功能性需求。如下图所示:所有的服务通过 API 网关来暴露,这是所有客户端访问的唯一入口;如果一个服务要访问另一个服务,也要通过这个网关。
所有服务通过一个 API 网关来暴露
一旦 API 网关允许客户端消费一个受管理的 API,那么我们就可以以受管理的 API 形式使用它来暴露这个微服务所实现的业务逻辑。API 网关以 NIO、IOCP 来连接内部受管理的 API,以实现 API 网关的高并发。
API Gateway 主要实现以下功能:
在使用 API Gateway 之前,需要先配置网关参数。网关参数的配置是在自主开发的 API 网关后台管理子系统中进行:
在自主开发的 API 网关后台管理子系统中配置网关参数
阅读数:79832017 年 11 月 29 日
Redis 的使用难吗?不难,Redis 用好容易吗?不容易。Redis 的使用虽然不难,但与业务结合的应用场景特别多、特别紧,用好并不容易。我们希望通过一篇文章及 Demo,即可轻松、快速入门并学会应用。
Redis 是一个开源的 Key-Value 存储,但又不仅仅是 Key-Value 存储,用官网上的话来说,Redis 是一个数据结构存储,可用作数据库、缓存和消息中间件。相对于传统的 Key-Value 存储 Memcached 来说,Redis 具有如下特点:
1、String
这是最简单的 Redis 类型。如果只使用这种类型,Redis 就像一个可持久化的 Memcached 服务器。
2、List
Redis 的 List 是基于双向链表实现的,可以支持反向查找和遍历。
常用案例:聊天系统、社交网络中获取用户最新发表的帖子、简单的消息队列、新闻的分页列表、博客的评论系统。
3、Hash
Hash 是一个 String 类型的 field 和 value 之间的映射表,请见下图,类似于.NET 中的 Hashtable 和 Dictionary。主要用来存储对象,可以避免序列化的开销和并发修改控制的问题。
4、Set
Set 也是一个列表,不过它的特殊之处在于它是可以自动排重的:当需要存储一个列表数据,而又不希望出现重复的时候,Set 是一个很好的选择(比如 ID 的集合)。并且 Set 提供了判断某个成员是否在一个 Set 集合内的接口,这也是 List 所没有的。
5、Sorted Set
Sorted Set 和 Set 的使用场景类似,区别是 Sorted Set 会根据提供的 score 参数来进行自动排序。当你需要一个有序的并且不重复的集合列表,那么就可以选择 Sorted Set 数据结构。常用案例:游戏中的排行榜。
以下特性请重点看管道和事务。
1、管道
Redis 管道是指客户端可以将多个命令一次性发送到服务器,然后由服务器一次性返回所有结果。管道技术在批量执行命令的时候可以大大减少网络传输的开销,提高性能。
2、事务
Redis 事务是一组命令的集合。一个事务中的命令要么都执行,要么都不执行。如果命令在运行期间出现错误,不会自动回滚。
管道与事务的区别:管道主要是网络上的优化,客户端缓冲一组命令,一次性发送到服务器端执行,但是并不能保证命令是在同一个事务里面执行;而事务是原子性的,可以确保命令执行的时候不会有来自其他客户端的命令插入到命令序列中。
3、分布式锁
分布式锁是控制分布式系统之间同步访问共享资源的一种方式。在分布式系统中,常常需要协调他们的动作,如果不同的系统或是同一个系统的不同主机之间共享了一个或一组资源,那么访问这些资源的时候,往往需要互斥来防止彼此干扰来保证一致性,在这种情况下,便需要使用到分布式锁。
4、地理信息
从 Redis 3.2 版本开始,新增了地理信息相关的命令,可以将用户给定的地理位置信息(经纬度)存储起来,并对这些信息进行操作。
步骤 1、在需要使用 Redis 的项目中引用 FxCommon.dll 和 Redis.dll。
步骤 2、在 App.config 或 Web.config 文件中添加如下配置:
复制代码
|
|
|
|
|
|
|
|
|
步骤 3、使用 PooledRedisClientManager 类创建 Redis 连接池:
复制代码
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
步骤 4、通过 PooledRedisClientManager 的实例获取 Redis 客户端,然后就可以开始通过 Redis 客户端的 API 进行操作。
5.1、 Redis Key 命名规范
Redis Key 命名规范:AppID:KeyName。
可能有很多人习惯用英文状态的点号来作为 AppID 和 KeyName 的分隔符,而笔者建议使用冒号作为 AppID 和 KeyName 的分隔符,其原因是:这么写会使 Redis Key 会以 AppID 作为分类显示在 Redis Desktop Manager 中,方便你能够快速查到要查阅的 Redis Key 对应的 Redis Value 值,请见下图:
但如果使用英文状态的点号来作为分隔符的话,那么在 Redis Desktop Manager 中,Redis Key 就不会被分类了,请见下图:
5.2、常见应用问题
阅读数:41482017 年 12 月 5 日
Job 类似于数据库中的作业,多用于实现定时执行任务。适用场景主要包括定时轮询数据库同步、定时处理数据、定时邮件通知等。
我们的 Job 分为操作系统级别定时任务 WinJob 和 HttpJob,其中,WinJob 使用开源的任务调度框架 Quartz.NET+ ZooKeeper 实现,HttpJob 的服务端是自主开发实现的,可以直接定时调用你的计划任务如微服务。下面分别予以介绍。
WinJob 使用 Quartz.NET+ZooKeeper 来实现,Quartz.NET 实现调度,ZooKeeper 使用 MasterElection 来实现高可用,解决单点问题。ZooKeeper 后继有文章单独介绍,这里重点介绍 Quartz.NET 框架的使用。
Quartz.NET 是一个全功能的开源任务调度框架,通过简单的配置就可以实现强大的任务调度功能,使得开发人员不用过多关注任务的调度,只用关注项目的业务逻辑。使用任务调度框架的价值:
基于 Quartz.NET 实现 Job 调度的方法:
在后端服务声明实例化一个调度器,在启动服务的时候启动调度器,相应的代码如下所示:
复制代码
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
创建相应的任务和触发器,之后把任务和关联的触发器加入之前声明的调度器 CurrentSched,相应的代码如下所示:
复制代码
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
在业务逻辑层继承 IJob 接口,并实现 Execute 方法,在该方法内实现需要调度的业务逻辑,相应的代码如下所示:
复制代码
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
通过自主开发的 JobServer,结合自主开发的 Job 集中式管理平台,可以实现满足绝大部分场景的 Job 调度。 这种 Job 调度使用方式使你只需关注实现业务系统的业务逻辑部分即可,无需在业务系统中额外关注如何使用 Quartz.NET。
JobServer 实现的主要逻辑:
在集中式 Job 管理平台中,配置相应的 Job 信息。配置完 Job 信息后,JobServer 获取到这些 Job 信息后,就能够定时执行这些 Job。要配置的 Job 信息包括 Job 的任务名称、任务组名、请求地址、请求类型、开始时间、触发器类型、次数、间隔时间 (s)、Cron-Like 表达式以及状态。
其中请求地址就是 JobServer 实际定时调用的任务的 http 地址,例如 HttpJobDemo 的 WebForm1.aspx 这个任务的运行地址 http://localhost:10786/WebForm1.aspx。
采用 HttpJob 的优势:
采用 HttpJob 的约束:
Cron 表达式格式:秒 分 时 日 月 周 年(可选)。要遵守的规范请见下表:
WinJobDemo 下载地址:https://github.com/das2017/QuartzDemo
HttpJobDemo 下载地址:https://github.com/das2017/HttpJobDemo
Quartz.NET 官网:http://www.quartz-scheduler.net/
Quartz.NET 开源网址:https://github.com/quartznet/quartznet
阅读数:20472017 年 12 月 17 日
Apache Solr 是一个开源的搜索服务器,Solr 使用 Java 语言开发,主要基于 HTTP 和 Apache Lucene 实现。 Apache Lucene 是一个高效的、基于 Java 的全文检索库。
URL 为:http://139.198.13.12:7000/solr/admin.html。请注意:Solr5.5 的,一定要加 admin.html,如果不加的话,则按回车后将返回 404(表示找不到页面)。
4.2.1、安装 Solr 服务:安装的版本号是 5.5.4。
4.2.2、建立 Core
要使用 Solr,需要建立类似于数据库实例的 Core。每个 Core 对应一个文件夹,此文件夹建立在 Solr Home 路径下,且其名字要和 Core 的名字一致:
4.2.3、配置 Core
以 Demo 中使用于 Solr 服务器上的 PolicyCore 为例,修改以下 3 个配置文件:
solrconfig.xml、managed-schema 是从位于【{Solr Home 路径}/configsets/basic_configs/conf】路径下的同名配置文件拷贝而来,而 data-config.xml 来自:对 Solr 服务端安装文件 solr-5.5.4.tgz 解压后,得到 solr-5.5.4 的文件夹名,然后把位于【solr-5.5.4/example/example-DIH/solr/db/conf】路径下的 db-data-config.xml 文件拷贝到【{Solr Home 路径}/configsets/basic_configs/conf】路径下,并重命名为 data-config.xml。
在 solrconfig.xml 配置文件中增加如下内容:
复制代码
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
以上内容加在【5.5.4】节点之后、【${solr.data.dir:}】节点之前。
复制代码
|
|
|
|
|
|
|
|
|
以上内容加的位置请见如下图所示:
对 managed-schema 文件进行修改:以下内容加在节点内:
复制代码
|
|
|
|
|
|
|
注释掉以下配置:
复制代码
|
然后在其下增加如下配置:
复制代码
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
属性说明:
对 data-config.xml 文件进行修改:先注释掉默认有的 dataConfig,然后在被注释内容的后面增加如下配置内容:
复制代码
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
属性说明:
复制代码
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
SolrNet 是 Solr 的开源.NET 客户端之一。
Solr 自身提供有定时增量导入功能,但经测试 apache-solr-dataimportscheduler1.0 版本在 Solr5.5 上已经不能使用,除非修改 apache-solr-dataimportscheduler 的源码。于是,我们采用了如下方式:
首先,开发 Job 任务调度 RESTful 服务,这种方式不仅可以实现定时增量数据导入,也能够实现定时全量数据导入。
然后,在自主研发的【Job 集中式管理平台】中把相关内容都配置好,如下图所示。
这样,我们的 JobServer 就会定时地以 HTTP GET 或 HTTP POST 或 HTTP HEAD 方式请求全量 / 增量导入链接,从而实现了定时全量、增量数据导入功能。另外,如果你想要知道如何利用 SolrNet 实现全量导入、增量导入,请分别参考 Demo 代码中的 FullDataImport() 和 DeltaDataImport() 这两个示例。
用 SolrNet 的 CURD API 实现,示例请见 Demo 的 Add()、Delete() 和 Query()。准实时数据导入较定时增量数据导入更近于实时,在实际应用中如通过消息队列对数据库和 Solr 同时更新,则更好。
阅读数:46722016 年 8 月 30 日
技改是技术改造的简称,是技术的蜕变。本文指的是在公司技术发展的某个瓶颈阶段,按原有开发和组织方式已经无法玩下去,这时公司希望引进架构师或技术牛人,来破解当前困局。技术改造,对于公司和技术人员而言都非常难得,参与者多,主导者少。我有幸前后主导过 3 次 OTA 系统的技改,规模有大有小,每次环境和问题虽不一样,但还是有套路可循。
《技改之路》少讲技术多讲路,我们不过多的关注技术细节和中间件的实现,而重点讲述技术改造的过程和思考,以下是本次分享的 Topic:
公司
系统规模
研发规模
此案例是一个中等规模的电子商务公司,老板白手起家,资本原始积累,现在赚钱的互联网公司很少哦。公司从 2006 年的几个研发人员,到技改前的 200 个左右研发人员,业务发展良好,是国内领先的 B2B 机票分销平台,互联网名声虽不大,但处于闷声发大财的状态。
公司之前尝试过 2 次系统重建,请了一批批的牛人,前后经历过 4 年。公司消耗大,但都以失败告终。此案例是我本人的第 2 次技改,效果不错,整体进展顺利,团队技术水平也有 1~2 个档次的提升,算是比较成功的实践。另外,因为案例过于真实,有些 UML 会打上马赛克,请多谅解。
成立架构部:
培养:
制度:
架构是演化出来的还是设计出来的?对于创业场景,创业本身就是在未知中寻找机会,将不清楚变为清楚,系统的架构自然是演化出来的,而对于技术改造或 Google 搜索等复杂工程场景,系统的架构当然要精心策划。
公司电商系统总体架构,我们整整花了 1 个多月的时间,对项目做了总体的规划,然后对内宣讲推广,让每一个参与者了解自已的目标和价值。不手握地图,你怎知站对了位置!
我们构建的中间件有:
job/redis/center Log/ 业务监控 metrics/dashboad/ 调试工具 windbg/rabbitMQ
ORM 工具 dapper/MongoDB/jetermclient/ 公共类库 jFX/zookeeper/openTSDB
HBase/searcher 工具 solr/ 元数据管理 DDM/DLL 管理 nuget/ 自动发布 Jenkins/ 微服务架构 JSOA
中间件是应用系统的基础设施,是应用的装备和工具。农村建住房是一块砖一块砖的往上垒,城市建大 house 则是先打地基,然后再建主框架,最后才是垒砖,所以中间件的建设是大中型系统建设的前提。
以上中件间的构建过程贯穿于整个技改的生命周期,每一个中间件可能需要花 1~2 个月,它们大部分都基于开源。请关注上面的顺序,直面当前的问题,按需快速构建和推动。虽然使用开源,但中件间的引进和改造有自已的一套流程:调查 => 试用 => 选型 => 深入研究 => demo => wiki => 分享推广 => 业务系统试用 => 改进完善 => 大规模推广。
中间件的构建和增加,不仅对当前业务系统影响较小,还可以解决一部分业务难题,减轻数据库的压力。同时它还有利于建立技术氛围和分享机制。一支有激情、爱技术的研发团队,对技改的具体实施是非常重要的。
当面对 100 个多库时,我认为系统架构师关注到数据库级别即可,建库拆库。数据库按模块整体迁移,其实并没有想象中那么难,理想情况下只需修改数据库的链接,而对于表和字段的优化,可由应用架构师或技术主管,以 SOA 收口或应用重构来实现。
数据库如何做到可伸缩,可大可小方便拆分呢,思考如下:
上图从内往外看,一个框即可以是一个库,也可以是一个模块,还可以是一个表,根据当前业务规模和系统复杂度来实现;
我们的大实体关系图具体为:产品、用户、订单、结算、基础设施。它们早期可以是一个库,里面有 5 个模块,中期可以分为 5 个库,后期则可以更底级别分为更多的库;
命名规范:数据库名:业务线缩写 + 库名;模块名:参考大 E-R 图 + 专业词汇缩写;表名:模块缩写 + 表名;自增编号:表名 +ID;
模块内可多表联接,模块间减少联接,数据库间不允许联接;
每一个数据库有且仅有一个 Owner 组,原则上只允许一个团队才能 Create,其它团队访问需要分级控制,L1 为接口,L2 为只读库,L3 为直接读写“写库”。
数据库规划
数据库是整个信息系统中生命周期最长、最难修改的部分。所以让时间来解决时间的问题,要加强设计,具体实施过程如下:
在地图即总体架构文档推广后,我们就新建立了一批库,这在早期还遭到 DBA 的抱怨;
新增相关库后,新表按新规则创建,特殊情况走特殊审批;
去 SP 去关联,让数据库减少计算,回归存储本质;
数据库拆分,改表改字段,采用模块整体迁移或应用重构;
一年后,再去看数据库,发现在没有特别立项和驱动的情况下,已接近一半的表在新库中。
数据变迁
状态图是数据的变迁,是数据与行为的互动,数据的变化会引起行为的变化,行为的变化会产生数据的不同。上图是国内的订单状态变迁图,它的价值不仅属于数据库层,还在于 SOA 服务化和核心业务流程。
服务是动词,是行为或活动的抽象,它的价值在于业务逻辑或行为的重用,具体实施过程如下:
服务列表和服务协议,在设计阶段使用 Excel 表格;
统一 Request/Response 规范;
服务实现,因没有直接可见的业务价值输出,最好以工单或项目来落地;
服务治理,早期没有工具时,使用 WIKI 做简单管理,后期使用专业的服务治理工具。
领域模型
(点击放大图像)
没有领域图的架构设计都是耍流氓,我们画领域图的架构师是 2 位老员工,没有多少高大上,甚至于他们之前没有画过 UML,但我们的状态图和领域模型都是出自他们之手。其实画领域图的关键是懂事物本身,并知道它们的关系。我们的领域图与业务模型中的 5 大业务流程一一对应,包括:预订流程,订单处理流程,产品供应流程,财务结算流程,账户管理流程。
微服务
我们的微服务 JSOA V2.0 是基于 ServiceStack 当时最新的版本号 4.0.50 实现的,它本身支持轻量级协议和 Metadata,以及 Swagger,是微服务的一种架构实现。另外,它还可以再扩展以 API Gateway 的方式实现 Open API。
微服务 MSA 与我们之前的 SOA、ESB 有什么区别呢?
ESB 有总线和聪明的管道管理能力;
SOA 弱化了中间的管道和总线,强化了两端;
微服务 MSA 使用通用的轻量级协议和更加 web 化(RESTFUL)。
系统是什么?系统 = 元素 + 关系。应用架构是什么?应用架构 = 应用 + 架构。应用就是系统的最小单元,应用分级和应用编号则构成了应用关系即应用的架构,它有利于应用的管理、交互和追踪。应用分为产品线,子系统和应用 3 级,每一级编号为 2 位,如 100206。应用要从用户的视角出发,先有用户,然后有应用功能,这样才是以用户为中心去构建系统。
组织架构没有最佳实践,只有适合于自已当前的选择,以下是组织架构与技术架构对齐方面的思考:
艺术与工程相关分离:UED;
软件开发与硬件相分离:运维;
技术研发与业务研发相分离:架构部;
需求,实施,验收相分离:每业务线分产品组、开发组、测试组;
开发按业务职责相分离:预订组、产品组、订单组;
专业技术委员会制:测试、产品、开发、轮流主持,设委员长;
第一步总体规划:手握地图,明确路线;
第二步数据库:建库拆库,去 join 去 SP;
第三步中间件:按需构建,先增加常用;
第四步服务:技改 = 工单,有业务价值输出;
第五步应用:拆应用,建门户 Portal,重构应用;
第六步组织架构微调:组架技术与组织架构对齐,技改之后调整;
第七步固化:框架化,自动化,管理过程工具化如 DevOps。
从服务入手是错的,从数据库或中间件入手是正确的。服务属于高级阶段,方便行为的重用,是深层次优化,但太慢了;
从当前问题或故障入手,要先灭火,逆向分析 dump 工具很重要;
历史要尊重,早期不可做大的改动,不能过多地影响现有业务。建议只做加法,建新库和新中间件,这样就不会有太多阻力和负担;
一般不能全部重建,除非系统较小,系统规模大时只能拆分后分步重构;
技术并不是技改过程中最复杂的,人和事及关系才是麻烦的部分,历史问题的后面是人;
每次环境和问题都不一样,要有准备脱一层皮的心态。
技改是大折腾,于公司于个人而言都是,小改怡情,大改伤身,我们应该避免大的技术改造,但此现象又比较常见,特别是业务发展快的创业公司。所以真正高手下棋,应该是通盘无妙招,让正确的事情很容易发生,基于自然的演化来实现技术的演进。
怎样才能通盘无妙招,系统良性长久的发展?我们需要两个力量,一个是技术,一个是业务,如果只重视业务,而很容易在技术上积劳成疾,如果完全技术驱动,则又容易忘记业务目标。所以它们应该相伴相生,共同发展,在大的技术改造实施之后,在框架和流程相对固化后,小的技术重构项目应该长期存在,这样才能良性循环,让系统进入自然演进的状态。
问题:请问张老师如果再来一次技改你会怎么做?在你做过的技改过程中你觉得你最大的收获是什么?觉得做的不好的又是什么?
这个问题非常好,为了更好回答您的问题,我简单介绍一下本人的 3 次技改经历。我的第 1 次技改是重建,项目从 10 月份到第二年 8 月,历史 10 个月,可以说是技术成功项目失败。第 2 次技改是重构,只管技术,少管人和业务,整体效果好,可以归结为成功。第 3 次技改还是重构,既管技术又管人,且业务处于高速发展期,资源少,可以总结为技术与业务相伴相生,技术效果一般。
如果以后还有机会,自已就不再直接负责了,实在是太累,从内外各招几个架构师,并按上面的工作流程和方式,然后把握好技术与业务的关系和资源占用即可。回到具体问题:
如果再来一次,我会多参考第 2 次技改经验,即 PPT 分享的过程总结;
技改后的收获是脱胎换骨,技术和管理都有很大提升;
不好的地方:要更多的关注业务,以及平衡好业务与技术的关系。
问题:单块应用向微服务迁移时,平滑过渡有什么技巧?如何解决分布式事务一致性呢?还有关于微服务持续交付、测试、监控(语义监控)方面有落地工具吗?
平滑过渡的技术:直面当前系统的问题,不断有价值输出,然后参考上面的过程总结,先规划,然后中间件和数据库,最后是服务和应用;
分布式事务一致性:使用替代方案,如最终一致;
落地工具:MSA 与 SOA 的治理没有本质差别,还是 DevOps/Trace/Metrics/,我们使用的是 ServiceStack/JMetrics/CenterLog/Jenkins/。
问题:如果旧有模块关联复杂,又影响现有系统性能,相关开发人员流失,不好梳理,改造有风险,重写老板不答应,该如何取舍呢?
旧有模块关联复杂,又影响现有系统性能:先灭火解决当前故障, 逆向分析 dump 工具;
相关开发人员流失:引进中件间,建立分享机制和学习型团队,将技改总体规划,让每个人了解自已的价值和目标;
不好梳理,改造有风险:内招几个老员工成为应用架构师;
重写老板不答应:有业务价值输入,技改 == 工单或项目,借助业务项目来实现技改。