老男孩微服务kubernetesspring cloud架构工程师怎么样 值得学吗?

K8S能替代SpringCloud吗?这两者不是一个概念,一个是掌勺的厨师,一个是厨师手里的锅,是要把厨师做成锅去炒菜吗。

我对Java熟一点可以用Spring Cloud,别人不会Java也可以用别的微服务框架。不管你换什么微服务框架,但容器的管理调度还是K8S。

Netflix是集成了奈飞的一套中间件(不得不说奈飞在github上开源的java项目是真多)

真正要考虑的是微服务出现的原因,以及使用微服务后会出现什么问题,Spring Cloud这样的微服务框架以及周边的中间件是怎么解决这些问题的:

业务简单完全可以用单机部署,搞成微服务拆成那么多应用部署就是给自己找罪受。一个简单的学生管理系统干嘛要搞成微服务呢,是吧。单机服务到顶了,直接多加几台机器就行。

但是业务复杂了之后,有些业务请求量很高,有些业务请求量少。比如电商的商品搜索,这玩意儿访问量这么大,要是我还和其他业务写在一个应用里部署,把能用的几台机器都打挂了,整个网站都瘫痪了,然后明天的新闻头条:某淘网站瘫痪,系程序员服务器挖矿导致,某程序员又要祭天了。

复杂业务单独写到一个应用里,还有一个问题就是重构困难,要换框架甚至换语言,那就是伤筋动骨。那就拆吧,把应用里的功能都拆成一个个服务,服务想用什么框架想用什么语言都无所谓,只要保证服务之间通信协议一致就行,所以就有了SOA的架构。

服务之间怎么通信呢,用什么协议通信呢。最早Java里有RMI,它用ObjectInput/OutputStream把调用的对象通过网络传给远程的服务器,但是因为对象序列化是java专属的而且有注入风险等问题,所以后面有了基于XML的SOAP协议,但是XML冗余信息太多了,于是还有基于JSON的REST协议,Spring Cloud的就是一个REST协议的客户端,直接声明式接口就能用(类似的还有Retrofit,只不过不支持负载均衡熔断等功能,所以一般用在Android比较多)。

但是SOAP和REST都是基于http协议传输的,头信息有点浪费,拉低了有效信息的荷载率,于是有人拉起直接基于TCP的轻量级的协议。这些序列化都是人类可识别的字符,还有一类呢更丧心病狂为了更高的传输效率直接上二进制,如谷歌的protobuffer,Facebook的Thrift,Kryo...一个RPC框架的优秀并不体现在序列化上,这些序列化协议可以做成插拔的随便替换,重点在于以下几点:

1、一个服务要被好多个客户端调用,要持有那么多连接,还要保证请求的高效处理,是不是得上io-multiplex,像Dubbo一样用上Netty吧,不然怎么吹牛逼叫高性能,当然你也可以用Mina,httpserver...甚至你可以用原生的NIO自己实现协议的处理。这个做的好一点也可以做成可插拔的。

2、服务怎么暴露给别人,A也要调用我,B也要调用我,明天来了个C也要调用我,我每次都把自己的ip告诉人家多麻烦。要是某一天我ip换了,我是不是还得发个邮件通知A,B,C,那多麻烦。服务一多,我也记不清到底哪些人在调我接口了,要是换ip少通知了一个人,导致他应用挂了,人家又要甩锅了,真是麻烦。既然这么麻烦,那就搞个注册中心吧,我应用一起来就把自己的ip注册到注册中心,别人要调用就到注册中心去拿我的地址吧。是不是感觉这个注册中心和DNS很像,其实它们的作用差不多,只是DNS运用于互联网,因为缓存以及生效慢等原因,不适合做内网服务的注册中心,那就自己搞吧,于是就有了etcd,euruka,zookeeper这样的东西。

3、我应用部署了好多台机器都注册到注册中心了,你要调用哪一台机器呢。所以有了负载均衡,根据不同的策略有不同的负载均衡算法,有随机有轮询有哈希,这些可以按自己心意配置

4、要是我应用机器里有某几台机器挂了,或者换ip了,怎么办,别人调用不到了,是不是得让注册中心把挂了的机器剔除掉。怎么剔除呢,肯定不能靠我的应用,我都不知道自己啥时候会死让我怎么给你善后。得靠注册中心,大部分注册中心都采用超时续约的方式来保证服务提供方正常提供服务,一旦提供方挂了,超过一定时间没续约,不好意思踢掉,然后告诉消费者这家伙挂了,不要再调了,换台机器调。

5、注册中心挂了怎么办。一般来说注册中心是要保证高可用的,但真的倒霉到打雷把电给断了,网管踩断了网线,发地震把磁盘给震坏了……还是要保证消费者能正常调用提供方的接口。所以客户端最好是在本地备份服务提供方的地址进行容灾。 这就有那么一点像dns缓存了。

6、既然注册中心这么重要,要做成高可用的,怎么做呢。“高可用”简简单单三个字,可不是像应用集群一样想多部署一台就部署一台。应用之所以可以方便地横向扩展,主要是因为没有状态,数据都存在数据库里。但是注册中心,和数据库一样是有状态的,有状态的节点要保证高可用难点在于数据复制和数据一致性。消费者向注册中心的机器A获取接口地址,和从注册中心的机器B获取接口地址不一致,就好像你同时被两个领导指挥着,可能导致接口调不通。你看Paxos、Raft以及zookeeper的ZAB就是解决这个一致性问题的的。

7、既然注册中心就是存个状态,那我用redis是不是也可以呢?额,dubbo还真的支持

哇塞,这么多注册中心,有啥区别呢?主要区别体现在CAP中一致性(C)和可用性(A)的取舍,Zookeeper、Consul、etcd用的是Paxos、Raft、ZAB这类基于主从复制的强一致性算法,leader节点接受写操作复制给slave节点,当leader节点压力过大或者其他原因挂了,集群重新选举Leader时有一段时间不可用;而Eureka是用了与的gossip协议类似的点对点无主复制,每个节点都一样能接受读写,其中任意一台机器挂了不影响集群的服务,缺点是一致性差。而阿里开源的nacos实现了强一致性的raft协议(CP)和私有的distro协议(AP)供你选择。

8、要是消费者在调用提供方的接口超时了怎么办,是直接失败抛异常返回呢,还是调用其他机器,又或者再多重试几次。如果是重试的话,你也不知道之前超时的调用到底是成功了还是失败了,所以重试策略应该只能用在幂等接口上。

9、要是消费者请求超过我机器能扛的量把这台机器打挂了,你跑去重试其他机器又把其他机器打挂了,导致我整个服务全军覆没了,那可不行。所以我得限流,超过我的承受范围那就排队去吧,不能让你把我给撑爆了。对于消费者,重试了几次还不行那就不要重试了,给我点生路好不好,那就熔断吧,直接告诉上游我不行了。不调接口了我总得给用户个响应吧,我不能装死啊,那就降级处理给用户个fallback。限流简单可以用Guava包里现成的RateLimiter,更专业的有,把熔断降级也做了,另外Netflix贡献了自己家的,阿里贡献了自己的都是干这个的。

10、应用那么多台机器,有时候想改个配置,还得重新部署所有的机器才能生效,要是有个中心化的配置中心就好了,把配置都放到配置中心,一改动所有的服务器都生效,做的更好一点呢,甚至连重启都省了。要是有个权限管理和版本控制就更完美了,谁能改配置以及改了什么配置导致了什么问题一目了然,想甩锅也甩不掉了。Spring Cloud Config除了可以访问数据库或redis,也可以访问git或svn上的配置文件来解决这个问题,Github、Gitlab支持Webhook可以做更新推送,为了更安全的管理密码等配置,Spring Cloud还整合了Vault。阿里内部有个Diamond专门用来做配置中心,用的是客户端的长轮询来推送变更给应用,另外阿里还开源了个Nacos把配置中心和注册中心的功能整合到一起了。引入了配置中心,也会有一些令人头疼的问题,到底是应用中的配置优先级高呢,还是配置中心的优先级高呢。如果是配置中心的优先级高,那团队开发的时候,在配置中心改动了配置就会影响到其他成员。

11、我的应用部署了那么多台机器,要看日志难道我还要一台一台的上去看嘛,要是线上有100台,1000台这不是要累死我。我需要一个把日志收集(Logging)起来的工具,让我在统一的地方看日志就行。ELK或者EFK怎么样,ElasticSearch还支持全文搜索呢,就是这套东西太吃内存了,Loki+Grafana好像是个不错的选择哦。

12、我的应用这么多台机器,我再也不好单独上一台机器用top等命令看CPU、内存、IO等性能了,不好用jmap分析java堆内存了,也不好用jconsole远程单独连接某台机器看gc或者JMX透出来的MBean了,还有上下游接口的qps,我要把这些数据收集起来,做个指标聚合(Metrics)。你看prometheus+grafana是目前开源界最流行的组合哦。

13、用户一个请求过来,从A服务到B服务再到C服务……这个调用链可能很长。再也不能像单机版应用一样直接看程序堆栈,直接用火炬图就能分析应用的性能了,而且具体调用了集群中哪台机器也不知道了。我需要把这些调用链也收集起来,整成一个跟程序stack trace类似的东西,最好还能告诉我每个服务调用过程中的耗时,也就是Distributed Tracing。谷歌的Dapper论文就提到了谷歌是怎么实现这个功能的,然后开源届大佬们弄了Zipkin,Jaeger,Spring Cloud也有一个Sleuth,这种组件很多,每种实现可能有所差别,但是大佬们觉得还是得定个规范于是有了OpenTracing,关于Distributed Tracing我的里有介绍是怎么实现的。 trace类似结构上基本上没多大变化,而Metrics日志按照监控的对象不同以及指标的维度不同结构也有所不同,Logging+Metrics+Tracing三者统一成一个传输协议也是谷歌微软要搞OpenTelemetry标准的最终目的。

14、后端应用调用层级有时候挺深的,不可能要求每个应用检验用户有没有登录、登录信息合不合法。后端应用不能再像以前写JSP那样可以随意的SetCookie,那在用户入口的地方加个接口网关负责安全认证(比如检查用户有没有登录或者SSL加密成https协议),当然也应该有负载均衡。Netflix/Zuul就是干这个的,Zuul1.x仍然用的是,2.x开始投向了,阿里内部有一个mtop太烂了没开源。还有以前servlet的HttpSession那套也不能再用了,毕竟内部接口调用可能都不是http协议,而且应用集群化了,状态应该抽离出来,比如把状态集中到Redis里。

还有吗,还有一大堆问题(比如分布式事务这块又会牵扯出一大堆问题)。微服务是应用解耦的手段,不是目的,微服务的关键不在于微服务本身,而在于微服务的治理,不到万不得已千万别用微服务,微服务不是万金油,软件工程里没有银弹。很多2B的应用,根本没有2C那么大的流量,为了追时髦也来搞微服务,把SpringCloud这一套引进来,很多服务就一台机器连负载均衡都不用,搞微服务不是折腾自己吗,明明可以六点下班,非得996。如果是为了微服务而微服务的话,那还不如花点时间多去思考一下怎么写好代码,怎么划分好模块,怎么做好单元测试。

今天有点晚了先睡了 ,以后有机会再聊。


刚下班回来,接着再聊聊k8s。这东西是个docker容器相关的,所以先说说没有docker的时候是怎么弄的吧。

最开始呢,大家要搭网站部署应用是很麻烦的,要自己采购机器布网线,还要养一堆网络工程师,有些小企业觉得这个成本高,所以大多都把网站放到运营商机房里,然后远程连上服务器进行管理,这个时候连上的服务器都是真实的物理机。但是硬件资源配置都是固定的,你想要4核16G的服务器机房里还不一定有,那买个高配的又嫌贵浪费,真是左右为难。

然后有人提出了云计算的概念,刚开始国内谁都不知道云计算是个啥,阿里的马老板被王博士"忽悠"了开始做阿里云。当时国内没几个人知道云计算具体要怎么做,看到谷歌发了那三篇著名的论文就以为云计算应该做成分布式存储分布式计算,然后阿里苦熬了几年换掉了玩具版的Hadoop做出了自主研发的分布式计算平台(刚开始叫飞天也就是现在的MaxCompute),但是这玩意儿小企业根本不需要呀,我只想部署个小网站我要你的分布式有毛用啊。

另一边呢,远在大洋彼岸的另一个电商巨头亚马逊开始"不务正业",搞了个AWS干起了卖虚拟机的生意,虚拟机的好处是资源可以弹性申请,解决了之前硬件资源配置的问题。虚拟机是依赖,将硬件抽象化,在上面虚拟出的多个操作系统可以共享一组通用资源。

阿里云一看,原来云计算的生意是这么做的啊,云计算重点不是"计算"而是"云",赶紧开始抄作业了。刚好美国有个Rackspace公司开发的虚拟化技术始终干不过AWS和VMware,一气之下开源了,也就是现在的OpenStack。阿里云真是幸运,想抄作业刚好有人把答案公开了,还不收钱,就这样阿里云开始做起了卖弹性云服务器(ECS)的生意。刚开始呢BAT的另外两位对云计算是嗤之以鼻的。小马哥内心想着,这玩意能赚钱我跟马云姓。

李彦宏心想,我不就不跟你们姓马了,我还是去耕耘我的互联网广告继续收割流量费吧。

现实就是这么啪啪啪打脸,阿里云靠着卖虚拟机挣得盆满钵满——一个教英语的老师给学计算机的李彦宏和小马哥上了一门叫《云计算》的商业课。然后就是众所周知的打脸现场了,百度腾讯华为等一众互联网公司开始抢食云服务市场,很多大企业为了隐私安全也用OpenStack搭起了自己的私有云。

知错能改,善莫大焉嘛,打脸有什么要紧的,面子值几个钱

与此同时呢,10年的时候有个小公司基于Linux的容器化技术()开发了Docker,本质上呢就是Linux内核的和两个功能,能限制一组进程的cpu、内存、网络等资源,但是小公司不好混呐,经济上捉襟见肘,走投无路之际想到了开源。这不开则已,一开惊人,旋即吸引了谷歌微软亚马逊等一众大厂前来围观。这玩意儿就是Linux上的一个运行沙箱,这可比虚拟机省资源呐。你看连微软都开始弄WSL、帮Docker移植到Windows,全面拥抱Linux,就知道这玩意儿到底有多香了。嗯,插句道听途说的话,谷歌内部其实早就开始研究容器化,而Docker最有价值的其实是它的Dockerfile,它能将容器的环境用标准化的文件描述出来,所以现在的云原生底层的容器运行时并不仅仅只有Docker。

容器化看上去已经挺完美的,但是你本地起一两个Docker容器玩玩还好说,docker-compose可以方便的管理几个容器,但是生产环境成千上万个容器可不好管理,跨机器网络怎么通信,怎么对容器增删改查。Docker官方开发了Swarm来管理集群化的容器,谷歌开发了K8S。最后大浪淘沙之下K8S已经成了容器编排的事实标准了。

Worker节点里的Kubelet会根据API-Server里的组件定义去部署一个个容器。不同机器容器怎么通信呢,kube-proxy会负责容器之间的通信和流量转发。

那K8S怎么调度的呢?这就是K8S里面定义各种对象要解决的问题了。

  1. 首先一个概念就是Pod,K8S里面最小的调度单位不是容器,而是Pod,一个Pod可能包含多个容器,为啥呢,因为这样更灵活。比如可以用init-container对环境做一些初始化;再比如ServiceMesh里可能会用到Sidecar容器,把服务发现,负载均衡,熔断限流,日志采集,链路追踪啥的全都抽离成一个个容器,服务的容器只要关心业务就行了,再也不用搞一大堆中间件依赖,中间件依赖冲突真的令人头疼。

2. 一个服务部署了多个Pod,要是有Pod挂了怎么办?K8S提供了(老版) 和 (新版)来处理这个问题,ReplicaSet可以确保在任何给定时间运行指定数量的 pod 副本,有Pod挂了会自动调度帮你重建容器。

我想对服务进行扩容,或者发布新版服务咋办。为了保证提供持续稳定的服务,我得新建Pod和ReplicaSet,等启动完了再把老的Pod和ReplicaSet给删掉。这个麻烦的操作有了K8S的,就方便多了,它会帮你管理Pods和ReplicaSets,有修改只需要更新Deployment定义就行了。所以实际我们平时很少直接使用Pod和ReplicaSet。为啥K8S这么火,有了Deployment,再也不用那么繁琐的部署过程了。

4. 如果应用是有状态的,比如有数据要落盘,Pod挂掉了,得保证磁盘里的状态能还原。所以跟Deployment对应的还有一个

5. 前面的ReplicaSet,K8S可以根据配置的replica数量以及机器的负载情况,将Pod调度到不同的机器上,而有些情况我们需要将Pod部署到每一个节点上,比如做日志采集,性能指标监控等场景,K8S为我们提供了来解决这个问题。

6. 原来我们跑批处理程序用的是Spring提供的 注解,但是如果应用挂了,有些调度可能就错过了,所以有这样的,K8S为我们提供了另外一种可能性就是

上面讲了调度,那服务怎么访问呢?

  1. Pod重建后ip是会变的,所以服务之间的调用肯定不能用Pod的ip,而且一个服务Pod有好几个,用Pod的ip咋整,所以K8S提供了的功能,用于代理部署的多个Pod,具体作用于哪些Pod由label selector定义,它映射到包含对应label的pod上。但是这个Service和Nginx这样的反向代理还是不一样的,它本质上是和类似的四层代理,也就是传输层代理,它是不区分应用层是http流量还是mysql的流量的。Service有四种类型,默认的ClusterIP使用集群内网IP,只能集群内部访问;要想外部能访问需要把Service映射到节点的IP上也就是类型;还有个LoadBalancer类型,不过需要云服务商提供负载均衡的支持;还有个ExternalName还没用过。

2. NodePort的方式有个问题,端口65535个,总有用完的时候,要是暴露的服务特别多,65535就不够用了,所以还是得上nginx这样的反向代理,因此K8S还有个Ingress的东西。

前面讲了计算的调度,网络的访问,还有一个关键的就是如何存储。

用docker的时候知道有一个volume可以把宿主机的存储挂载到容器中,在k8s里也差不多,但是又两种场景:

  1. 挂载配置文件。用docker-compose的时候,给应用进行配置,可以通过env环境变量传到容器里,还有一种是通过配置文件挂载到容器里面。用环境变量的方式还好说,k8s也提供了env变量,但是配置多了env管理起来不方便,还是配置文件好。但是k8s有多台机器咋挂载配置文件,所以k8s还专门提供了一个ConfigMap的东西。
  2. 挂载数据存储。PersistemVolume(PV)用来定义存储卷,PersistemVolumeClaim(PVC)用来声明在Pod中用哪个PV。通常PV和PVC是一一对应的。但是如果每次都要去创建PV太麻烦了,所以K8S还提供了StorageClass来动态创建PV。前面的StatefulSets因为要保证Pod的状态持久化落盘,它就依赖于PV和PVC这玩意儿做持久化。

容器化和微服务有啥关系吗?这两者起关联主要得益于DevOps这个概念——(开发Development即运维Operations)。以前没有云计算的时候有开发工程师,测试工程师,运维工程师,一整套流程是分工明确的。但是开发写完软件自测完成没问题了,交付给测试或运维发布后,不是这个环境有问题就是那个配置有问题,运维测试对开发说你是不是不行啊,开发心里那个气啊,你们这些不会写代码的麻瓜敢说劳资不行,看我不打掉你们的饭碗。刚好Docker技术出来了,开发工程师直接把软件和运行环境打包成Docker镜像,发布的时候只要把镜像往K8S集群部署就行,从此运维工程师们就失业了。微服务就是因为应用拆分的足够小,从开发到测试到上线基本上可以让一个人完成,一个微服务打包成一个docker镜像,发布的时候只要在k8s里申请相应的资源来运行这个docker镜像就行,开发人员美滋滋。

目前为止已经大致讲了K8S和微服务的关系。微服务需要弹性计算,弹性扩缩容,而容器化的docker配合k8s就能很好的做到这一点。

但是其实我在想题主问的是不是这个狭义的K8S。因为K8S由谷歌主导开发的,谷歌联合了各大云服务商成立了云原生基金会,这个基金会里已经囊括了很多云原生组件。

这里面ServiceMesh是号称可取代SpringCloud的下一代微服务技术。我看到阿里云和腾讯云上已经有服务网格的相关产品了,这块可以关注一下。

今天先这样了,又码了两千字,该去洗澡了。(* ̄︶ ̄)



有大佬说让我讲一讲消息系统,流批处理还有k8s调度,istio,这些我也还在学习中,我先挑一个稍微熟悉一点的消息系统讲一下吧,希望整理的过程中自己也能有些收获。有什么不对的地方希望路过的大佬指正。

在讲消息系统以前,先想象一下这个场景。

我是维护订单系统的几个服务,今天营销平台说让我在用户下单的时候调用一下他的服务,他好去对这部分下单用户进行一些营销动作,比如说这个用户下单了一个小时都还没付款需要发个短信提醒用户付款,明天又一个B平台的开发让我调用一下他的B服务,后天C平台的开发说调用他们的C服务的参数能不能改一下。

然后我就天天忙于他们的业务,自己头上的KPI却没有任何进展。而且因为同步调用他们的服务,导致用户下单的时候贼耗时,这些外部服务严重降低了用户下单时的体验,特别是营销平台的短信服务它还要调下游运营商的服务,这尼玛可拖累死我了。而且双十一大促的流量如洪水滔天,我调用他们的服务时,他们的机器根本杠不住,直接把他们打挂了,导致自己订单服务经常抛异常。这尼玛自己的KPI没完成,还造成了性能问题,恐怕今年绩效的3.25我是背定了。

怎么办呢?想想这里面的几个问题:

1、我堂堂一个订单核心应用,竟然要依赖营销平台这样一个跟用户无关紧要的服务,这明显是不合理的,我要把这些无关紧要的服务用一个统一的方式处理掉,把那些无关紧要的代码从我的核心代码里通通干掉,让我的服务与这些服务进行解耦。

2、由于我一个一个地调用他们的服务,这种同步调用严重拖累了我自己的核心业务,所以如果能把这些调用转成异步调用就ok了。

3、这一到双十一,即使我另外开线程异步调用,调用量还是洪水滔天一样,他们处理不过来还是很难扛的住,大促一过呢一切又归于平静,他们的机器又闲的发慌。而且他们有些业务并没有很高的及时性要求,发个促销短信,发张优惠券,送个积分,慢一点又何妨。所以他们亟需一个削峰填谷的功能。

现在大家都知道消息队列可以解决这些问题。但是没有消息队列的时候,要怎么解决类似的问题呢?

我可以把下单消息存在数据库里,然后开一个异步Scheduler把这些消息发送给订阅了这个消息的订阅方。为了实现这个功能需要一张msg表存消息,还有一张subscriber表来记录每个订阅方的发送进度。有新的业务方需要我的下单数据,我只需要在subscriber表里添加一条记录,Scheduler会自动帮我把消息发给新的业务方,我终于可以高枕无忧了。

慢慢地,我发现这种基于消息的场景越来越多,其他团队也有这样的场景,要是能把这个逻辑单独拎出来就好了,于是消息队列的需求就出来了。

消息队列里经常把存储每种类型消息的队列称作一个topic,把存储消息的中间件叫做broker,所以加入消息队列后的结构就变成这样了。

设计这个消息队列的时候会碰到什么问题呢?

1、producer->broker本质上就是一次RPC调用:原来在同一个数据库的msg表被迁移到了broker上。在同一个数据库,我可以用本地事务保证我的消息一定持久化到数据库了,但是变成RPC调用后,消息可能会因为网络原因弄丢,或者因为网络超时,producer可以配置retries次数进行重试,当然重试也可能会导致消息重复(RPC会碰到的问题,消息队列也会碰到)。retries配置为0,也就意味着消息最多持久化一次(at most once),这个至多一次的概念划重点后面还会讲到。

2、消息机制被单独拎出来成了broker,那broker就得保证高可用,不然宕机了,下游的订阅方又是一阵骂娘。要保证高可用又涉及到数据复制了,kafka自带了topic级别的分区与功能,只需要将topic的replication设置成大于1的值,kafka就会帮你完成数据复制。

3、高可用集群里的持久化,一台机器数据落盘不一定可靠。producer发送消息给集群leader的时候,leader有可能还没来得及把数据复制给从节点就挂了,那这个消息就丢失了。为了解决这个问题,kafka给producer提供了参数:

  • acks=0的时候,producer不会等待broker的确认,producer只要把数据扔进自己的socket缓冲区,他就认为成功了。这种情况producer的速度会很快,但是明显非常不可靠。
  • acks=1的时候,producer发送给broker后,broker的leader只要将消息落盘了就会给producer返回ack响应。这种情况leader没来得及将数据复制给从节点就挂了,这个消息也就丢了。
  • acks=-1或者acks=all的时候,broker收到消息后会等待集群中所有副本确认落盘了才会给producer返回ack响应。这种情况是最可靠的,当然效率也会更低。
  • 这个acks的三个选项和数据库的异步复制(不等从库确认),同步复制(等待所有从库确认),半同步复制(一个从库确认即可)道理是一样的。如何选择就看具体业务了,在可靠性和速度方面平衡一下。

4、acks=all能保证消息一定被broker集群持久化了,消息不会丢失。但是因为网络等种种原因producer可能没有收到ack确认,他为了保证可靠性就重试了,结果导致消息被broker集群持久化了多次。也就是说broker上的replication>1和producer的ack=-1只能保证消息至少保存了一次(at least once),但是无法保证只有一次(exactly-once)。前面讨论RPC的时候说过,为了防止接口重试产生的影响需要保证RPC接口的幂等,producer->broker也一样。所以Kafka 0.11.0引入了的功能,Kafka会为每个Producer生成一个ProducerID,并为每条消息生成一个序列号,所以当broker收到同一个Producer发出的两条序列号相同的消息就不会再保存一遍了。而这个exactly-once是现代流系统精确性的必要条件。你想,如果你用事件流来实时统计双十一大盘上的销售额GMV,如果有重复消息不就相当于一笔订单统计了多次吗,那这几千亿的GMV水分就大了。

5、消息的持久化问题与消息的堆积问题。我们开始设计的broker是基于数据库存储的,随着消息的增多,数据库B+树的深度就会增大,消息堆积的越多性能下降就越严重。阿里最早的notify消息队列是基于ActiveMQ设计的,Linkedin最早也是用ActiveMQ,都出现了这个问题,所以Linkedin开发了基于日志结构的Kafka,并且通过内存映射的方式大大提高了读写的速度,具体可以看Linkedin的这篇文章:。但Kafka的存储结构并不适用于阿里,所以阿里就基于Kafka开发了metaq(也就是开源的RocketMQ)。

Kafka主要问题在于:

  • Kafka每个topic会有若干个partition,每个partition就是一个文件,除此之外partition还有一个offset的索引文件,并且在。topic越多,partition就越多,文件数就越多,一是消耗了过多的文件句柄,二是原本高性能的顺序写随着文件数的增多就变成了随机写。所以Kafka在topic数特别大的时候性能会急剧下降
  • Kafka只能保证一个partition内的消息有序,如果topic有多个partition,就无法保证消息的有序性了,也就是说消息的有序性与多个partition带来的高吞吐量二者不可兼得
关于阿里的metaq怎么解决这个问题,有兴趣的可以参考我的

6、消费完的消息怎么清理。如果是使用数据库存储,我们为了避免B+树深度的增大,肯定是需要开一个任务定时清理已经消费过的数据,B+树是对读性能优化的数据结构,对于增删操作多的应用写性能是很差的,这也是前面提到为什么kafka使用日志来存储消息的原因之一。同样的,kafka用日志存储也需要考虑到日志的清理,毕竟硬盘容量不是无限的,如果使用一个日志文件肯定是不方便的,所以kafka的日志除了分了partition,每个partition还分成了若干的segment。默认的直接删除也就是把cleanup.policy设置成了delete,根据消息的key对消息进行合并保留最新的一个消息就把cleanup.policy设置成compact。说到这个compact,再思考一个问题,如果发了一条消息反悔了想删除怎么办,kafka目前只提供了一个墓碑消息的概念,就是你再发送一条消息体为null的消息并且这条消息和之前的消息key相同就行,kafka执行compact的时候把这条消息删掉。

7、Broker->Consumer是让Broker起一个Scheduler往Consumer推消息呢,还是让Consumer自己起一个Scheduler从Broker拉消息呢?这两者各有优缺点,让Broker实现Push方式可以保证消息的及时性,一旦有新的消息进来就可以立马推送给Consumer,但是如果Consumer消化不良就可能把Consumer给撑死。Consumer的Pull方式可以让Consumer根据自身需要自身控制消费速度,消费的实时性虽然有些影响,但是可以Consumer可以提高Pull频率达到自己预期的响应要求,当然提高Pull频率也就导致Broker压力增大,为了避免频繁的建立连接断开连接,可以用长轮询,让服务端hold住连接,等有变更了再返回响应。Kafka的消费客户端就是基于Pull模式的。

8、Broker->Consumer消费过程中,Consumer可能会消费失败,或者消费超时,从而导致Consumer重复消费,所以同样地Consumer消费消息的时候仍要保证幂等。

-今天先聊到这吧,又到吃饭时间了-

}
Spring Cloud拥有丰富的、综合的JAVA类库来处理所有执行障碍作为部分应用堆栈。因此,自身有类库和执行代理来做客户端服务发现、配置升级、指标追踪等等。模式例如集群服务和批量作业也在JVM中管理。
使用spring cloud构建实际的微服务架构。 基本概念: 使用docker进行集成测试 混合持久化 微服务架构 服务发现 api网关 docker 使用docker对每一个服务进行构建和部署。使用docker compose在一个开发机上进行端到端的集成测试。
  • Spring Cloud拥有丰富的、综合的JAVA类库来处理所有执行障碍作为部分应用堆栈。因此,微服务自身有类库和执行代理来做客户端服务发现负载均衡、配置升级、指标追踪等等。模式例如单例模式集群服务和批量作业也在JVM中管理。

  • 使用Spring Cloud构建实际的微服务架构。   基本概念:   使用Docker进行集成测试   混合持久化   微服务架构   服务发现   API网关   Docker   使用Docker对每一个服务进行构建和部署。使用Docker Compose在一个开发机上进行端到端的集成测试。   混合持久化   混合持久化其实就是说使用多种数据库来存储。不同的微服务实例都会使用它们自己的数据库,并通过REST服务或者消息总线来通信,举个例子,你可以使用基于以下数据库来构建微服务:   Neo4j(图形 ...

  • 使用Spring Cloud构建实际的微服务架构。   基本概念:   使用Docker进行集成测试   混合持久化   微服务架构   服务发现   API网关   Docker   使用Docker对每一个服务进行构建和部署。使用Docker Compose在一个开发机上进行端到端的集成测试。   混合持久化   混合持久化其实就是说使用多种数据库来存储。不同的微服务实例都会使用它们自己的数据库,并通过REST服务或者消息总线来通信,举个例子,你可以使用基于以下数据库来构建微服务:   Neo4j(图形 ...

  • Spring Cloud拥有丰富的、综合的JAVA类库来处理所有执行障碍作为部分应用堆栈。因此,微服务自身有类库和执行代理来做客户端服务发现负载均衡、配置升级、指标追踪等等。模式例如单例模式集群服务和批量作业也在JVM中管理。

  • 尽管像AWS这样的云可让您启动CPU和硬盘以及库存操作系统安装,但像CloudFoundry这样的PaaS可让您启用基础架构,如消息代理,数据库以及Web服务器和路由器。 所以,是的,它取代了服务器(或者更重要的是,它可 ...

  • minikube的最新版本默认启用了RBAC。 对于启用了RBAC的集群,我们在安装部分中添加了关于此问题的注释。 “最新版本的kubernetes已经在api-server上启用了RBAC,如果您的目标平台启用了RBAC,则必须要求cluster-admin在部署数据流服务器之前为您创建角色和角色绑定,并将数据流服务考虑到它需要运行的角色。“

}

我要回帖

更多关于 springcloud完整项目 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信