k8凯发官网
您当前的位置: > k8凯发官网 >

Dubbo 在 K8s 下的思考

编辑: 时间:2019-11-22 浏览:173

  Dubbo在2011开源之后,一直是国内最受欢迎的RPC框架,之后spring boot和Spring Cloud的面世,助推了微服务的火热程度。计算机的世界变化很快,自从容器和K8s登上舞台之后,给原有的RPC领域带来了很大的挑战。这个文章主要讲述RPC领域遇到的问题,以及RPC怎么去拥抱K8s怀抱的一些思考。

  kubernetes是一个开源的,用于管理云平台中多个主机上的容器化的应用,Kubernetes的目标是让部署容器化的应用简单并且高效,Kubernetes提供了应用部署,规划,更新,维护的一种机制。kubernetes简称K8s。

  在Kubernetes中,最小的管理元素不是一个个独立的容器,而是Pod。Pod的生命周期需要注意以下几点:

  如果一些Pods 提供了一些功能供其它的Pod使用,在kubernete集群中是如何实现让这些前台能够持续的追踪到这些后台的?答案是:Service。

  默认的Service,通过一个集群Ip获取A Record。但是有时需要返回所有满足条件的Pod Ip列表,这时候可以直接使用Headless Services。

  随着微服务的普及,应用之间的通信有了足够多的成熟方案。Dubbo在2011年开源之后,被大量的中小型公司采用;在Spring Boot推出之后,Spring逐渐焕发出第二春,随即Spring Cloud面世,逐渐占领市场,在中国市场中,和Dubbo分庭抗争;gRPC是google推出的基于Http2的端到端的通信工具,逐渐地在K8s市场上占据统治地位,如etcd,istio等都采用gRPC作为通信工具;Service Mesh从开始概念上就火热,现在逐渐走向成熟,Istio + Envoy(其他sidecar)逐渐开始走上舞台。

  从功能层面来说,对开发者有感知的功能有:服务实现,服务暴露(注解或配置),服务调用(注解或配置),服务治理等。

  从选型角度会关注以下几点:易用性(开发易用性和开箱即用),性能,功能,扩展性等。

  关键知识点:序列化,网络通信,服务路由,负载均衡,服务限流,熔断,降级等服务治理。

  Dubbo提供了面向接口的远程方法调用。应用开发者定义接口,编写服务并暴露;Client端通过接口进行调用。

  Dubbo支持条件路由,脚本路由,Tag路由等。这些路由规则都是强依赖于IP地址。

  备注:Dubbo和HSF的大部分机制都是相似的,所以下面都以Dubbo作为方案进行讨论。

  Spring Cloud提供了一套标准API,而其中Netflix是其中的佼佼者,对这套API进行了实现,对大部分开发者来说,可以回直接依赖和使用Netflix,所以可以说是Netflix提供成了Spring Cloud的核心。但是作为商业公司对开源投入往往会多变,如Eureka已经体制维护。

  gRPC 是一个 基于 HTTP/2 协议设计的 RPC 框架,它采用了 Protobuf 作为 IDL。gRPC作为端到端的通信方案,可以解决现在的多语言问题。

  gRPC本身不提供服务注册,服务治理的功能。但现在可以看到gRPC有趋势往这方面扩展的野心。

  K8s体系下,默认情况下,Pod的Ip是变化的,所以Pod和Pod之间需要通信的话,有几种方式:

  Istio的控制层会向K8s的api server请求并监听Pod信息,service信息等信息。这样Istio中就有了完整的K8s集群中的Pod,service等的完整信息。如果K8s集群中有信息变更,istio中也可以得到通知并更新对应的信息。

  Envoy作为Proxy一个最常见的实现,以Envoy作为例子简单介绍。Envoy 通过查询文件或管理服务器来动态发现资源。对应的发现服务及其相应的 API 被称作 xDS。协议内容包括LDS,RDS,CDS等等。

  备注:上述知识是通过查阅资料(Istio官网),以及和集团service mesh同学沟通获得。如有问题,欢迎指正。

  Dubbo默认是基于TCP通信,Spring Cloud大部分基于Rest请求。在阿里云实施商业化过程中,发现大量公司需要Spring Cloud应用和Dubbo进行通信,社区主要依靠Dubbo上增加一层网关来解决。

  K8s下Pod的IP是变化的 (默认),dubbo的服务治理高度依赖IP。

  K8s的服务注册通过Pod定义完成,服务发现其实是寻找Pod的过程。Pod和应用有一定的对应关系,和dubbo里的接口维度的服务注册发现模型不是很匹配。

  如果公司已经在部署了RPC框架,这时候如果需要实施Service Mesh,有什么好的过渡方案吗?

  服务在功能维度对应某一功能,如查询已买订单详情。在Dubbo中,对应某个接口下的方法;在Spring Cloud和gRPC对应一个Http请求。如果从面向函数编程角度,一个服务就是一个function。在Java语言中,class是一切编程的基础,所以将某些服务按照一定的维度进行聚合,放到某个接口中,就成了一个接口包含了很多的服务。

  从Dubbo角度来解释下:Dubbo是面向接口编程的远程通信,所以Dubbo是面向服务集的编程,你如果想调用某个服务,必须通过接口的方式引入,然后调用接口中的某个服务。Dubbo Ops中提供的服务查询功能,其实不是查询单个服务,而是通过查询接口(服务集)之后获得具体的方法(服务)。

  而在Spring Cloud的世界里,服务提供方会将自己的应用信息(Ip+port)注册成应用下的一个实例,服务消费方和服务提供方按照约定的形式进行Rest请求。每个请求对应的也是一个服务。

  K8s里的service其实是对应到一组Pod+port列表,和DNS联系紧密;用通俗易懂的方式表达:维护了Pod集合的关系映射。和上面讲的服务是属于不同场景下的两个概念。

  按照这个方式定义服务,服务治理的粒度其实也是按照服务粒度,可以针对每个服务设置超时时间,设置路由规则等等。但是服务注册的粒度和服务有什么关系呢?

  一个应用下包含了很多接口,一个接口下包含了很多服务(Dubbo);或者一个应用包含了很多的服务(Spring Cloud)。分析下应用维度注册和接口维度注册的优缺点。会有一篇独立的文章来阐述应用维度注册的方案。

  应用拆分或者合并的时候,Client端需要感知 (如果想做到不感知,需要框架开发者维护一份接口和应用映射关系的存储)

  如果想对用户保持Dubbo原有的接口维度的查询,需要较多的工作量来保证。

  对用户透明度有所减少,需要在OPS上提供其他一些工具。如供应用开发者可以查看具体某个Ip是否提供了某个服务等等。

  Dubbo实现中,支持将以Rest协议进行暴露,并且让Spring Cloud识别。@桃谷

  在K8s已经阐述过,下面的内容也是假设一个应用部署在一个容器里,一个容器部署在一个Pod里。

  接下来方案的讨论,互相之间其实是有关联的,如服务治理可能会影响到服务注册发现,服务查询也不能依赖于服务注册的内容。整个设计的过程是不断优化的过程。下面所说的内容,以Dubbo来举例说明。

  Dubbo原有体系里的服务治理是强依赖于IP,当配置了一套服务治理规则的时候,最后都是基于一个或多个Ip地址。

  到K8s体系下之后,要考虑的是Pod的Ip不是固定的。所以当前的路由规则不能满足条件,而且会产生很多规则垃圾数据。K8s体系下,通过service查找Pod,是基于label selector; 通过deployment管理Pod,其实也是基于Pod label selector。所以Pod label selector是在K8s习题中比较通用的解决方案。

  以路由规则为例,需要支持一种新的路由规则:label路由。通过一定条件匹配之后,将结果定位到以label selector查询到的Pod列表里,而非原来的Ip列表。

  Dubbo提供对环境变量读取的支持,Pod中需要按照Dubbo定义的环境变量设置具体的Pod信息。

  依赖于应用能获取自身的Pod信息,同时将自身的Pod信息暴露成服务(rest或dubbo协议)

  通过拿到Server端的Ip或者host,Client端就可以发起Http或者其他协议的请求。

  带来的问题是增加了ZooKeeper的维护,同时这个方案很不云原生,和K8s的体系没有任何关系。

  这种方案中K8s service的定义被改造了,而且定义了过多的service,service的维护管理是个难题。

  在传统的RPC领域,服务分成服务注册和服务发现。在K8s领域Pod和应用是一对一的关系,K8s本身就提供了Pod查找的能力,所以一定程度上服务注册其实可以不存在,而只需要服务发现。但是这个其实需要一个前提:

  如果K8s service提供了cluster Ip,那么Dubbo只负责调用该集群Ip,路由和负载均衡的逻辑则交给了K8s的proxy来完成。此方案削减了Dubbo的核心能力。

  Pod的容器中部署的dubbo应用,服务注册流程可以直接删除,服务发现功能通过和Api Server进行交互,获取Pod和service信息,同时watch Pod和service的变更。通过这种方式之后,服务治理相关的信息也可以通过Api Server直接获取。

  Dubbo可以直接使用指定Ip+端口的方式调用同一个Pod下Envoy (也可能是同一个node的Envoy)。Dubbo将路由规则,负载均衡,熔断等功能交给Istio和Envoy。Envoy需要支持Dubbo协议的转发。

  所以Dubbo需要完成两个事情:本地IP直连(现有功能), 多余功能裁剪(暂未实现)。

  Dubbo 应用不再依赖 Envoy 作为 sidecar ,而是直接和 Istio 进行交互,把 Istio 作为注册中心,作为服务治理的配置中心。

  Dubbo 还需要去适配 istio 的一些功能,如健康检查,安全相关的逻辑。具体实现可以参考 Envoy 的实现。

  Istio 提供了跨集群和云上云下的解决方案, kubeFed 作为 K8s 的跨集群解决方案也能起到一定作用。

  这个课题的复杂度更加高,心中有了一些答案,期望大家通过上文也有一定的思考。

  Dubbo原有的服务查询是针对接口的查询,每个接口会有版本号和组别。接口名+版本号+组别确定唯一的服务集合,这个服务集下有对应的服务提供者和服务消费者(接口级依赖),服务提供者是一组Ip+port列表,服务消费者也是一组Ip+port列表。

  当做了改造成应用级别的服务注册或者直接使用K8s自带的Pod发现机制的话,需要做一些改造,这部分改造,和前面提到的一样,放到其他文章里单独说明。

  和Spring Cloud类似,支持应用维度的查询。查询到具体应用之后,应用详情下包含了Ip+port列表,每个Ip+port其实就是一个应用的实例。点击开每个应用实例,可以查看每个应用的详细信息,详细信息包含了该实例提供了哪些服务。

  在原来只支持应用查询的基础上,增加一步:支持查询某个接口对应的应用列表,而大部分接口只属于一个应用。

  上述讨论的是开源的方案,所以相对历史包袱比较少。对一些大公司想从原有的RPC方案切换到云原生的支持,需要考虑更多兼容性和性能,需要付出更大的代价。

  云原生的趋势已经势不可挡,在RPC领域究竟哪种方案最终能够胜出,现在还言之过早。我相信Service Mesh 和传统的RPC (Dubbo/ gRPC) 都会有自己的一席之地,一切让时间给我们答案吧。

  双11福利来了!先来康康#怎么买云服务器最便宜# [并不简单]参团购买指定配置云服务器仅86元/年,开团拉新享三重礼:1111红包+瓜分百万现金+31%返现,爆款必买清单,还有iPhone 11 Pro、卫衣、T恤等你来抽,马上来试试手气:

  • 点击这里给我发消息
  • 点击这里给我发消息
  • 点击这里给我发消息
  • 点击这里给我发消息