小L强烈建议团队使用微服务,并极力推荐了前公司用的一套分布式事务解决方案。
小P经过反复思考查证并做了大量的尝试后,辨证地对微服务架构做了如下分析:

为什么要用微服务,微服务带来了哪些好处?
1、减少相同代码的copy
2、屏蔽底层,不对外暴露DB,避免DB耦合
3、业务特定,适合由专门团队维护
4、保留无限伸缩能力
其中好处1、2、3通过传统模块化的方式,通过一定的研发管理也能达成。而伸缩能力才是传统的模块化方法无法达到的。所以说追求水平扩展能力才是我们实施微服务的本质目标。

事物都有两面性,服务化带来的坏处又有哪些?
1、带来了分布式事务
2、开发变复杂了,原本简单的方法调用,现在跨了N个工程,通过各种RPC调用
3、对Devops的要求变高
总而言之,就是一切都变复杂了,成本提高了。

无论是用Dubbo、OSP还是后来的Spring Cloud作为服务化实现的框架,服务发现、熔断、负载均衡,链路追踪、配置中心、监控,甚至由于服务的拆分引入Docker并辅以运维自动化的手段。这些知识,或许对开发人员而言一段时间后都将被淡忘,小P认为一个完善的服务化框架应该是对开发人员屏蔽掉底层这一切的,就像现在HTTP编程不需要过多关注底层网络协议的细节实现一样。关于微服务的定义,不同的人有不同的理解,似乎很难达成完全的一致。小P认为服务化第一是为了水平伸缩,第二是为了分工。所以服务化的重点和难点并不在于框架,而在于服务的拆分。

那服务的拆分又有好多套方法,从微观到宏观可以有 一个接口一个服务,一个类一个服务、一个模块一个服务、一个系统一个服务,甚至还可以按层拆分,就像传统的MVC一样,每层搞个服务。各种说法都似乎有它的道理,忽略场景而去找一个放之四海皆准的法则似乎也不太可靠。拆细了,充斥着分布式事务,加上开发运维成本的递增;拆粗了,似乎又没达成当初使用微服务的初衷。

微服务开发中容易碰到的那些坑:
循环依赖问题
A服务依赖B,B依赖C,C又依赖A

多网卡多IP
无论是用Zookeeper或者Eureka服务注册,都需要关注多网卡多IP问题造成服务访问不通。

重试
有重试通常就意味着要实现幂等,别小看这一点点工作量,累加起来成本可不低。

RPC比HTTP效率高?
一般而言二进制协议比通用HTTP效率要高,但HTTP有更好的可读性,还要兼顾测试,再者RPC协议接口对外部还需要一层API Gateway层,将HTTP转为RPC。为了提高一点性能,我们付出这么高的代价到底值不值得?

批量接口
以前单体应用,可以方便加本地缓存,批量获取数据可以循环获取,因为每次都是进程内调用。而现在每次调用都是跨网络调用,再用循环获取时间必然成倍增长。

报表
很多时候报表需要跨多个服务,那到底报表归属给谁?

辨证地分析完之后,系统也从原来的集中化架构,改为分布式微服务架构,如下

服务化前

服务化后

跟大神小L的不断的合作、碰撞与冲突也促使小P不断地去思考,不断地去学习流行的互联网架构技术。对新技术而言,小P会更加谨慎保守,小L则更为激进。小P也意识到了团队管理里面有个很重要的问题:团队的成长与更简单实现任务是一对矛盾,同样一项任务,有简单可靠的实现方案,假设能得80分,花的时间是20%。而用另一种方法去实现完美方案,假设能得99分,需要花100%的时间。小P要做的是尽可能地保证技术架构稍微领先于业务

关于MQ
ZeroMQ、ActiveMQ、RabbitMQ、Kafka、RocketMQ
ZeroMQ其实就是0MQ,就是没有MQ的意思啦,实际上它还真的不是一个MQ,可以认为是Socket的增强库,把它放到跟Netty同一归类才是正确。

ActiveMQ和RabbitMQ都是老牌的MQ产品,前者使用Java实现,是JMS规范的参考实现,后者使用Elang实现,是AMQP的一个实现,通常认为RabbitMQ比ActiveMQ更成熟,更高的性能与稳定性。

Kafka最初被设计用来做日志处理,是一个不折不扣的大数据通道,追求高吞吐,存在丢消息的可能。

RocketMQ是阿里参考了Kafka自行实现的高可靠、高可用、高并发、低延迟MQ产品,需要注意的是RocketMQ有部分特性是不开源的。

如何选择合适的MQ产品是摆在架构师前面的一个挑战,一般而言,对于中小公司来说,选择RabbitMQ是比较中庸的选择:性能够用、安全、可靠、可控、维护简单。当然也要结合具体场景综合选择。有一点需要注意:默认参数配置下,出现脑裂后RabbitMQ集群不会自我恢复,需要人工介入恢复,务必加好监控和报警。

程度员的世界通常只有0和1,也更容易陷入牛角尖里出不来,非比个高下,然后选择性能最高的,小时候我看武侠片也最喜欢问:谁才最厉害,但现在我们已经成年,对于惟性能论我想说的是:
Kafka之所以快是有几个代价的:
第一是用了MMAP,第二是采用顺序文件,第三是ZeroCopy。
MMAP如果要最快,就用异步,反正我消息是写到内存了,操作系统自己决定什么时候写到硬盘,如果没写,那就是人们经常说的Kafka不可靠,可靠吗?不可靠,因为有概率存在。可靠吗?可靠,因为概率极低。而且我还可以配成同步的,但这样就牺牲了性能
顺序文件的话就没有随机操作了,像RocketMq这种也是类似的机制,通常没办法删消息了,只能靠时间到了自己触发。另外其实我觉得对一般的中小公司来说,瓶颈根本就不在消息中间件,你号称一秒100万消息有什么用呢?你的消费者处理能能跟得上吗?如果你直接用Push,结局就是直接把消费者压死,最后还得老老实实的慢慢Pull,那你又得过来反思,我需要那么快的MQ吗?

什么时候考虑用MQ?
上游不关心业务执行结果
上游关心执行结果但要比较长时间才能执行完成

什么时候不用MQ?
上游实时依赖下游的执行结果,而且在业务上也无法妥协为两个步骤,这时候就老实的调用RPC接口吧,如登录。

MQ是如何解耦的?
拿注册送优惠券为例子,紧耦合的做法是在注册完成后加上一段送优惠券的代码,这样就把注册与送券耦合到了一起,哪天营销活动有改动了,不再送券了,则需要修改注册相关代码。
松耦合的做法是注册完成之后发消息给MQ,MQ消费者订阅该队列,在接收到新消息后执行送券逻辑。如果哪天不再送券了,则修改消费者代码不再送券即可。

如何理解MQ能削峰填谷
一般MQ都支持推和拉的模式。如果上游的处理能力远远大于下游的处理能力时,如采用推的方式,则消费者有被压垮的风险。这时消费者可根据自己处理能力,以一定的处理频率拉取消息,避免被压垮。

MQ结合快速失败
对于某些客户期望立即返回处理结果,但生产者和消费者处理能力差异明显的系统,可以使用MQ达到”排队处理”的效果,处理结果使用异步通知。如订票、秒杀业务。生产者在消息体里加上创建时间,消费者在处理消息时判断消息的创建时间与当前系统时间,如果超过了某个值,则直接失败处理。这其实也是业务妥协的结果,即保证系统在高峰期的某个时间段内只有部分用户的请求处理成功优于所有用户的请求都失败。

MQ如何实现消息必达
先本地事务再调用MQ发送消息,则不能保证消息发送成功;先发送MQ做本地事务则不能保证本地事务成功。一般会先本地事务,再调用MQ发送消息,对于发送超时或失败的,有个补偿程序进行补偿,最终一致即可。RocketMQ的事务消息核心原理与之类似,只是中间件做了一部分补偿的活。

MQ消费者幂等设计
消费者要保证收到重复的消息后不会重复处理,一般是使用业务ID,如订单保证惟一,通常使用数据库的惟一索引约束。

常见的解耦手段

数据库中间件
分库分表、读写分离等是常用的优化手段,数据库中间件(在一定程度上)屏蔽了底层的实现,使业务系统不再关注这些细节。

配置中心
各类中间件地址、下游服务地址集中管理,解决使用配置文件时配置私藏引起的诸多问题,另外配置中心更易于运维统一管理。

关于SQL:
尽量由应用去实现join,预留垂直再拆分的空间。通常Mysql的join是通过临时表实现,也更难优化,拆成简单的sql,更容易建索引优化。

常用提升单机性能的常见手段

缓存
难点在于过期数据的淘汰
应用程序角度看:页面缓存、数据缓存
架构的角度看:进程内缓存、分布式(跨网络)缓存
客户端角度看:浏览器缓存、DNS缓存、CDN加速

数据库索引
强烈建议阅读完《高性能Mysql》

减少跨网络调用次数
比如,调用Redis查询用户数据,一次取10个用户数据比10次每次取1个用户数据要快

互联网分布式架构的本质在于分,分完之后最终的瓶颈一定落在CPU、内存、存储和网络上,而后面的一系列的具体战术都是为了减少某个瓶颈。而越是大流量的互联网公司,越容易走在前面,很多中小公司由于流量不够,对大型互联网架构只能停留在纸上谈兵阶段。了解了这些之后,小P觉得自己做为技术的老大,在这里已然很难有技术的提升空间而他要学习的东西实在还有太多,于是毅然选择了某大型互联网公司,不久之后,小L也去了另一家大型互联网公司,全剧终!

小P的架构生活(下)的更多相关文章

  1. 小P的架构生活(上)

    背景:这年小P已经参加工作4年了,在前同事Z的极力劝说下,小P加入了Z新开的公司Y,公司一共有三个人:老板Z.程序员小P.前台W.项目名为XX交易系统 小P加班加点,终于在两个月后把系统开发完成,版本 ...

  2. "大中台、小前台”新架构下,阿里大数据接下来怎么玩? (2016-01-05 11:39:50)

    "大中台.小前台”新架构下,阿里大数据接下来怎么玩?_炬鼎力_新浪博客 http://blog.sina.com.cn/s/blog_1427354e00102vzyq.html " ...

  3. 技术博客——微信小程序的架构与原理

    技术博客--微信小程序的架构与原理 在两个月的微信小程序开发过程中,我曾走了不少弯路,也曾被很多现在看来十分可笑的问题所困扰.这些弯路与困扰,基本上都是由于当时对小程序的架构理解不够充分,对小程序的原 ...

  4. 纯CSS实现带小角的对话框式下拉菜单

    最近公司首页样式重写,头部下拉菜单改为了带小角的对话框式下拉菜单: 很多人可能会用图片,事实上纯CSS就能够实现: HTML: <!DOCTYPE html> <html lang= ...

  5. (转载)RESTful架构风格下的4大常见安全问题

    转载自<RESTful架构风格下的4大常见安全问题>,作者:马伟 伴随着RESTful架构风格的大量应用微服务架构的流行,一些本来难以察觉到的安全问题也逐渐开始显现出来.在我经历过的各种采 ...

  6. Kubernetes 架构(下)- 每天5分钟玩转 Docker 容器技术(121)

    上一节我们讨论了 Kubernetes 架构 Master 上运行的服务,本节讨论 Node 节点. Node 是 Pod 运行的地方,Kubernetes 支持 Docker.rkt 等容器 Run ...

  7. 微信小程序之自定义select下拉选项框组件

    知识点:组件,animation,获取当前点击元素的索引与内容 微信小程序中没有select下拉选项框,所以只有自定义.自定义的话,可以选择模板的方式,也可以选择组件的方式来创建. 这次我选择了组件, ...

  8. Kubernetes 架构(下)【转】

    上一节我们讨论了 Kubernetes 架构 Master 上运行的服务,本节讨论 Node 节点. Node 是 Pod 运行的地方,Kubernetes 支持 Docker.rkt 等容器 Run ...

  9. 微信架构 & 支付架构(下)

    微信架构 & 支付架构(下) 3. 管理网络请求 首先看看原来 iOS 处理支付网络请求的缺陷: 原来支付的请求,都是通过一个单例网络中心去发起请求,然后收到回包后,通过抛通知,或者调用闭包的 ...

随机推荐

  1. [论文理解] FoveaBox: Beyond Anchor-based Object Detector

    FoveaBox: Beyond Anchor-based Object Detector Intro 本文是一篇one-stage anchor free的目标检测文章,大体检测思路为,网络分两路, ...

  2. 六十七:flask上下文之Local线程隔离对象

    Local对象在flask中,类似于request对象,其实是绑定到了werkzeug.local.Local对象上,这样即使是同一个对象,在多线程中都是隔离的,类似的对象还有session以及g对象 ...

  3. JAVA处理链表经典问题

    定义链表节点Node class Node { private int Data;// 数据域 private Node Next;// 指针域 public Node(int Data) { // ...

  4. Jmeter之集合点

    Jmeter之集合点 Jmeter中也有集合点,看样子还是很强呀 哇哈哈 它只是通过计时器Synchronizing Timer实现的假集合点功能. 没有时间整理,来实际的,直接上图. 在线程下添加集 ...

  5. linux常用命令(13)tail命令

    tail 命令从指定点开始将文件写到标准输出.使用tail命令的-f选项可以方便的查阅正在改变的日志文件,tail -f filename会把filename里最尾部的内容显示在屏幕上,并且不但刷新, ...

  6. Web23_Listener

    记得在web.xml配置<listener-class>监听器的Copy Qualified Name复制类全名</listener-class> <listener-c ...

  7. ubuntu下终端代理方法

    起因 正常使用shadowsocks后只能在浏览器中访问google,而终端中却无法使用.   解决方法 ProxyChains是一个终端代理方案,使用比较简单. 在源里有这个软件,直接安装 sudo ...

  8. 安装IE11必备更新

    https://support.microsoft.com/zh-cn/help/2847882

  9. centos下kill、killall、pkill命令区别

    kill是用来终止进程的 首先可以通过ps aux查看系统有哪些进程正在运行. 1.用kill来杀死某一个进程 #kill,加选项-9,加PID,表示杀死进程编号为PID的这个进程# -1 重启#ki ...

  10. 对scrapy进行单元测试 -- 使用betamax

    使用betamax进行单元测试 爬虫代码 测试代码 对于scrapy的单元测试,官方文档并没有提到,只是说有一个Contract功能.但是相信我,这个东西真的不好用,甚至scrapy的作者在一个iss ...