侧边栏壁纸
博主头像
why

一个主要敲代码,经常怼文章,偶尔拍视频的成都人。

  • 累计撰写 197 篇文章
  • 累计创建 11 个标签
  • 累计收到 101 条评论

参加Dubbo社区开发者日成都站后,带给我的一点思考。

why
why
2019-10-28 / 0 评论 / 1 点赞 / 223 阅读 / 5,381 字
温馨提示:
关注公众号why技术,第一时间接收最新文章。

我的收获

进入会场的时候可以在接待台的地方拿到七个折页,每一个折页都是阿里对开源社区的共享,每一个折页的背后都代表着一个团队的辛勤付出,他们为中国在世界的开源史上落下了浓墨重彩的一笔。值得尊重,我也必须一一打出来,以示尊重。它们分别是:

  • 【Dubbo】国内最受欢迎的服务框架、服务化/微服务最佳解决方案。
  • 【阿里巴巴Spring Cloud】微服务开发一站式解决方案。
  • 【Nacos】一个更易于构建元原生应用的动态服务发现配置管理和服务管理平台。
  • 【ChaosBlade】阿里巴巴开源的一款简单易用、功能强大的混沌实验注入工具。
  • 【Alibaba Java】应用诊断利器。
  • 【Dragonfly】元原生的镜像与文件分发解决方案。
  • 【Sentinel】The Flow Sentinel of your Microservices

这次成都的Dubbo社区开发者日宣传海报上一共有六个议题.

但是实际上来分享的老师有七位。

在活动开始之前还有一个暖场的小活动。就是做一个简单的自我介绍,然后介绍的比较好的,阿里的小姐姐会送一本小马哥写的《SprintBoot编程思想》,还是签名版哦。

这环节是我的强项啊。所以,当仁不让,我有幸获得了这个奖品。谢谢小姐姐,谢谢小马哥。

同时,在自我介绍的环节,我惊奇的发现,我旁边的这个哥们,居然阅读过我的公众号文章。在会议进行的过程中,我更加惊奇的发现,我右前方的哥们也读过我公众号的文章。

这就很神奇了。

微服务转型

在这七个优秀的分享中,每一个都可以拿出来单独写一篇文章,如果一篇文章包含了所有的分享,那大概率是泛泛而谈了。

我不想泛泛而谈,所以在这篇文章里我只写一个主题:来自新网银行谢延泽老师的分享。

谢老师分享主题是《新网银行微服务转型实践》,主要是关于微服务落地的相关内容。我会结合谢老师的PPT来分享一下我的一些思考。

微服务简介

对于微服务的定义,谢老师的PPT里面是这样描述的:

我觉得这个定义还是很精准的。微服务是一种概念,一种实现方式,一种设计理念,而不是一种具体的技术。不是说你的项目中用了Dubbo、用了SpringCloud等等技术,这个服务就是微服务了。微服务完全不局限于框架或者语言。

我谈一谈个人对于第一段话的理解:

微服务是一种将一个单一应用程序开发为一组小型服务的方法。每个服务运行在自己的进程中,服务间通信采用轻量级通信机制 。

拿我参与过的一个项目来举例。

上家公司是一家做支付的公司。支付有各种各样的支付通道,我们把这些支付通道聚合在了一起,对外输出的是统一且稳定的支付服务。但是这个支付服务背后,对应的是一个单体的大项目,所有人都在这个项目上进行开发。我所谓单体大项目的意思就是,用户功能、支付功能、订单功能、账户功能都在同一个应用里面,不同组的开发人员都在这一个项目上进行开发。

在这个场景下,随着公司的快速发展,人员越来越多,项目变得十分臃肿,开发人员也不敢轻易动手开发,完全谈不上什么架构思想、高耦合、低内聚。

公司及时的将这个单一应用程序,拆分为了用户服务、支付服务、订单服务、账户服务。这个过程,就是服务拆分,微服务化的一个过程。每个服务,都有自己的服务器,服务之间调用是采用的Dubbo框架。

在单一大项目中我们能提供的服务,在拆分为微服务后我们同样可以提供,而且性能更好。

在上面的这个场景中,我们拆分后的架构,就是由微服务组成的架构。之前的很长一段时间里面,我理解的微服务就是支付服务、订单服务、账户服务这一个个系统,但是这样的理解是很片面的。

一个由Dubbo开发完成的服务不能叫微服务,只能叫做微服务中的一个部分。

别忘了,上面说的,服务之间还要通讯。假设你只有一个支付服务,你和谁通讯呢?那你能说这个支付服务是微服务吗?很明显不能的。

一个服务使用微服务架构的话,只有两种可能性。

  • 第一种是对原来大系统的拆分。
  • 第二种是最开始就采用了微服务架构来设计。

我祝你遇见的都是第二种情况。

微服务的起源,从PPT我们可以看出,2012年这个概念才算出现,距离落地还有一定的距离,2014年才算正式提出,2016年才算是有了一个比较容易理解的明确定义。从2014年到2016年,处于摸着石头过河的阶段。

微服务的优点,逻辑清晰、简化部署、可扩展、灵活组合、技术异构、故障隔离。

还是拿我之前举的列子,我们来一个个的说。

逻辑清晰:支付服务只管对接支付通道,需要操作账户,对账户进行冻结、解冻、扣款的操作时,只需要调用账户服务提供的对应接口即可。简而言之,账户的具体逻辑,对于支付服务是一个黑盒。支付服务只需要把更多的注意力放到自身的逻辑上即可。这样,一个服务干自己该干的事。逻辑清晰。

简化部署:当有新功能来临时,如果经过需求拆分后,发现只需要修改支付服务即可。那我们只需要修改并部署支付服务即可。如果不是微服务架构,你得整个项目重新部署,包括没有改动的部分,这是我们不希望看见的。

可扩展:这个没啥说的了,微服务设计天生适合扩展。

灵活组合:每一个系统,就是微服务的一个部分,当用户系统、支付系统、订单系统、账户系统组成一个微服务架构的时候,对外输出的是商城能力,其使用方是C端用户。当支付服务、订单服务、清结算服务组成一个微服务架构的时候,对外输出是支付能力,使用方是B端用户。这就是灵活组合。

技术异构:只要两个服务之间能接收并且正确的解析req/resp报文,那各自的服务可用不同的语言开发,使用不同的技术栈,使用不同的数据存储技术。简而言之,技术异构。

对于技术异构这一点,我想借用第二位分享者马骥老师的PPT多说一句:

如果有技术异构,那大概率涉及到跨语言的需求。那在马骥老师看来:

跨语言特性实际是RPC层的支持,本质是协议层面的支持。

大家可以细细的品味一下这句话,一语中的。

故障隔离:由于每个服务都运行在自己的服务器中,首先服务器就是天生隔离的。其次,只要服务的调用方,做好服务容错机制。当下游服务出现异常的时候,对上游服务系统的运行不会产生影响。但是,对于是否会对业务产生影响,这个得结合业务进行分析。

这些优点在各大会议上频频出现,所以谢老师只是蜻蜓点水的提了一下。重点想要说的是第三部分,带来的挑战。

带来的挑战

带来的挑战,包括但是不限于下面列出的几点。

对于带来的挑战,我们也可以一个个的来说。

可用率降低

首先第一个,怎么去理解这个可用率降低呢?

当我们对系统进行微服务设计后,势必意味着需要更多的服务器和相关的基础设施(诸如Nginx、redis、mysql等等)。

比如下面的这两个问题:

  • 跨机房调用时涉及到防火墙问题。
  • 由于基础设施的增多,基础设施的不稳定,会带来服务的不稳定。

在单体应用里面则没有这些考虑。从这个角度来说,服务的可用率降低了。

同时服务与服务之间需要进行跨进程的调用或者通过网络进行调用。如果这些服务的功能还是糅合在一个项目里面,并不会带来这样的问题。所以,从跨进程或网络调用的这个角度来说,服务的可用率是降低了。

所以我们在设计微服务系统的时候,其中的一个重要的原则就是面向故障设计。必须对预知和不可预知的故障进行充分的分析。打好提前量,做好容错机制。

事务复杂度

这个可以说是家喻户晓了,对吧。拆分服务后,你大概率会碰到分布式事务的问题。

不要说你没有碰到过,极有可能是你碰到了,但是你不知道这就是分布式事务。而且这种情况,我猜你们大概率使用的是最终一致性的解决方案。

分布式事务,又分为两种,一种是跨库的分布式事务,一种是跨服务的分布式事务。

分布式事务的解决方案也是多种多样的,我个人认为,每一种方案说到底不外乎两种:最终一致性和强一致性。

比如我们可以基于本地表状态查询的方法、基于注册回调接口的方法、基于消息队列的方法、基于TCC分布式事务的方法...

大多数场景,使用数据的最终一致性方案都是可以满足的。但是比如在银行的场景里面,对于账务的操作,必须是强一致性的。

巧合的是,在这次的分享中,最后一位分享的老师季敏(Seata 开源项目发起人),他分享的主题就是《Seata 101》。Seata也是一种分布式事务的解决方案。从git上看,其收到的关注度还是比较高的。

贴两张季敏老师的PPT给大家看看:

运维复杂度

上面的图是某个单体应用完全微服务化后的架构图。

微服务化后的系统,势必带来的一个问题就是对于运维工作的复杂度。

一个单体应用,我们假拆分后有20个服务,每个服务对应一个系统,每个系统你要保证他的高可用,至少需要部署2个节点,这样算下来就是至少40个节点。这里我还没有假设其中的某个服务的访问特别大,比如说是网关层,那部署的节点可能就不止2个了。

假设有一次这些服务全部都需要上线,如果你们没有诸如k8s这样的服务编排基础设施,需要运维人员手动一个个的到服务器上去操作,好的,告辞。

所以谢老师给出的忠告是:在底层的基础设施还不够完善的时候,不要贸然去推微服务。

调优复杂度

分布式链路追踪工具

当我们只是一个单体应用的时候,我们也需要对用户的请求进行调用链路的追踪,但是不是分布式的,这个功能非常好实现。

但是当我们的系统微服务化后呢?可能当你的服务个数不多的时候,你还没觉得调用链路追踪的重要性,因为就那几个服务,调用关系你烂熟于心。但是,当服务多到你都记不清的时候,分布式调用链路追踪的重要性就体现出来了。

我所知道的分布式调用链路的实现方式有大众点评开源的cat、twitter团队开源 Zipkin、华为开源的skywalking、naver团队开源的pinpoint。

合理规范的日志

日志必须规范,接口的请求参数和输出参数需要打印出来,以后"对簿公堂"的时候这就是证据。如果拿不出证据,这个锅你就得背好。

同时,为了方便不同系统之间的问题查询,或者对日志进行聚合分析,建议给日志打上追踪号。比如Dubbo filter+MDC技术,SpringCloud的sleuth,了解一下。

高性能的日志平台

不论你是使用非常成熟的ELK去聚合、分析你们的日志,还是其他的日志聚合技术。首要需要保证的一个点就是性能,就是响应速度。开发人员用你的日志平台就是为了方便的查看日志,但是点击查询后半天没有反应,这谁受得了啊。等你反应过来了,我一台台服务器登录上去查也查出来了,如果出现这样的情况,你可以想象一下开发人员的心情。

测试复杂度

【图片中的白盒测试应该是黑盒测试,笔误】

这一小节,我没有什么特别想说的,唯一想要强调的是:做好单元测试,做好单元测试,做好单元测试。

不然联调的时候,对方会觉得你low,你会觉得对方很烦。

聚合查询

这个得好好说说,这是一个大坑啊!痛点啊!

我们拆分微服务的时候,是站在C端用户的角度拆分的。假设我们把服务拆成了用户服务、订单服务、支付服务、账务服务。看着没毛病啊,C端用户用起来十分流畅,完全感知不到你具体有哪些服务。

这个时候巧了,运营人员也完全感知不到你有哪些服务。他们提出的需求怎么说呢。是可以理解的,但是站在开发的角度来说:

所以,在拆分微服务的时候,一定要把:有没有、需不需要大数据平台的支撑作为一个重要的考量点。

如果考虑不充分,当你碰到这些千奇百怪的需求时,你只能临时拿出一个非常low、性能低下、实现起来非常难受的方案。

什么?你说你不接这个需求?

我们的实践

这一部分谢老师分享了两个案例。

一个是成功的微服务化的过程,一个是过度设计带来的问题。

成功的微服务化的过程

这是微服务化之前的系统架构。

经过循序渐进、逐步拆分、由简到繁、由粗到细这样的一个实施过程后:

拆服务一定不是一个一蹴而就的过程,它一定是一个循序渐进的过程。

经过拆分后,系统变成了这个样子:

在这个过程中,谢老师提到了拆分原则,对应的具体理论知识可以去仔细的研究一下:

过度设计带来的问题

上面的图是新网银行采购的一个项目,厂商提供的架构图。其实需求很简单,就是实现一个单点登录。

在厂商提供的架构图中,他们采用了微服务设计,利用了SpringCloud实现。根据厂商的设计,我们需要50,60台虚拟机来实现这个功能。

而这个系统的使用者有多少呢?400多人。因为是内部员工使用,所以只有400多人使用。

你做这么复杂的一个设计,来支撑400多人的一个单点登录功能?有没有价值?有没有性价比?

从这个例子中我们可以看出,你拆微服务,或者你需不需要拆、拆多细这个是和业务紧密相关的。

千万不要为了微服务而微服务,为了技术而微服务。

引申思考

写到这里,我突然想起之前的支付公司做的时候碰到的一个需求,这个需求,在支付服务和清结算服务都能进行开发实现,但是这两个服务都觉得自己不应该去做这个事情,即使这个需求必须由这两个服务中的一个去实现。

后来,我们一起去找了我们的首席架构师,他说:

这个需求,由清结算服务来做。因为对用户来说,用户更能直接感受到的是支付服务。当我们遇到需要开发一个功能的时候,应该开发在哪里,这样的边界不清晰的问题的时候。我的答案是为更多用户能直观感受到的主要服务让路。所以,这个需求由清结算服务实现。

最后说一句

好了,看到了这里了,关注一下我的公众号[why技术]吧,文章写好后第一时间会先发布在公众号里面。

写文章很累的,需要一点正反馈。你的关注,就是强有力的正反馈!

才疏学浅,难免会有纰漏,如果你发现了错误的地方,还请你留言给我指出来,我对其加以修改。

抱拳了,铁子!

0

评论区