聊聊服务发现的推拉模型
前言
过去一年,我的工作重心投入到了 API 网关(阿里云 CSB)中,这对于我来说是一个新的领域,但和之前接触的微服务治理方向又密不可分。API 网关适配微服务场景需要完成一些基础能力的建设,其一便是对接注册中心,从而作为微服务的入口流量,例如 Zuul、SpringCloud Gateway 都实现了这样的功能。实际上很多开源网关在这一特性上均存在较大的局限性,本文暂不讨论这些局限性,而是针对服务发现这一通用的场景,分享我对它的一些思考。
过去一年,我的工作重心投入到了 API 网关(阿里云 CSB)中,这对于我来说是一个新的领域,但和之前接触的微服务治理方向又密不可分。API 网关适配微服务场景需要完成一些基础能力的建设,其一便是对接注册中心,从而作为微服务的入口流量,例如 Zuul、SpringCloud Gateway 都实现了这样的功能。实际上很多开源网关在这一特性上均存在较大的局限性,本文暂不讨论这些局限性,而是针对服务发现这一通用的场景,分享我对它的一些思考。
路由(Route)的设计广泛存在于众多领域,以 RPC 框架 Dubbo 为例,就有标签路由、脚本路由、权重路由、同机房路由等实现。
在框架设计层面,路由层往往位于负载均衡层之前,在进行选址时,路由完成的是 N 选 M(M <= N),而负载均衡完成的是 M 选一,共同影响选址逻辑,最后触发调用。
在业务层面,路由往往是为了实现一定的业务语义,对流量进行调度,所以服务治理框架通常提供的都是基础的路由扩展能力,使用者根据业务场景进行扩展。
今天这篇文章将会围绕路由层该如何设计展开。
这是一篇很久之前就想动笔写的文章,最近正好看到群里有小伙伴分享了 Dubbo 连接相关的文章,才又让我想起了这个话题。今天想跟大家聊的便是 Dubbo 中的连接控制这一话题。说到“连接控制”,可能有读者还没反应过来,但你对下面的配置可能不会感到陌生:
1 | <dubbo:reference interface="com.foo.BarService" connections="10" /> |
如果你还不了解 Dubbo 中连接控制的用法,可以参考官方文档:https://dubbo.apache.org/zh/docs/advanced/config-connections/ ,话说最近 Dubbo 官方文档来了一次大换血,好多熟悉的文档差点都没找到在哪儿 Orz。
众所周知,dubbo 协议通信默认是长连接,连接配置功能用于决定消费者与提供者建立的长连接数。但官方文档只给出了该功能的使用方法,却并没有说明什么时候应该配置连接控制,本文将主要围绕该话题进行探讨。
本文也会涉及长连接相关的一些知识点。
今天要聊的技术是序列化,这不是我第一次写序列化相关的文章了,今天动笔之前,我还特地去博客翻了下我博客早期的一篇序列化文章(如下图),竟然都过去 4 年了。
为什么又想聊序列化了呢?因为最近的工作用到了序列化相关的内容,其次,这几年 Dubbo 也发生了翻天覆地的变化,其中 Dubbo 3.0 主推的 Tripple 协议,更是打着下一代 RPC 通信协议的旗号,有取代 Dubbo 协议的势头。而 Tripple 协议使用的便是 Protobuf 序列化方案。
另外,Dubbo 社区也专门搞了一个序列化压测的项目:https://github.com/apache/dubbo-benchmark.git ,本文也将围绕这个项目,从性能维度展开对 Dubbo 支持的各个序列化框架的讨论。
最近几年,各种新的高效序列化方式层出不穷,最典型的包括:
为什么开源社区涌现了这么多的序列化框架,Dubbo 也扩展了这么多的序列化实现呢?主要还是为了满足不同的需求。
序列化框架的选择主要有以下几个方面:
和 CAP 理论有点类似,目前市面上很少有一款序列化框架能够同时在三个方面做到突出,例如 Hessian2 在兼容性方面的表现十分优秀,性能也尚可,Dubbo 便使用了其作为默认序列化实现,而性能方面它其实是不如 Kryo 和 FST 的,在跨语言这一层面,它表现的也远不如 ProtoBuf,JSON。
其实反过来想想,要是有一个序列化方案既是跨语言的,又有超高的性能,又有很好的兼容性,那不早就成为分布式领域的标准了?其他框架早就被干趴了。
大多数时候,我们是挑选自己关注的点,找到合适的框架,满足我们的诉求,这才导致了序列化框架百花齐放的局面。
很多序列化框架都宣称自己是“高性能”的,光他们说不行呀,我还是比较笃信“benchmark everything”的箴言,这样得出的结论,更能让我对各个技术有自己的认知,避免人云亦云,避免被不是很权威的博文误导。
怎么做性能测试呢?例如像这样?
1 | long start = System.currentTimeMillis(); |
貌似不太高大上,但又说不上有什么问题。如果你这么想,那我推荐你了解下 JMH 基准测试框架,我之前写过的一篇文章《JAVA 拾遗 — JMH 与 8 个测试陷阱》推荐你先阅读以下。
事实上,Dubbo 社区的贡献者们早就搭建了一个比较完备的 Dubbo 序列化基础测试工程:https://github.com/apache/dubbo-benchmark.git。
你只要具备基本的 JMH 和 Dubbo 的知识,就可以测试出在 Dubbo 场景下各个序列化框架的表现。
我这里也准备了一份我测试的报告,供读者们参考。如果大家准备自行测试,不建议在个人 windows/mac 上 benchmark,结论可能会不准确。我使用了两台阿里云的 ECS 来进行测试,测试环境:Aliyun Linux,4c8g,启动脚本:
1 | java -server -Xmx2g -Xms2g -XX:MaxDirectMemorySize=1g -XX:+UseG1GC -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -Xloggc:/home/admin/ |
为啥选择这个配置?我手上正好有两台这样的资源,没有特殊的设置~,况且从启动脚本就可以看出来,压测程序不会占用太多资源,我都没用满。
测试工程介绍:
1 | public interface UserService { |
一个 UserService
接口对业务应用中的 CRUD 操作。server 端以不同的序列化方案提供该服务,client 使用 JMH 进行多轮压测。
1 |
|
整体的 benchmark 框架结构如上,详细的实现,可以参考源码。我这里只选择的一个评测指标 Throughput,即吞吐量。
省略一系列压测过程,直接给出结果:
Kryo
1 | Benchmark Mode Cnt Score Error Units |
Fst
1 | Benchmark Mode Cnt Score Error Units |
Hessian2
1 | Benchmark Mode Cnt Score Error Units |
FastJson
1 | Benchmark Mode Cnt Score Error Units |
Tripple
1 | Benchmark Mode Cnt Score Error Units |
怎么看到这个测试结果呢?createUser、existUser、getUser 这几个方法测试下来,效果是参差不齐的,不能完全得出哪个框架性能最优,我的推测是因为序列化的数据量比较简单,量也不大,就是一个简单的 User 对象;而 listUser 的实现是返回了一个较大的 List<User>
,可以发现,Kryo 和 Fst 序列化的确表现优秀,处于第一梯队;令我意外的是 FastJson 竟然比 Hessian 还要优秀,位列第二梯队;Tripple(背后是 ProtoBuf)和 Hessian2 位列第三梯队。
当然,这样的结论一定受限于 benchmark 的模型,测试用例中模拟的 CRUD 也不一定完全贴近业务场景,毕竟业务是复杂的。
怎么样,这样的结果是不是也符合你的预期呢?
最后,聊聊你可能知道也可能不知道的一些序列化知识。
Dubbo 使用的 Hessian2 其实并不是原生的 Hessian2 方案。注意看源码中的依赖:
1 | <dependency> |
最早是阿里开源的 hessian-lite,后来随着 Dubbo 贡献给了 Apache,该项目也一并进入了 Apache,github 地址:https://github.com/apache/dubbo-hessian-lite。相比原生 Hessian2,Dubbo 独立了一个仓库致力于在 RPC 场景下,发挥出更高的性能以及满足一些定制化的需求。
Dubbo 客户端在高版本中默认是在业务线程中进行序列化的,而不是 IO 线程,你可以通过 decode.in.io 控制序列化与哪个线程绑定
1 | <dubbo:reference id="userService" check="false" |
在 benchmark 时,我发现 IO 线程中进行序列化,性能会更好,这可能和序列化本身是一个耗费 CPU 的操作,多线程无法加速反而会导致更多的竞争有关。
某些序列化实现,例如 Kryo 和 Fst 可以通过显示注册序列化的类来进行加速,如果想利用该特性来提升序列化性能,可以实现 org.apache.dubbo.common.serialize.support.SerializationOptimizer 接口。一个示例:
1 | public class SerializationOptimizerImpl implements SerializationOptimizer { |
按照大多数人的习惯,可能会觉得这很麻烦,估计很少有用户这么用。注意客户端和服务端需要同时开启这一优化。
别忘了在 protocol 上配置指定这一优化器:
1 | <dubbo:protocol name="dubbo" host="${server.host}" server="netty4" port="${server.port}" serialization="kryo" optimizer="org.apache.dubbo.benchmark.serialize.SerializationOptimizerImpl"/> |
一般而言,Dubbo 框架使用的协议(默认是 dubbo)和序列化方式(默认是 hessian2)是由服务端指定的,不需要在消费端指定。因为服务端是服务的提供者,拥有对服务的定义权,消费者在订阅服务收到服务地址通知时,服务地址会包含序列化的实现方式,Dubbo 以这样的契约方式从而实现 consumer 和 provider 的协同通信。
在大多数业务应用,应用可能既是服务 A 的提供者,同时也是服务 B 的消费者,所以建议在架构决策者层面协商固定出统一的协议,如果没有特殊需求,保持默认值即可。
但如果应用仅仅作为消费者,而又想指定序列化协议或者优化器(某些特殊场景),注意这时候配置 protolcol 是不生效的,因为没有服务提供者是不会触发 protocol 的配置流程的。可以像下面这样指定消费者的配置:
1 | <dubbo:reference id="userService" check="false" |
&
代表 &,避免 xml 中的转义问题
借 Dubbo 中各个序列化框架的实现,本文探讨了选择序列化框架时我们的关注点,并探讨了各个序列化实现在 Dubbo 中具体的性能表现, 给出了详细的测试报告,同时,也给出了一些序列化的小技巧,如果在 Dubbo 中修改默认的序列化行为,你可能需要关注这些细节。
最后再借 Dubbo3 支持的 Tripple 协议来聊一下技术发展趋势的问题。我们知道 json 能替代 xml 作为众多前后端开发者耳熟能详的一个技术,并不是因为其性能如何如何,而是在于其恰如其分的解决了大家的问题。一个技术能否流行,也是如此,一定在于其帮助用户解决了痛点。至于解决了什么问题,在各个历史发展阶段又是不同的,曾经,Dubbo2.x 凭借着其丰富的扩展能力,强大的性能,活跃度高的社区等优势帮助用户解决一系列的难题,也获得了非常多用户的亲来;现在,Dubbo3.x 提出的应用级服务发现、统一治理规则、Tripple 协议,也是在尝试解决云原生时代下的难题,如多语言,适配云原生基础设施等,追赶时代,帮助用户。
转载自:https://www.dozer.cc/2014/12/netty-long-connection.html
原文作者:dozer
还记得一年半前,做的一个项目需要用到 Android 推送服务。和 iOS 不同,Android 生态中没有统一的推送服务。Google 虽然有 Google Cloud Messaging ,但是连国外都没统一,更别说国内了,直接被墙。
所以之前在 Android 上做推送大部分只能靠轮询。而我们之前在技术调研的时候,搜到了 jPush 的博客,上面介绍了一些他们的技术特点,他们主要做的其实就是移动网络下的长连接服务。单机 50W-100W 的连接的确是吓我一跳!后来我们也采用了他们的免费方案,因为是一个受众面很小的产品,所以他们的免费版够我们用了。一年多下来,运作稳定,非常不错!
时隔两年,换了部门后,竟然接到了一项任务,优化公司自己的长连接服务端。
再次搜索网上技术资料后才发现,相关的很多难点都被攻破,网上也有了很多的总结文章,单机 50W-100W 的连接完全不是梦,其实人人都可以做到。但是光有连接还不够,QPS 也要一起上去。
所以,这篇文章就是汇总一下利用 Netty 实现长连接服务过程中的各种难点和可优化点。
Nacos 致力于帮助您发现、配置和管理微服务。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据及流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。Nacos 是构建以“服务”为中心的现代应用架构 (例如微服务范式、云原生范式) 的服务基础设施。
在接下里的教程中,将使用 Nacos 作为微服务架构中的注册中心,替代 ZooKeeper 传统方案。
社区版本 Dubbo 从 2.7.5 版本开始,新引入了一种基于应用粒度的服务发现机制,这是 Dubbo 为适配云原生基础设施的一步重要探索。版本发布到现在已有近半年时间,经过这段时间的探索与总结,我们对这套机制的可行性与稳定性有了更全面、深入的认识;同时在 Dubbo 3.0 的规划也在全面进行中,如何让应用级服务发现成为未来下一代服务框架 Dubbo 3.0 的基础服务模型,解决云原生、规模化微服务集群扩容与可伸缩性问题,也已经成为我们当前工作的重点。
既然这套新机制如此重要,那它到底是怎么工作的,今天我们就来详细解读一下。在最开始的社区版本,我们给这个机制取了一个神秘的名字 - 服务自省,下文将进一步解释这个名字的由来,并引用服务自省代指这套应用级服务发现机制。
熟悉 Dubbo 开发者应该都知道,一直以来都是面向 RPC 方法去定义服务的,并且这也是 Dubbo 开发友好性、治理功能强的基础。既然如此,那我们为什么还要定义个应用粒度的服务发现机制那?这个机制到底是怎么工作的?它与当前机制的区别是什么?它能给我们带来哪些好处那?对适配云原生、性能提升又有哪些帮助?
带着所有的这些问题,我们开始本文的讲解。
近日,有报道称在 HashCorp 的商业软件试用协议上发现,旗下所有商业产品禁止在中国境内使用、部署、安装,这其中就包含了 Terraform, Consul, Vagrant 等众多知名软件,其中 Consul 是一个在微服务领域的开源软件,可以用于做注册发现、配置管理等场景。
该新闻在国内发酵后,有人在 Twitter上咨询了HashCorp 公司的创始人,得到的回复是影响的软件仅限于 Vault 这款加密软件,目前 HashCorp 公司的官方网站上已经更新了相关的条款,明确了受影响的产品仅限 Vault 这一款产品。
上面的条款里只提到了商业软件,那么开源的 Consul 是否受到影响呢?在 Github 的 Consul 仓库上,可以得知项目的 license 是 Mozilla Public License 2.0
,这款许可证在 Apache 官网上是 Category B
, 属于 Weak Copy Left
许可,那么它有哪些特点呢?
可以看到,MPL 通常被认为是介于 Apache License 和 GPL/LGPL 之间的一个折中方案。相对于 Apache License,MPL 2.0 要求修改了源码必须保持相同协议;相对于 GPL/LGPL, MPL 2.0 可以商用,同时衍生的作品在一定条件下也可以更换许可证类型。
总体来看的话,开源版 Consul 无论是私用还是商用都是不受限制的。但这也可能是一个警钟,如果对 Consul 还是有所顾忌的话,如何替代掉它呢?
在微服务领域,Consul 主要被用来做充当注册中心和配置中心,例如 Dubbo 和 SpringCloud 都有对应的支持。本文便以这个事为一个引子,介绍如何平滑地迁移 Dubbo 服务,达到替换注册中心的效果。
2020 是多事的一年,新冠状性病毒的肆虐,其次是自己也生了一场病,希望随着天气暖和起来,一起都能变得更好。
前一段时间真的很忙,一直没有抽出时间,也没有什么思路给大家分享优质的文章,今天这篇文章很久之前就想写了,抓住这次假期的尾巴,总结一下我最近这一年的工作。
在此文之前,我写过一篇 《一文聊透 Dubbo 优雅停机》,这篇文章算是一个续集,优雅停机和优雅上线两者都是微服务生命周期中,开发者必须关心的环节。
优雅上线还有很多称呼:「无损上线」,「延迟发布」,「延迟暴露」。它们的对立面自然是:「有损上线」,「直接发布」。
我最近写的「一文聊透 Dubbo xx」系列文章,都有一个特点,即当你不注重文章中实践,你的 Dubbo 应用依旧可以正常运行,但总归在某些场景 case 下,你的系统会出现问题。做不到优雅上线,你的系统将会出现:在应用刚启动时,就有流量进入,而此时应用尚未初始化完毕,导致调用失败,在集群规模较大时,影响会变得很明显。
Update your browser to view this website correctly.&npsb;Update my browser now