Spring Cloud Alibaba 官方实践指南【文章有点长自备咖啡茶点】

注:本文内容均转自官方文档,方便胖友们学习,不代表博主观点。

链接地址:SpringCloudAlibaba | Spring Cloud Alibaba

基于网关实现 SpringCloud 服务发现与路由 | Spring Cloud Alibaba

Spring Cloud Alibaba 应用灰度发布实践 | Spring Cloud Alibaba

应用如何平滑迁移至IPv6? | Spring Cloud Alibaba

在Proxyless Mesh上的探索 | Spring Cloud Alibaba

2022.0.0.0-RC1 版本发布啦 | Spring Cloud Alibaba

Spring Cloud Alibaba 是什么?

Spring Cloud Alibaba 为分布式应用开发提供一站式解决方案。它包含开发分布式应用程序所需的所有组件,使您可以轻松地使用 Spring Cloud 微服务框架开发应用程序。

2023年8月31日 · 阅读需 6 分钟

赵炳堃(秉钧)

使用 Nacos 做注册中心

应用配置具体参考Nacos Spring Cloud 快速开始进行应用配置

不指定命名空间

如果 application.properties 中没有指定 Nacos 命名空间,例如:

server.port=8080
spring.application.name=my-service

spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848

则 Higress 的 McpBridge 中亦无需指定命名空间:

apiVersion: networking.higress.io/v1
kind: McpBridge
metadata:
  name: default
  namespace: higress-system
spec:
  registries:
    # 定义一个名为 my-nacos  的服务来源
  - name: my-nacos
    # 注册中心类型是 Nacos 2.x,支持 gRPC 协议
    type: nacos2
    # 注册中心的访问地址,可以是域名或者IP
    domain: 127.0.0.1
    # 注册中心的访问端口,Nacos 默认都是 8848
    port: 8848
    # Nacos 服务分组
    nacosGroups:
    - DEFAULT_GROUP

配置 Ingress 转发到这个服务(假设/api前缀的路由都转发给这个服务)需要做如下配置:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    higress.io/destination: my-service.DEFAULT-GROUP.public.nacos
  name: demo
  namespace: default
spec:
  rules:
  - http:
      paths:
      - backend:
          resource:
            apiGroup: networking.higress.io
            kind: McpBridge
            name: default
        path: /api
        pathType: Prefix

注意这里通过注解higress.io/destination指定路由最终要转发到的目标服务。

对于 Nacos 来源的服务,这里的目标服务格式为:“服务名称.服务分组.命名空间ID.nacos”,注意这里需要遵循 DNS 域名格式,因此服务分组中的下划线'_'被转换成了横杠'-'。命名空间未指定时,这里默认值为"public"。

指定命名空间、服务分组等信息

如果 application.properties 中指定了 Nacos 命名空间,服务分组等信息,例如:

server.port=8080
spring.application.name=my-service

spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
spring.cloud.nacos.discovery.namespace=d8ac64f3-xxxx-xxxx-xxxx-47a814ecf358
spring.cloud.nacos.discovery.group=custom-group

则 Higress 的 McpBridge 做相应配置即可

apiVersion: networking.higress.io/v1
kind: McpBridge
metadata:
  name: default
  namespace: higress-system
spec:
  registries:
    # 定义一个名为 my-nacos  的服务来源
  - name: my-nacos
    # 注册中心类型是 Nacos 2.x,支持 gRPC 协议
    type: nacos2
    # 注册中心的访问地址,可以是域名或者IP
    domain: 127.0.0.1
    # 注册中心的访问端口,Nacos 默认都是 8848
    port: 8848
    # Nacos 命名空间 ID
    nacosNamespaceId: d8ac64f3-xxxx-xxxx-xxxx-47a814ecf358
    # Nacos 服务分组
    nacosGroups:
    - custom-group

配置 Ingress 转发到这个服务(假设/api前缀的路由都转发给这个服务)需要做如下配置:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    higress.io/destination: my-service.custom-group.d8ac64f3-xxxx-xxxx-xxxx-47a814ecf358.nacos
  name: demo
  namespace: default
spec:
  rules:
  - http:
      paths:
      - backend:
          resource:
            apiGroup: networking.higress.io
            kind: McpBridge
            name: default
        path: /api
        pathType: Prefix

使用 ZooKeeper 做注册中心

使用 Zookeeper 做注册中心时,注意必须配置spring.cloud.zookeeper.discovery.preferIpAddress=true,否则注册到注册中心中到地址为主机名称,而不是IP。

不指定注册根路径

如果 application.properties 中未指定注册根路径信息,例如:

spring.application.name=my-service
spring.cloud.zookeeper.connect-string=127.0.0.1:2181
spring.cloud.zookeeper.discovery.preferIpAddress=true
spring.cloud.zookeeper.discovery.enabled=true
spring.cloud.zookeeper.discovery.register=true

则 Higress 的 McpBridge 中亦无需指定zkServicePath:

apiVersion: networking.higress.io/v1
kind: McpBridge
metadata:
  name: default
  namespace: higress-system
spec:
  registries:
    # 定义一个名为 my-zk  的服务来源
  - name: my-zk
    # 注册中心类型是 ZooKeeper
    type: zookeeper
    # 注册中心的访问地址,可以是域名或者IP
    domain: 127.0.0.1
    # 注册中心的访问端口
    port: 2181

配置 Ingress 转发到这个服务(假设/api前缀的路由都转发给这个服务)需要做如下配置:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    higress.io/destination: my-service.services.zookeeper
  name: demo
  namespace: default
spec:
  rules:
  - http:
      paths:
      - backend:
          resource:
            apiGroup: networking.higress.io
            kind: McpBridge
            name: default
        path: /api
        pathType: Prefix

注意对于 ZooKeeper 来源的服务,这里的目标服务格式为:"服务名称.服务注册根路径.zookeeper",SpringCloud 在未指定服务注册根路径的情况下,根路径默认是"services"

指定注册根路径

如果 application.properties 中指定了注册根路径信息,例如:

spring.application.name=my-service
spring.cloud.zookeeper.connect-string=127.0.0.1:2181
spring.cloud.zookeeper.discovery.preferIpAddress=true
spring.cloud.zookeeper.discovery.enabled=true
spring.cloud.zookeeper.discovery.register=true
spring.cloud.zookeeper.discovery.root=my-services-root

则 Higress 的 McpBridge中亦需指定zkServicePath:

apiVersion: networking.higress.io/v1
kind: McpBridge
metadata:
  name: default
  namespace: higress-system
spec:
  registries:
    # 定义一个名为 my-zk  的服务来源
  - name: my-zk
    # 注册中心类型是 ZooKeeper
    type: zookeeper
    # 注册中心的访问地址,可以是域名或者IP
    domain: 127.0.0.1
    # 注册中心的访问端口
    port: 2181
    # 对应 spring.cloud.zookeeper.discovery.root 配置字段
    zkServicePath:
    - my-services-root

配置 Ingress 转发到这个服务(假设/api前缀的路由都转发给这个服务)需要做如下配置:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    higress.io/destination: my-service.my-services-root.zookeeper
  name: demo
  namespace: default
spec:
  rules:
  - http:
      paths:
      - backend:
          resource:
            apiGroup: networking.higress.io
            kind: McpBridge
            name: default
        path: /api
        pathType: Prefix

注意如果 spring.cloud.zookeeper.discovery.root 中包含了下划线,需要被替换为横杠,因为目标服务整体格式需要满足 DNS 域名规范。

Spring Cloud Alibaba 应用灰度发布实践

2023年8月21日 · 阅读需 13 分钟

赵炳堃(秉钧)

Higress 是阿里巴巴开源的一款下一代云原生微服务网关。Higress 可以对接多种注册中心,包括 Nacos/Zookeeper/Eureka 等,能够无缝集成 Spring Cloud 应用,对 Dubbo/Sentinel/OpenSergo 等微服务生态也有着深度的集成。与此同时,Higress 采用 C++ 内核,相比于传统的 Java 网关来说性能更高,更稳定,对比 Spring Cloud Gateway 和 Zuul 来说,性能可以提升至2-4倍。另外,Higress 还天然兼容 K8s 的 Ingress/Gateway API 标准,是一款更符合云原生时代标准的微服务网关。

Higress 无缝对接 Spring Cloud 应用发布实战

在现代软件架构逐渐走向微服务化、云原生化的过程中,应用的更新和迭代的频率变得越来越快,如何在尽可能保证用户体验不受影响的情况下完成应用的迭代发布就显得至关重要。目前业界普遍采用的几种典型的应用发布策略包括蓝绿发布、金丝雀发布、A/B Testing发布等。接下来本文将介绍如何使用 Higress 来实现 Spring Cloud Alibaba 应用发布的最佳实践。

前提条件

  1. 安装 Higress,并安装 Istio CRD,参考Higress安装部署文档
  2. 安装 Naocs,参考Nacos安装部署文档

Higress 支持将 Nacos,Spring Cloud 应用部署于 K8s 集群内,或者独立于 K8s 进行部署。为了演示方便,本文将 Higress,Nacos,Spring Cloud 应用都部署在本地 K8s 集群。

通过 Higress 实现 Spring Cloud 应用的服务发现和路由

部署 Spring Cloud Alibaba 应用

apiVersion: apps/v1
kind: Deployment
metadata:
  name: spring-cloud-demo-v1
spec:
  replicas: 1
  selector:
    matchLabels:
      app: spring-cloud-demo
  template:
    metadata:
      labels:
        app: spring-cloud-demo
    spec:
      containers:
        - name: server
          image: higress-registry.cn-hangzhou.cr.aliyuncs.com/samples/spring-cloud-demo:v1
          imagePullPolicy: IfNotPresent
          env:
          # 注册到的nacos的地址
            - name: NACOS_REGISTRY_ADDRESS
              value: nacos-server.default.svc.cluster.local 
          # 注册时携带的version元信息
            - name: SPRING_CLOUD_NACOS_DEMO_VERSION
              value: v1

我们在 k8s 集群中部署如上 Deployment,其中通过 NACOS_REGISTRY_ADDRESS 和 SPRING_CLOUD_NACOS_DEMO_VERSION 两个环境变量指定了 Nacos 的地址以及注册时携带的 version 元信息。Spring Cloud 应用的 application.properties 配置会读取这两个环境变量,如下所示:

spring.cloud.nacos.discovery.server-addr=${NACOS_REGISTRY_ADDRESS}:8848
spring.cloud.nacos.discovery.metadata.version=${SPRING_CLOUD_NACOS_DEMO_VERSION}

配置服务来源

Higress 支持多种服务来源,包括 Nacos/Zookeeper/DNS/固定IP,通过创建 Nacos 服务来源,Higress 就可以发现注册到 Nacos上的服务,从而完成转发请求到这些服务上。 进入 Higress 控制台(http://console.higress.io/),点击 服务来源-创建服务来源 以创建服务来源。这里选择 Nacos 2.X,然后填写注册中心的地址,端口,命名空间,服务分组等信息。注册中心的地址可以填写 ip 或者域名,本文将 Nacos 部署在本地 K8s 中,通过 K8s service 暴露 Nacos 端口,因此这里填写对应的 service 域名。 

image.png

 配置好 Nacos 服务来源后,我们可以在服务列表中看到我们刚刚部署好的应用。 

image.png

创建域名和路由

在 Higress 控制台上点击域名管理-创建域名,创建一条 demo.springcloud.com 域名用于后续的访问。 

image.png

 点击路由配置-创建路由,创建一条名为 demo 的路由,域名选择我们刚刚创建好的 demo.springcloud.com,目标服务选择我们在1.2中看到的 Spring Cloud 应用,path 配置为/version。 

image.png

请求验证

接下来我们就可以用配置好的路由来访问 Spring Cloud 应用了,在请求时需要将 demo.springcloud.com 域名解析到本地 ip,如下所示,可以成功得到返回结果。 

image.png

 注:如果您将 Higress 的80和443端口通过 LoadBalancer 的方式暴露出来,这里需要将本地 ip 替换为对应 LoadBalancer 的 ip,详见Higress快速开始文档

利用Higress进行蓝绿发布

在蓝绿发布中,有两套相同的运行环境,一套是当前正在使用的生产环境(蓝色环境),另一套是新版本的测试环境(绿色环境)。新版本的代码只在绿色环境中运行,测试通过后,直接将流量切换到绿色环境中,从而完成新版本的上线。与此同时蓝色环境作为热备环境,当绿色环境出现问题需要回滚时,也可以直接将流量全部再切换回蓝色环境。 

image.png

image.png

部署新版本应用

在本地 K8s 集群中 apply 如下资源,以部署 v2 版本的 Spring Cloud 应用。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: spring-cloud-demo-v2
spec:
  replicas: 1
  selector:
    matchLabels:
      app: spring-cloud-demo
  template:
    metadata:
      labels:
        app: spring-cloud-demo
    spec:
      containers:
        - name: server
          image: higress-registry.cn-hangzhou.cr.aliyuncs.com/samples/spring-cloud-demo:v2
          imagePullPolicy: IfNotPresent
          env:
            - name: NACOS_REGISTRY_ADDRESS
              value: nacos-server.default.svc.cluster.local
            - name: SPRING_CLOUD_NACOS_DEMO_VERSION
              value: v2

部署完毕后,我们可以在 Higress 控制台的服务列表中看到应用已经有两个 endpoint 了,如下图所示: 

image.png

为服务划分子集

部署完 v2 版本的应用后,我们可以在 Nacos 控制台( http://localhost:8848/nacos ) 上看到 service-provider 这个服务有两个 ip,它们的 metadata 中的 version 字段分别为 v1 和 v2。Higress 可以根据服务的元信息将服务划分为不同的子集(subset),从而将请求转发到新版本或者老版本的应用中去。 

image.png

 在本地 K8s 集群中 apply 如下资源,从而根据应用元信息中的 version 字段将服务划分为 v1 和 v2 两个子集。

apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: demo
  namespace: higress-system
spec:
  host: service-provider.DEFAULT-GROUP.public.nacos
  subsets:
  - name: v1
    labels:
      version: v1
  - name: v2
    labels:
      version: v2

修改ingress路由规则

新版本应用上线后,我们需要把流量全部切到新版本应用中去,这时只需要简单地修改一下我们在1.3中创建的路由即可。我们可以在本地 K8s 集群中找到如下 ingress 资源,这对应了我们在1.3中创建的那条路由。 

image.png

 我们直接编辑这条 ingress 资源,将 higress.io/destination 这条 annotation 的 value 改为 service-provider.DEFAULT-GROUP.public.nacos v2,即可将路由的目标服务修改为 v2 子集。

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    higress.io/destination: service-provider.DEFAULT-GROUP.public.nacos v2
    higress.io/ignore-path-case: "false"
  labels:
    higress.io/domain_demo.springcloud.com: "true"
    higress.io/resource-definer: higress
  name: demo
  namespace: higress-system
spec:
  ingressClassName: higress
  rules:
  - host: demo.springcloud.com
    http:
      paths:
      - backend:
          resource:
            apiGroup: networking.higress.io
            kind: McpBridge
            name: default
        path: /version
        pathType: Prefix

请求验证

我们再发送请求,可以看到此时得到的是 v2 版本应用的返回结果,如此便实现了新版本的上线发布。 

image.png

 如果发现已上线的新版本出现问题需要回滚,只需要修改 ingress 路由中的 higress.io/destination,将值更改为 service-provider.DEFAULT-GROUP.public.nacos v1 即可完成回滚。

利用Higress进行金丝雀发布

金丝雀发布是将少量的请求引流到新版本上,因此部署新版本服务只需极小数的实例。验证新版本符合预期后,逐步调整流量权重比例,使得流量慢慢从老版本迁移至新版本,期间可以根据设置的流量比例,对新版本服务进行扩容,同时对老版本服务进行缩容,使得底层资源得到最大化利用。 

image.png

修改ingress路由规则

Higress 可以通过一条 Ingress 注解轻松完成应用的金丝雀发布。我们编辑2.3中的 ingress 资源,将 ingress 中的 higress.io/destination 注解按如下方式进行修改:

metadata:
  annotations:
    higress.io/destination: |
      80% service-provider.DEFAULT-GROUP.public.nacos v1
      20% service-provider.DEFAULT-GROUP.public.nacos v2

这样 Higress 就可以把80%的流量转发到 v1 版本的应用,将20%的流量转发到 v2 版本的应用。

请求验证

连续发送20条请求,可以看到 v1 和 v2 的比例符合我们在 ingress 中配置的比例。随着灰度的进行,可以逐渐调大v2版本的流量比例,最终完成新版本的平滑上线。 

image.png

利用Higress进行A/B Testing发布

A/B 测试基于用户请求的元信息将流量路由到新版本,这是一种基于请求内容匹配的灰度发布策略。只有匹配特定规则的请求才会被引流到新版本,常见的做法包括基于 HTTP Header 和 Cookie 。基于 HTTP Header 方式,例如 User-Agent 的值为 Android 的请求 (来自 Android 系统的请求)可以访问新版本,其他系统仍然访问旧版本。基于 Cookie 方式,Cookie 中通常包含具有业务语义的用户信息,例如普通用户可以访问新版本,VIP用户仍然访问旧版本。 

image.png

image.png

修改ingress路由规则

在本示例中,我们通过 HTTP header 中的 User-Agent 对流量进行区分,将 Android 系统的流量转发到 v2 版本,其他系统的流量仍保持 v1 版本。首先修改2.3中名叫 demo 的 ingress 资源,将 higress.io/destination 修改为 v1 版本,代表目前线上的流量全部会打到原来的 v1 版本:

metadata:
  annotations:
    higress.io/destination: service-provider.DEFAULT-GROUP.public.nacos v1

当新版本部署完成后,再新建一条如下所示的 ingress 路由。这里采用正则匹配的方式,当 User-Agent 中含有 Android 时,将请求转发到 v2 版本的服务。

kind: Ingress
metadata:
  annotations:
    higress.io/destination: service-provider.DEFAULT-GROUP.public.nacos v2
    higress.io/canary: "true"
    higress.io/canary-by-header: "User-Agent"
    higress.io/canary-by-header-pattern: ".*Android.*"
    higress.io/ignore-path-case: "false"
  labels:
    higress.io/domain_demo.springcloud.com: "true"
    higress.io/resource-definer: higress
  name: demo-ab
  namespace: higress-system
spec:
  ingressClassName: higress
  rules:
  - host: demo.springcloud.com
    http:
      paths:
      - backend:
          resource:
            apiGroup: networking.higress.io
            kind: McpBridge
            name: default
        path: /version
        pathType: Prefix

请求验证

可以看到来自 Android 系统的请求被转发到了 v2 版本,其余系统仍访问 v1 版本。 

image.png

 当新版本验证完毕需要全量上线时,只需要将 demo 路由的 higress.io/destination 注解修改为 v2 版本,并删除 demo-ab 路由,这样所有流量就都会访问 v2 版本了。

加入Higress和Spring Cloud Aliaba社区

Spring Cloud Alibaba 社区交流群:钉钉群号2415000986

Higress 社区交流群:

higress-comm.png

Higress 社区交流钉钉群中有历次 Higress 社区周会录屏,包括本文中提到的结合 Spring Cloud 应用发布的完整实操视频。

应用如何平滑迁移至IPv6?

2023年3月30日 · 阅读需 19 分钟

铖朴

作为下一代互联网协议,向IPv6迁移是未来的大势所趋。但由于当前互联网中IPv4协议的应用规模非常大,对于用户来说,没办法通过规定一个时间日期,从那一刻开始,所有互联网上的设备全部使用IPv6,这是不现实的。一次性迁移不仅在基础设施层面不可行,对企业用户来说,就算基础设施都能准备完毕,让其将少则上百,多则成千上万的应用实例在一段时间内一次性停机进行协议栈迁移,无论是在风险上,还是成本上,对企业用户来说都是难以接受的!既然无法一步到位,渐进式的IP地址迁移成为当前的主流选择。本文将介绍一些主流渐进式的IP地址迁移方法。

背景

IPv4协议(后文简称IPv4)为互联网的发展与普及做出了重要贡献,但近年来,随着应用程序、数据和 IT 服务的爆炸式增长。当初协议设计过程中用来描述IP地址所采用的32位二进制数格式的IPv4地址已经于2011年[1]被申请耗尽,从那时起,全世界都已经处于无新地址可用的局面。

IPv6协议(后文简称IPv6)作为IPv4之后被采用的下一代互联网协议,相比IPv4协议中采用32位来表示IP地址,其地址表示位数扩充到了128位,地址数量是IPv4所能提供的2的96次方倍。简单看数字可能显得不太直观,换成一句描述IPv6地址之多更直观和经典的话:“采用128位表示地址的IPv6可以为地球上的每一粒沙子都分配一个IP地址”!此外,IPv6协议其不仅可以解决IPv4协议中的地址短缺问题,同时也能为互联网提供更高效、更安全的网络通信。IPv6协议在网络通信中提供了许多新的功能和优势。例如,在数据传输和路由方面,其通过新的设计提高了效率和可靠性,减少了网络拥堵和数据包丢失的情况。此外,在安全领域,其内置对IPSec的支持,可以更好地保护网络中的数据传输安全,防止黑客攻击和窃取数据。 作为下一代互联网协议,向IPv6迁移是未来的大势所趋。在我国,从2014年开始相关机构已经逐步停止向新用户和应用分配IPv4地址,开始全面商用IPv6协议(计算机网络(第七版)谢希仁)。在政府引导测,近年来,陆续也出台了一系列相关指导文件例如:2017年国务院发布的《推进互联网协议第六版(IPv6)规模部署行动计划》、2021年工业与信息化部发布的《IPv6流量提升三年专项行动计划(2021-2023年)》、2021年网信办发布的《关于推动IPv6规模部署的指导意见》等不断地在引导企业从IPv4协议向IPv6协议迁移。 但由于当前互联网中IPv4协议的应用规模非常大,对于用户来说,没办法通过规定一个时间日期,从那一刻开始,所有互联网上的设备全部使用IPv6,这是不现实的。一次性迁移不仅在基础设施层面不可行,对企业用户来说,就算基础设施都能准备完毕,让其将少则上百,多则成千上万的应用实例在一段时间内一次性停机进行协议栈迁移,无论是在风险上,还是成本上,对企业用户来说都是难以接受的!既然无法一步到位,渐进式的IP地址迁移成为当前的主流选择。接下来本文将介绍一些主流渐进式的IP地址迁移方法。

迁移方案

虽然IPv6协议具有许多优势,但是其推广和应用仍然面临许多挑战。IPv6的普及需要全球范围内的配套基础措施和支持,包括网络设备的更新、人员培训和政策法规的推进等等。同时,IPv6与IPv4之间的兼容性也是一个重要的问题,需要通过技术手段和过渡机制来解决。 常见的IP协议渐进式迁移共存方案,主要有双栈(Dual Stack)、隧道(Tunneling)等技术。其中,双栈技术是目前业界应用较为广泛的一种IPv4/IPv6共存的一种技术,其目的是在互联网完全过度到IPv6之前,通过为设备安装IPv4和IPv6双协议栈。具有双栈的设备可以实现与单IPv4、单IPv6或者双栈的设备进行通信。通过让各种协议栈能共存,渐进式地进行IP协议栈的迁移。像Kubernetes很早也已经对双栈功能进行了支持。 隧道技术是一种把IPv6地址封装到IPv4数据报中的方法,当数据从IPv6单协议栈发出后,在经过IPv4单栈网络环境的过程中,将IPv6地址封装到IPv4数据报作为IPv4数据报内容后,通过IPv4协议栈进行传输。在经过IPv4单栈环境后,来到IPv6单栈环境时,再将数据报中的IPv6数据段内容解析出来,构造新的IPv6数据报在IPv6协议栈环境中进行传输。

微服务双栈迁移方案

上文介绍的方案更多的是一般化的方法论。但具体到微服务系统中,远程调用过程如何实现多协议栈共存以便帮助企业用户平滑进行协议栈的迁移呢? 

image.png

 上图是当前业界微服务系统中服务之间普遍采用的远程调用过程架构图,本文接下来介绍如何基于双栈技术实现微服务应用的协议栈平滑迁移的常用方式。

双注册双订阅实现协议栈平滑迁移

在微服务系统中,相比于单栈环境下,只有一个IP地址,微服务的注册与发现过程都基于该地址完成服务远程调用。在多协议栈共存的环境中,其本质就是要解决服务注册和发现过程怎么使用IP地址的问题。 梳理清楚了问题,就不难发现基于双注册双订阅的方法可以较好地解决微服务系统中多协议栈共存的问题,以便实现微服务系统协议栈的平滑迁移。该方案的服务注册和订阅过程可以被描述为下图所示: 

image.png

采用双注册双订阅实现微服务系统平滑进行IP协议栈迁移的过程可以被大致描述为以下步骤:

  1. 在新的应用升级或者发版之前,对相关微服务应用所在宿主机进行IP地址协议栈升级改造,让其同时支持IPv4和IPv6双协议栈。
  2. 经过步骤1改造的微服务应用,在微服务框架层面,通过一个双栈地址提取模块提取应用宿主机中有效的IPv4和IPv6地址,并通过服务注册模块,将双栈地址都注册到注册中心。
  3. 消费者订阅注册中心中的某个服务的IPv4和IPv6双栈地址,通过应用服务框架层面的双栈地址解析模块,比对宿主机所支持的协议栈类型,如果宿主机仅支持IPv4协议,则使用提供者的IPv4地址发起服务调用;如果仅支持IPv6或同时支持双栈,则用提供者的IPv6地址发起服务调用;
  4. 当系统中的所有微服务都完成支持IPv6协议栈的支持后,逐步对所有应用宿主机关闭IPv4协议栈,从而平滑完成大规模微服务系统从IPv4协议栈到IPv6协议栈的迁移。

基于DNS技术实现协议栈平滑迁移

双注册双订阅的方法虽然很自然和清晰,但是其由于服务注册过程中针对双栈环境中的应用会多注册一条IP地址对应的记录,会降低注册中心的服务承载量。 因此,也可以基于DNS技术实现多协议栈共存,解决微服务系统协议栈迁移的方法。其本质是将原来的注册服务实例地址过程变成注册服务实例域名(这里域名更多是实例标识作用),可实现在注册中心所注册服务实例记录数量不变的情况下,通过额外的DNS域名系统存储服务域名所对应的双栈IP地址,从而实现多协议栈的共存。采用该方案的服务注册和订阅过程如下图所示: 

image.png

 基于DNS技术实现微服务系统平滑进行IP地址迁移的过程可以被大致描述为以下步骤:

  1. 在新的应用升级或者发版之前,对相关微服务应用进行IP地址协议栈改造,让其同时支持IPv4和IPv6双协议栈。改造后的应用需要将本机的双栈IP地址信息和本应用实例特点的域名注册到系统的DNS服务上。
  2. 完成域名注册后,应用实例将本地域名注册到注册中心。
  3. 消费者订阅注册中心中的某个服务所有实例的域名,通过应用框架层面的域名解析模块,向系统中的DNS服务发起基于域名解析请求,在通过DNS获取到示例域名对应的IP地址后,比对宿主机所支持的协议栈类型,如果宿主机仅支持IPv4,则使用IPv4地址发起服务调用;如果仅支持IPv6或同时支持双栈,则优先使用IPv6地址发起服务调用;
  4. 当系统中的所有微服务都完成支持IPv6协议栈的支持后,逐步对所有应用宿主机关闭IPv4协议栈,从而平滑完成大规模微服务系统从IPv4协议栈到IPv6协议栈的迁移。

相比于双注册双订阅方式,基于DNS的方法可以较好地解决双注册双订阅过程中带给注册中心的多余压力,但DNS的高可用也是企业用户需要特别注意的点。

实践

Spring Cloud Alibaba作为应用广泛的微服务框架,目前在2021.0.5.0版本中已经提供了微服务场景下的不同协议栈应用互通共存方案,以便帮助企业用户实现大规模微服务系统的协议栈迁移能力。社区方案基于双注册双订阅实现,应用启动后会默认将微服务的IPv4地址和IPv6地址注册到注册中心中,其中IPv4地址会存放在Nacos服务列表中的IP字段下,IPv6地址在Nacos的metadata字段中,其对应的Key为IPv6(可以解决普通双注册双订阅过程中的同一个服务实例有两条记录,对注册中心造成压力的问题)。当服务消费者调用服务提供者时,会根据自身的IP协议栈支持情况,选择合适的IP地址类型发起服务调用。具体规则:

  1. 服务消费者本身支持IPv4和IPv6双协议栈或仅支持IPv6协议栈的情况下,服务消费者会使用服务提供的IPv6地址发起服务调用;
  2. 服务消费者本身仅支持IPv4单协议栈的情况下,服务消费者会使用服务提供的IPv4地址发起服务调用。

应用配置

相比于一般使用Spring Cloud Alibaba构建微服务,要使用协议栈共存迁移功能需要对应用增加如下配置:

服务注册

目前,使用支持协议栈共存迁移功能的Spring Cloud Alibaba版本以后,服务提供者在进行服务注册过中,不需要做任何配置,会默认检查当前应用所支持的协议栈情况,如果默认是单IPv6或IPv4协议栈,则仅注册相应的地址。如果应用支持双栈,则会自动获取应用的IPv6地址,然后,将IPv6地址作为应用实例的服务示例元数据注册到注册中心上。

服务消费

如果应用是采用Spring Cloud Alibaba 2021.0.5.0版本,默认使用Spring Cloud LoadBalancer负载均衡策略,需要在消费者应用application.properties配置文件中增加如下配置开启协议栈共存迁移功能:

spring.cloud.loadbalancer.ribbon.enabled=false
spring.cloud.loadbalancer.nacos.enabled=true

效果演示

为了便于演示,本文直接基于阿里云容器服务ACK构建了一个双栈环境,来进行双栈环境的服务注册与消费演示。

服务注册

如下本文演示用的服务提供者实例Pod信息: 

image.png

 基于Spring Cloud Alibaba协议栈共存迁移功能,其在注册中心上的服务实例列表信息: 

image.png

服务消费

单栈环境服务消费者: 

image.png

 服务调用成功以后,服务提供者会打印调用消费者的调用IP地址: 

image.png

 从上述返回结果来看,IPv4单栈环境中的消费者由于仅支持单栈,所以一直通过IPv4协议栈向双栈服务提供者发起请求。 双栈环境服务消费者: 

image.png

 服务调用成功以后,服务提供者会打印调用消费者的调用IP地址,可以看到打印的是消费者的IPv6地址: 

image.png

 从上述返回结果来看,IPv4/IPv6双栈环境中的消费者由于支持IPv6,为了实现协议栈向IPv6的迁移,所以默认一直通过IPv6协议栈向双栈服务提供者发起请求。

在Proxyless Mesh上的探索

2023年1月20日 · 阅读需 24 分钟

铖朴

经过过去几年的发展,Service Mesh已再是一个新兴的概念,其从一经推出就受到来自全世界的主流技术公司关注和追捧。Proxyless Mesh全称是Proxyless Service Mesh,其是近几年在Service Mesh基础上发展而来的一种新型软件架构。Service Mesh理想很丰满,但现实很骨感!通过一层代理虽然做到了对应用无侵入,但增加的网络代理开销对很多性能要求很高的互联网业务落地存在不少挑战。因此Proxyless Mesh作为一种在传统侵入式微服务框架与Service Mesh之间的折中方案,通过取众家之所长,为大量的非Service Mesh应用在云原生时代,拥抱云原生基础设施,解决流量治理等痛点提供了一种有效的解决方案。本文将介绍Spring Cloud Alibaba在Proxyless Mesh上的探索。

Service Mesh

站在2023年的今天,Service Mesh 早已不是一个新兴的概念, 回顾过去6年多的发展历程,Service Mesh 从一经推出就受到来自全世界的主流技术公司关注和追捧。

  • 2016 年作为 Service Mesh 的元年,Buoyant 公司 CEO William Morgan 率先发布 Linkerd[1] ,成为业界首个 Service Mesh 项目,同年 Lyft 发布 Envoy[2] ,成为第二个 Service Mesh 项目。
  • 2017年,Google、IBM、Lyft 联手发布了 Istio[3],它与 Linkerd / Envoy 等项目相比,它首次给大家增加了控制平面的概念,提供了强大的流量控制能力。经过多年的发展 Istio,已经逐步成为服务网格领域控制平面的事实标准。
  • 2018年7月,Istio 1.0版本发布[4],标志着其进入了可以生产可用的时代,逐渐也有越来越多的企业开始考虑和尝试将服务网格应用于生产中。

Istio 作为当前最流行的开源服务网格技术,它由控制平面和数据平面两部分构成。 

image.png

 在 Istio Mesh 架构中,其控制平面是一个名为 Istiod 的进程,网络代理是 Envoy 。Istiod 作为控制面的统一组件,负责对接服务注册发现、路由规则管理、证书管理等能力,Envoy 则是作为数据面通过 Sidecar 方式代理业务流量,Istio 和 Envoy 之间通过 xDS 协议接口完成服务发现、路由规则等数据的传递。Istiod 通过监听 K8s 资源例如 Service、Endpoint 等,获取服务信息,并将这些资源统一通过 xDS 协议下发给位于数据平面的网络代理。Envoy 则是独立于应用之外的一个进程,以 Sidecar 的方式(一般是以 Container 方式)伴随业务应用 Pod 运行,它与应用进程共用同一个主机网络,通过修改路由表的方式劫持业务应用的网络流量从而达到为应用无侵入地提供如服务鉴权、标签路由等能力。

Proxyless Mesh

Proxyless Mesh 全称是 Proxyless Service Mesh,其是近几年在 Service Mesh 基础上发展而来的一种新型软件架构。Service Mesh 理想很丰满,但现实很骨感!通过一层代理虽然做到了对应用无侵入,但增加的网络代理开销对很多性能要求很高的互联网业务落地存在不少挑战。因此Proxyless Mesh作为一种在传统侵入式微服务框架与Service Mesh之间的折中方案,通过取众家之所长,为大量的非Service Mesh应用在云原生时代,拥抱云原生基础设施,解决流量治理等痛点提供了一种有效的解决方案。 Service Mesh 和 Proxyless Mesh 架构区别如下图所示: 

image.png

 过去几年,国内外的知名软件开源社区也都在相关领域进行了大量探索,例如在2021年10月,gRPC社区为用户提供如下架构形式[5],通过对接Istio控制平面,遵循 VirtualService & DestinationRule CRD规范为gRPC应用提供流量治理能力。 

image.png

Spring Cloud Alibaba Mesh 化方案

Spring Cloud Alibaba作为一种侵入式的微服务解决方案,通过基于Spring Cloud微服务标准为用户提供了微服务应用构建过程中的如服务注册与发现、限流降级、分布式事务与分布式消息等在内的一站式微服务解决方案。过去几年被国内大量中小企业所采用,帮助大量企业更加方便地拥抱微服务。 但随着企业应用微服化的不断深入,微服务给应用带来系统解耦、高可扩展性等诸多优势的同时,也让应用变得更加复杂。如何管理好微服务?成为了很多企业逐渐开始关注和重视的一个新的问题。Spring Cloud Alibaba社区也注意到很多用户有微服务治理方面的诉求,于是从2022年初,就开始了在该方面的探索,社区觉得相比于Service Mesh,Proxyless Mesh是一种对广大中小企业更合适的技术方案,其不仅不会有额外Sidecar代理所带来的较大性能损耗,而且更重要的是对企业来说,其落地成本很低! 要通过Mesh化方案解决微服务治理需求,一个能给应用动态下发规则的控制面不可或缺,社区本着不重复造轮子,拥抱业界主流解决方案的原则,通过支持xDS协议不仅为用户提供通过主流的Istio控制面来对Spring Cloud Alibaba应用进行服务治理以外,用户也可以使用阿里巴巴开源的OpenSergo微服务治理控制面所提供的差异化治理能力进行应用治理。相关提供Mesh技术方案社区在最近发布的 2.2.10-RC版本[6]中进行了提供。做了提供微服治理能力的第一个版本,社区当前已经部分兼容了Istio VirtualService & DestinationRule的标签路由和服务鉴权能力,用户可以通过Istio控制面给应用下发相关规则,对应用进行流量治理。 

image.png

准备工作

Proxyless Mesh的方案首先需要准备好一个能给应用动态下发规则的控制面,本次Spring Cloud Alibaba 2.2.10-RC1 版本支持了2种当前市面上的主流控制面来更好的满足各类用户诉求:

1. Istio控制面

为了使用Istio控制面下发治理规则,首先需要在K8s环境中安装Istio控制面,您可以使用Spring Cloud Alibaba社区提供的测试用的Istio环境,也可以选择自己尝试安装一套Istio控制面,安装Istio控制面的流程如下:

  1. 安装K8s环境,请参考K8s的安装工具小节
  2. 在K8s上安装并启用Istio,请参考Istio官方文档的安装小节
2. OpenSergo控制面

OpenSergo 是开放通用的,覆盖微服务及上下游关联组件的微服务治理项目。OpenSergo 从微服务的角度出发,涵盖流量治理、服务容错、服务元信息治理、安全治理等关键治理领域,提供一系列的治理能力与标准、生态适配与最佳实践,支持 Java, Go, Rust 等多语言生态。 OpenSergo 控制平面 (Control Plane) 作为 OpenSergo CRD 的统一管控组件,承载服务治理配置转换与下发的职责。

  1. 安装K8s环境,请参考K8s的安装工具小节
  2. 在K8s上安装并启用 OpenSergo Control Plane,请参考 OpenSergo 官方提供的 OpenSergo 控制面安装文档

标签路由

应用背景

在现在的微服务架构中,服务的数量十分庞大,为了更好的管理这些微服务应用,可能需要给这些应用打上标签,并且将一个或多个服务的提供者划分到同一个分组,从而约束流量只在指定分组中流转,实现流量隔离的目的。标签路由可以作为蓝绿发布、灰度发布等场景的能力基础,它可以被应用在以下场景中:

  • 多版本开发测试

多个版本并行开发时,需要为每个版本准备一套开发环境。如果版本较多,开发环境成本会非常大。流量隔离方案可以在多版本开发测试时大幅度降低资源成本。使用基于标签路由的全链路流量隔离机制,可以将特定的流量路由到指定的开发环境。例如在开发环境1中只修改应用B和应用D,则为这两个应用在开发环境1中的版本创建Tag1标签,并配置对应的路由规则。入口应用A调用B时,会判断流量是否满足路由规则。如果满足,路由到开发环境1中应用B的V1.1版本;如果不满足,路由到基线环境中的应用B的V1版本。应用C调用D的时候同样根据流量决定路由到D的V1版本或V1.1版本。 

image.png

  • 应用流量隔离

如果一个应用有多个版本在线上同时运行,部署在不同环境中,如日常环境和特殊环境,则可以使用标签路由对不同环境中的不同版本进行流量隔离,将秒杀订单流量或不同渠道订单流量路由到特殊环境,将正常的流量路由到日常环境。即使特殊环境异常,本应进入特殊环境的流量也不会进入日常环境,不影响日常环境的使用。 

image.png

  • A/B Testing

线上有多个应用版本同时运行,期望对不同版本的应用进行A/B Testing,则可以使用标签路由的全链路流量控制将地域A(如杭州)的客户流量路由到V1版本,地域B(如上海)的客户流量路由到V1.1版本,对不同版本进行验证,从而降低新产品或新特性的发布风险,为产品创新提供保障。 

image.png

 目前,Spring Cloud Alibaba Mesh提供的标签路由能力支持根据请求路径、请求头和HTTP请求参数等请求元信息对请求做标签路由,让应用发出的请求根据Istio控制面下发的规则发送至指定版本的上游服务。

使用方式
1. 导入依赖并配置应用

首先,修改pom.xml 文件,导入Spring Cloud Alibaba 2.2.10-RC1版本下的标签路由以及Istio资源转换模块的相关依赖(推荐通过云原生应用脚手架 start.aliyun.com 进行项目构建试用):

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-alibaba-dependencies</artifactId>
            <version>2.2.10-RC1</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

<dependencies>
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-governance-routing</artifactId>
    </dependency>
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-xds-adapter</artifactId>
    </dependency>
</dependencies>

application.yml配置文件给消费者配置Istio控制面以及Nacos注册中心的相关信息:

server:
  port: 18084
spring:
  main:
    allow-bean-definition-overriding: true
  application:
    name: service-consumer
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
        fail-fast: true
        username: nacos
        password: nacos
    istio:
      config:
        # 是否开启Istio配置转换
        enabled: ${ISTIO_CONFIG_ENABLE:true}
        # Istiod IP
        host: ${ISTIOD_ADDR:127.0.0.1}
        # Istiod 端口
        port: ${ISTIOD_PORT:15010}
        # 轮询Istio线程池大小
        polling-pool-size: ${POLLING_POOL_SIZE:10}
        # 轮询Istio时间间隔
        polling-time: ${POLLING_TIME:10}
        # Istiod鉴权token(访问Istiod 15012端口时可用)
        istiod-token: ${ISTIOD_TOKEN:}
        # 是否打印xds相关日志
                log-xds: ${LOG_XDS:true}

application.yml配置文件给生产者应用配置元信息:

# 第一个生产者,版本为v1
spring.cloud.nacos.discovery.metadata.version=v1
# 第二个生产者,版本为v2
spring.cloud.nacos.discovery.metadata.version=v2

如果是需要对接 OpenSergo 控制面的,则需要给消费者应用加上 spring-cloud-starter-alibaba-governance-routing 跟 spring-cloud-starter-opensergo-adapter相关依赖,并配置OpenSergo所需的配置即可。

2. 运行应用程序

启动两个生产者应用和一个消费者应用,并将这些应用都注册到本地的Nacos注册中心里,消费者在调用生产者时,会根据控制面下发的标签路由规则来调用不同的生产者实例。启动消费者和两个生产者后,可以在Nacos注册中心里看到这几个已注册的服务: 

image.png

 控制台上会打印出以下信息,说明此应用正在监听Istio控制面下发的配置: 

image.png

3. 通过Istio控制面下发标签路由规则

通过Istio控制面下发标签路由规则,首先下发DestinationRule规则:

kubectl apply -f - << EOF
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: my-destination-rule
spec:
  host: sca-virtual-service
  subsets:
  - name: v1
    labels:
      version: v1
  - name: v2
    labels:
      version: v2
EOF

此规则将后端服务拆分为两个版本,label为v1的pod被分到v1版本,label为v2的pod被分到v2版本 之后,下发VirtualService规则:

kubectl apply -f - << EOF
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: sca-virtual-service
spec:
  hosts:
    - service-provider
  http:
  - match:
    - headers:
        tag:
          exact: gray
      uri:
        exact: /istio-label-routing

    route:
    - destination:
        host: service-provider
        subset: v2
  - route:
    - destination:
        host: service-provider
        subset: v1
EOF

这条VirtualService指定了一条最简单的标签路由规则,将请求头tag为gray,请求路径为/istio-label-routing的HTTP请求路由到v2版本,其余的流量都路由到v1版本 发送若干条不带请求头的HTTP请求至IstioConsumerApplication

while true;
    do curl localhost:18084/istio-label-routing;
    sleep 0.1;
    echo "";
done;

因为请求头不为gray,所以请求将会被路由到v1版本,返回如下 

image.png

 之后发送一条请求头tag为gray,且请求路径为/istio-label-routing的HTTP请求

while true;
    do curl localhost:18084/istio-label-routing -H "tag: gray";
    sleep 0.1;
    echo "";
done;

因为满足路由规则,所以请求会被路由至v2版本 

image.png

4. 通过 OpenSergo 控制面下发标签路由规则

通过OpenSergo控制面也定义了特定的流量路由规则TrafficRouter,如下是一个OpenSergo控制面对应的流量路由规则:

kubectl apply -f - << EOF
apiVersion: traffic.opensergo.io/v1alpha1
kind: TrafficRouter
metadata:
  name: service-provider
  namespace: default
  labels:
    app: service-provider
spec:
  hosts:
    - service-provider
  http:
    - match:
        - headers:
            tag:
              exact: v2
      route:
        - destination:
            host: service-provider
            subset: v2
            fallback:
              host: service-provider
              subset: v1
    - route:
        - destination:
            host: service-provider
            subset: v1
EOF

这条TrafficRouter指定了一条最简单的流量路由规则,将请求头tag为v2的HTTP请求路由到v2版本,其余的流量都路由到v1版本。如果 v2 版本没有对应的节点,则将流量fallback至v1版本。 停止v2版本的ProviderApplication后,继续发送一条请求头 tag 为 v2 的HTTP请求

curl --location --request GET '127.0.0.1:18083/router-test' --header 'tag: v2'

因为v2版本没有服务提供者,因此流量被fallback至 v1 版本。

Route in 30.221.132.228: 18081,version is v1.

上述详细示例代码可以在社区Github上示例代码中获取。

服务鉴权

正常生产场景,微服务应用都具有安全要求,不会让任意的服务都可直接调用。因此需要对调用该应用的上游应用进行服务鉴权,保证应用自身的安全。 未配置服务鉴权Consumer 1、2、3和Provider在同一个命名空间内,Consumer 1、2、3默认可以调用Provider的所有Path(Path 1、2和3)。 

image.png

 配置服务鉴权规则后,应用间合法的调用关系如下图所示: 

image.png

 设置所有Path的鉴权可以对Provider的所有Path设置鉴权规则,例如Provider所有Path的鉴权规则设置为拒绝Consumer 1调用(黑名单),则允许Consumer 2、3调用(白名单)。 设置指定Path的鉴权在设置所有Path的鉴权基础上,还可以设置Consumer指定Path的鉴权规则,例如按所有Path的鉴权方式,Consumer 2、3可以访问Provider的所有Path,但Provider的Path2涉及一些核心业务或数据,不希望Consumer 2调用,可以将Path 2对Consumer 2的鉴权方式设置为黑名单(拒绝调用),则Consumer 2只能访问Provider的Path 1和Path 3。 目前,Spring Cloud Alibaba Mesh支持了Istio的大部分鉴权规则,支持了除了需要mTLS支持以外的鉴权规则,支持了Istio的所有字符串匹配模式以及规则的逻辑运算。 

image.png

使用方式
1. 导入依赖并配置应用

修改pom.xml文件,引入Istio资源转换以及Spring Cloud Alibaba鉴权模块(推荐通过云原生应用脚手架 start.aliyun.com 进行项目构建试用):

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-alibaba-dependencies</artifactId>
            <version>2.2.10-RC1</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

<dependencies>
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-governance-auth</artifactId>
    </dependency>
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-xds-adapter</artifactId>
    </dependency>
</dependencies>

在应用的 application.yml 配置文件中配置Istio相关元数据:

server:
  port: ${SERVER_PORT:80}
spring:
  cloud:
    governance:
      auth:
        # 是否开启鉴权
        enabled: ${ISTIO_AUTH_ENABLE:true}
    istio:
      config:
        # 是否开启Istio配置转换
        enabled: ${ISTIO_CONFIG_ENABLE:true}
        # Istiod IP
        host: ${ISTIOD_ADDR:127.0.0.1}
        # Istiod 端口
        port: ${ISTIOD_PORT:15010}
        # 轮询Istio线程池大小
        polling-pool-size: ${POLLING_POOL_SIZE:10}
        # 轮询Istio时间间隔
        polling-time: ${POLLING_TIMEOUT:10}
        # Istiod鉴权token(访问Istiod 15012端口时可用)
        istiod-token: ${ISTIOD_TOKEN:}
        # 是否打印xds相关日志
                log-xds: ${LOG_XDS:true}

2. 运行应用程序

在导入好以上的依赖并且在application.yml文件中配置了相关配置之后,可以将此应用程序运行起来,启动一个简单的Spring Boot应用,其中只含有一个简单的接口,此接口将会把本次请求的详细信息返回给客户端。 启动应用后,控制台上会打印出以下信息,说明此应用正在监听Istio控制面下发的配置: 

image.png

3. 通过Istio控制面下发鉴权配置

在使用如下命令通过Istio下发一条鉴权规则至demo应用,这条规则的限制了访问该应用的请求header:

kubectl apply -f - << EOF
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: http-headers-allow
  namespace: ${namespace_name}
spec:
  selector:
    matchLabels:
      app: ${app_name}
  action: ALLOW
  rules:
  - when:
    - key: request.headers[User-Agent]
      values: ["PostmanRuntime/*"]
EOF

之后发送一个带User-Agent头部的HTTP请求来验证规则是否生效:

while true;
    do curl localhost/auth -H "User-Agent: PostmanRuntime/7.29.2";
    sleep 0.1;
    echo "";
done;

由于此请求由于携带了正确的HTTP Header信息,将会返回: 

image.png

 之后发送一个不带User-Agent头部的HTTP请求来验证规则是否生效:

while true;
    do curl localhost/auth;
    sleep 0.1;
    echo "";
done;

由于此请求没有携带正确的HTTP Header信息,将会返回: 

image.png

 上述详细示例代码可以在社区Github上示例代码中获取。

2022.0.0.0-RC1 版本发布啦

2022年12月30日 · 阅读需 32 分钟

铖朴

基于GraalVM对Java应用进行运行前的静态编译优化,能显著地解决Java应用长期被诟病的冷启动耗时长、运行时占用内存大的问题,实现降本增效!本文将介绍如何使用Spring Cloud Alibaba 2022.0.0.0-RC1版本,以及其如何使用GraalVM对Spring Cloud Alibaba应用进行静态编译优化。

新版本预览

本次发布的 Spring Cloud Alibaba 2022.0.0.0-RC1 版本,是基于社区 2022.x 主干分支进行构建发布第一个Release Candidate(RC)版本,考虑到本次版本升级属于重大版本变更,因此暂时先以 RC 版本形式发布,当前大家可以先试用起来,待后续时机成熟社区会尽快发布正式版本。新版本预览内容如下:

2022.0.0.0-RC1 版本

是在 Spring Cloud 2022.0.0、Spring Boot 3.0 的基础上,对生态中原有的包括注册配置中心、分布式消息等在内的众多组件进行了适配,属于一个大变更的版本。本次发布的 Spring Cloud Alibaba 2022.0.0.0-RC1 版本对以下组件版本进行了适配:

  • Seata:客户端适配版本为 1.6.1 版本[1],该版本相比于之前的1.5.x版本,已经支持MySQL updatejoin,PostgreSQL & Oracle多主键支持,InsertOnDuplicateUpdate 做了大量优化,支持多注册中心等及核心功能大量优化,该版本客户端已完成JDK 17的支持。
  • RocketMQ:客户端适配版本为 4.9.4版本[2],该版本提供了轻量级消息队列和为延迟消息提供异步发送功能等在内的诸多特性。
  • Sentinel:客户端适配版本为 1.8.6 版本[3],该版本调整了Sentinel规则类中的属性,并将javax. 包下的相关基础类都替换为了jakarta.包路径下的,以兼容 JDK 17 。
  • Nacos: 客户端适配版本为 2.2.1-RC,该版本是Nacos社区在最新发布的 2.2.0 版本基础上为适配最新GraalVM构建原生镜像而推出的最新版本客户端,该版本可直接搭配Nacos 2.x系列Nacos Server使用,不仅能体验 2.2.0 最新带来的数据源、连接限流等插件能力,而且可直接构建GraalVM原生镜像,启动速度和运行时内存得到大幅降低。

除了组件升级,另外也修复了一些之前版本所存在的问题,进一步提升了Spring Cloud Alibaba 使用的稳定性与健壮性。更多内容可参见该版本相关发版公告[4]

版本解读

为什么是JDK 17?

很多人,听到Spring Boot 3.0默认所需的JDK最低版本为17会感到非常诧异!对很多JDK 8用户来说Spring官方的选择一定是不明智的。真的是这样的吗?对于这个问题,我们认为主要基于2个原因:Oracle官方对JDK支持政策和先进性。 Oracle当前对所有发布的JDK版本分为 Long-Term-Support (LTS) releases和相对non-TLS releases,TLS版本的JDK 作为Oracle官方长期支持的版本,会在未来的很长一段时间内,官方都会对该版本进行持续的维护和更新。而non-TLS版本的JDK仅仅是作为过度版本,只要下一个LTS版本出现以后,官方就不会对其进行维护了,因此也是不适合作为外部用户生产长期使用的。 

image.png

 因此在Spring Boot 3.0于今年年初的第一个Milestone版本发布之时,可选的JDK版本从上图来看,就只有JDK 7、8、11和17。为什么是17而不是其之前的版本呢?这个就要结合Oracle官方的JDK支持政策来理解了。Oracle官方一般将所发布的JDK后续的支持策略分为以下3种:

  • Premier Support: 其可以理解为Oracle提供的标准支持类型,其最新政策下的支持时间周期为5年,5年内Oracle官方会对该版本JDK提供持续免费的更新与升级服务。
  • Extended Support: 作为标准支持后的延续支持类型,其最新政策下的支持时间周期为3年,3年内Oracle的用户可以通过支付一定的支持服务费用购买Oracle对该版本JDK所提供的更新支持服务。
  • Sustaining Support: 其是Oracle官方在延续支持类型后的一种支持服务,当然其也是要收费的,其目前暂时还没有明确的截止时间。

根据上述Oracle官方对当前JDK所提供的支持服务形式以及JDK版本本身的先进性来看,JDK 7,8已经截止了Premier Support支持服务,11相关的Premier Support也快到期了。JDK 17作为目前最新的LTS版本,本身无论是在语法还是运行性能方面都在之前版本上做了一定优化,本身具有比较大的优势。因此,选择JDK 17作为最新的Spring Boot 3.0的默认JDK版本也就顺理成章了!

Spring Cloud 2022.0.0 带来了什么?

Spring Cloud 在2022年的最后一个月迎来了2022.x系列的第一个正式版本 2022.0.0,有些用户这个时候可能会有一种快结束了才刚刚开始的感觉!其实不然,Spring 在2022年的第一个月就推出了2022.0.0-M1,作为第一个Milestone版本。 

image.png

 在接下来一年里,其陆续发布了5个Milestone和3个Release Candicate(RC)版本以后,才正式推出正式的General Available(GA)版本。由此可见,Spring 官方做事情还是非常靠谱和有耐心的,值得尊敬! Spring Cloud 作为当前业界应用最为广泛的微服务框架,其定义了一套包含:分布式注册配置中心、分布式消息、限流降级、远程过程调用、负载均衡等在内的较为完整的一套微服务解决方案标准。在2022.0.0中,主要做了如下部分内容的调整:

  • Spring Cloud Common模块中由于 AsyncRestTemplate 已在 Spring Framework 6 中删除,因此删除了对应的 LoadBalancer 自动配置,老代码中有涉及相关内容并考虑升级的用户需要注意。
  • Spring Cloud Common模块中 LoadBalancer 的 ResponseData 现在已经调整为使用 Spring中 org.springframework.http.HttpStatusCode,跟Spring其他模块保持了一致性。
  • Spring Cloud Common模块中第一次正式从源码中移除 @SpringCloudApplication注解,@EnableDiscoveryClient、@EnableCircuitBreaker 注解也都不再默认需要添加内容等。
  • Spring Cloud Stream 模块正式移除了对@StreamListener、@Input等注解的支持,当前只能使用函数式编程方式进行消息的订阅与发送。
  • Spring Cloud OpenFeign 中 feign.autoconfiguration.jackson.enabled 属性默认改为 true。

更多具体信息可以参考 Spring Cloud 2022.0.0 版本说明

Spring Boot 3.0 意味着什么?

Spring Boot 3.0距离上次大版本2.0发布以来,已经过去4年半,该版本社区历时12个月共提交超过5700个commit。其在Spring 6.0和 Spring Native 的基础上主要做了4大主要的调整:

  • 调整JDK基线到17版本,兼容JDK19;
  • 将Java EE依赖迁移到Jakarta EE;
  • 支持应用使用GraalVM技术生成原生镜像,取代了之前实验性质的Spring Native项目,让Spring Boot应用直接迈向GraalVM;
  • 使用Micrometer和Micrometer Tracing提升了应用可观测性。

其中,前2点前文也有说明,不再赘述。接下来将就其中的GraalVM和可观测方面进行介绍。

迈向GraalVM

Spring Boot 3.0本次带来最大的改动就是GraalVM原生镜像的支持,也是官方文档中强调的他们花费时间精力比较多的部分。 GraalVM技术作为JRE的替代方案,其通过预先编译(Ahead Of Time,AOT)等技术对Java应用进行预先编译,让Spring在运行应用时掌握更多应用有关的信息,让整个应用启动速度更快。另外,通过编译工具在编译过程中通过消除一些不必要的内容可以让最终的应用更小,占用内存更低。对于一些对启动速度要求非常高的场景,比如Serverless、FaaS场景非常友好! 提到GraalVM技术,其最早来自于 Spring 团队于2019年发起的 Spring Native 项目。它作为一个实验性质的项目,在过去几年通过与 Spring Boot 3.0 和 Spring Framework 6.0 之前的项目进行整合使用,据 Josh Long 在最近的相关采访透露,该实验项目已经验证了 Spring Boot 2.x 和 Spring Framework 5.x 的各项功能。本次 Spring Boot 3.0 直接将其正式从 Spring Native 迁入到 Spring Boot 中来,也预示着该项技术开始逐渐走向成熟,Spring生态开始迈入 GraalVM 阶段! 跟 JVM 编译部署方式相比,GraalVM 具有以下特点:

  • 在应用构建阶段,从主入口点就开始进行应用程序的静态分析。
  • 创建本机镜像时,通过代码分析,会将无法访问的代码删除,并且不会成为可执行文件的一部分,从而可在一定程度上压缩程序包大小。
  • GraalVM 无法直接感知代码的动态元素,因此对于存在反射、序列化和动态代理的应用程序,需要提前提供相关hint配置文件,帮助解析应用程序,相关操作过程可参考官方文档
  • 应用程序类路径在构建时是固定的,不能更改。
  • 没有惰性类加载,可执行文件中的所有内容都将在启动时加载到内存中。
  • 支持的 Java 应用程序在某些方面存在一些限制,因此目前并不能保证之前的 Java 应用都可直接使用GraalVM技术进行应用构建,有一定概率会存在不兼容的异常情况。

本次发布的 Spring Cloud Alibaba 2022.0.0.0-RC1 版本所包含的部分中间件客户端已完成了构建 GraalVM 原生应用的适配,以下是社区对目前所支持的服务注册与发现、分布式事务模块相关示例应用在升级为 Spring Boot 3.0 以后,使用GraalVM构建原生应用镜像做的在启动速度和运行时占用内容相关的测试(Sentinel和RocketMQ目前还在适配中,以下测试过程在MacOS 11.4,2.6 GHz 6-Core Intel Core i7处理器,16G内存环境下分别模拟5次取平均值测得): 

image.png

 从上述对比可发现,最新支持 Spring Boot 3.0 基于 GraalVM 的 Spring Cloud Alibaba 应用会在启动速度、运行时内存占用和应用包大小方面得到大幅度降低,例如,其中服务注册消费应用启动速度提升了近10倍,运行时内存占用比原来降低了近乎2/3,效果非常明显。这给云原生时代,托管在云上的应用带来了显著优势,让其可以更快的进行弹性扩缩容以及降低企业整体用云成本!

可观测能力

微服务应用带来了系统的解耦,把一个应用拆分成若干个模块来进行部署,这样在提高系统的可扩展性的同时,一个请求的处理可能会经过多个单独部署的模块,因此,让问题排查显著提升。可观测技术通过定义 logging、metrics 和 traces 3个维度指标数据的采集和处理,让系统运维人员可以方便地掌握系统运行状态,及时排查解决问题。 Spring Boot 3.0中另外一项重大特性,就是其在可观测领域的增强。在 Spring Boot 3.0 中,支持了可观测事实标准 Micrometer 1.10 中引入的新 API。例如,Spring Boot 3.0 可自动装配一个 ObservationRegistry 实例对象,为用户提供一个同时适用于 metrics 和 traces 的API接口。另外,3.0 也为用户提供了自动配置 Micrometer Tracing 功能,具体包括支持第三方的相关可观测工具,如:Brave、OpenTelemetry、Zipkin 以及 Wavefront。让Spring Boot 应用能非常方便的集成各种主流的可观测工具。更多有关可观测的内容可参见相关文档说明。 除了上述介绍的主要特性以外, Spring Boot 3.0 还解决很多之前存在的bug,更多具体内容可参见 Spring Boot 3.0 版本说明

升级步骤

升级操作

如果对于一个 Spring Boot 3.0项目需要使用Spring Cloud Alibaba 2022.0.0.0-RC1 版本,请在项目中添加如下 Management 依赖:

<dependencyManagement>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-dependencies</artifactId>
        <version>2022.0.0</version>
        <type>pom</type>
        <scope>import</scope>
    </dependency>
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-alibaba-dependencies</artifactId>
        <version>2022.0.0.0-RC1</version>
        <type>pom</type>
        <scope>import</scope>
    </dependency>
</dependencyManagement>

注意除了调整上述JDK版本,还需要将JDK版本升级到17。

兼容Spring Boot 3.0 & Spring Cloud 2022.0.0

Spring Cloud Alibaba项目作为阿里巴巴中间件微服务领域的一站式解决方案,在本次发布的 2022.0.0.0-RC1 版本适配过程中,由于Spring Boot & JDK的较大变化给项目适配造成了除功能升级以外的大量其他兼容性工作。如果是直接构建新项目,可以参考最新的 Spring Boot 3.0 项目构建过程进行操作即可,以下步骤可以省略,如果是老的应用希望升级到 JDK17 & Spring Boot 3.0 可能需要做如下一些兼容处理: Java EE依赖迁移到Jakarta EE 由于 Oracle 跟 Eclipse 基金会在 Java EE商标上所存在的纠纷,从 Jakarta EE 9 开始, javax. 包下的基础类都被迁移到了jakarta.。因此,对于本次升级如果在程序中使用了 javax.* 开头的导包,都需要将其进行修改。 以下列出了一系列工具可以帮助你完成这部分的迁移:

spring.factories 文件不再支持对 Auto-configuration 进行自动装配 从 Spring Boot 3.0 开始,META-INF/spring.factories 文件不再支持对 Auto-configuration 进行自动装配。用户可以使用 AutoConfiguration.imports 文件代替 META-INF/spring.factories 文件对原来编写在其中的自动装配类进行迁移。如果不做对应的修改,直接升级你会发现之前程序运行阶段自动注入的对象都将不存在导致运行报错。这个也是本次 Spring Cloud Alibaba 所使用的方式,如本次 Spring Cloud Alibaba 升级过程中服务注册与发现模块就通过创建如下 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 进行自动类装配:

com.alibaba.cloud.nacos.discovery.NacosDiscoveryAutoConfiguration
com.alibaba.cloud.nacos.endpoint.NacosDiscoveryEndpointAutoConfiguration
com.alibaba.cloud.nacos.registry.NacosServiceRegistryAutoConfiguration
com.alibaba.cloud.nacos.discovery.NacosDiscoveryClientConfiguration
com.alibaba.cloud.nacos.discovery.reactive.NacosReactiveDiscoveryClientConfiguration
com.alibaba.cloud.nacos.discovery.configclient.NacosConfigServerAutoConfiguration
com.alibaba.cloud.nacos.loadbalancer.LoadBalancerNacosAutoConfiguration
com.alibaba.cloud.nacos.NacosServiceAutoConfiguration
com.alibaba.cloud.nacos.utils.UtilIPv6AutoConfiguration

不在允许 URI 尾部斜杠匹配 在Spring 6以前,请求路径使用"/hello"和"/hello/"都可以进入如下到hello()方法,但是在升级以后需要注意只有前者请求才能正常被配到到方法中,后者会抛出404找不到匹配路径异常。

@GetMapping("/hello")
String hello() {
    return "Hello World";
}

Spring Cloud Stream注解使用方式被移除 Spring Cloud Stream 作为Spring Cloud 体系内集成具有高度可扩展性的分布式消息解决标准实现,Spring Cloud Alibaba 基于其将 RocketMQ 集成进入了 Spring Cloud 生态,让用户可以不用修改一行业务代码仅调整依赖和配置即可进行消息中间件从 RabbitMQ、Kafka 等迁移到 RocketMQ。在Spring Cloud 2022.0.0 最新版本所对应的 Spring Cloud Stream 4.0中移除之前的注解方式在客户端处理消息能力,目前仅支持函数式方式。 因此,像之前的@StreamListener和@Input等注解在升级以后都不再能直接使用。目前,Spring Cloud Alibaba 中RocketMQ相关模块示例代码已调整为函数方式,函数式方式让代码编写过程变得更加简洁,以下为使用函数式方式完成广播消息的消费代码,更多示例可参考相关示例模块

@SpringBootApplication
public class RocketMQBroadcastConsumer2Application {
    private static final Logger log = LoggerFactory
            .getLogger(RocketMQBroadcastConsumer2Application.class);

    public static void main(String[] args) {
        SpringApplication.run(RocketMQBroadcastConsumer2Application.class, args);
    }

    @Bean
    public Consumer<Message<SimpleMsg>> consumer() {
        return msg -> {
            log.info(Thread.currentThread().getName() + " Consumer2 Receive New Messages: " + msg.getPayload().getMsg());
        };
    }
}

Spring Cloud Common模块正式移除@SpringCloudApplication注解 在Spring Cloud 2022.0.0所对应的Spring Cloud Common 4.0.0中正式移除@SpringCloudApplication注解。该注解的推出是为了包含@SpringBootApplication、@EnableDiscoveryClient、@EnableCircuitBreaker这3个Spring Cloud应用都必要的注解分别提供应用依赖管理,服务注册和断路器包含。在后来通过引入相关的依赖就可默认提供服务注册以及断路器能力,因此这两个注解也不再必须,通过配置spring.cloud.discovery.enabled=false 可直接关闭默认注册行为,相关注册方式这样操作更加灵活,这次在新版本中@SpringCloudApplication正式被移除,升级过程中老版本需要注意进行相应的调整。

上述内容是 Spring Cloud Alibaba 适配 JDK 17 & Spring 6 & Spring Boot 3.0 & Spring Cloud 2022.0.0 过程中框架层面比较直接的一些变动。其他的一些相关新版本所带来的更多特性和改变可详细参考相关文档 Spring 6Spring Boot 3.0Spring Cloud 2022.0.0。另外在适配支持 GraalVM 技术构建Spring Cloud Alibaba应用原生镜像方式,社区了也联合Nacos、Sentinel、Seata等社区共同做了一些改造和兼容。具体在新特性使用介绍中会有提及。

新特性以及使用方式

使用 GraalVM 技术构建应用

本次适配 Spring Boot 3.0 的 Spring Cloud Alibaba 所支持的所有组件中,Nacos 2.2.1-RC 已经支持 GraalVM 技术构建应用。接下来,将介绍一下相关组件使用 GraalVM 技术进行应用编译与运行测试:

项目构建

按照一般的 Spring Cloud Alibaba 应用构建方式进行项目构建即可,以下为相关必须添加的依赖内容:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>3.0.0</version>
    <relativePath/> <!-- lookup parent from repository -->
</parent>
<dependencies>
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-commons</artifactId>
</dependency>
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>2022.0.0</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-alibaba-dependencies</artifactId>
            <version>2022.0.0.0-RC1</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

以上为本次通过 Spring Cloud Alibaba 使用 Nacos 进行服务注册所需要的必要依赖,其他依赖请根据自身需求进行调整,请注意,使用 GraalVM spring-boot-starter-parent 父模块是非常关键的,其声明一个 native profile,其中包含了创建、运行 GraalVM 原生映像的必要信息。 构建 Spring Boot 原生镜像应用主要有两种方式:

  1. 使用 Spring Boot 对 Cloud Native Buildpacks 的支持来生成包含本机可执行文件的轻量级容器。
  2. 使用 GraalVM Native Build Tools 生成本机可执行文件。

由于第一种方式使用过程中对本地环境有一定的要求,如需使用可参考 Spring Boot 3.0 相关用户文档。本文接下来演示使用第二种方式进行 GraalVM 应用构建。

环境准备

要使用 Native Build Tools 构建原生镜像,需要在首先在机器上安装 GraalVM 发行版。 您可以在 Liberica Native Image Kit 页面上手动下载它,也可以使用像 SDKMAN! 这样的下载管理器。本文演示环境为MacOS,如果是 Windows 可参考相应文档进行操作。执行以下命令安装 GraalVM 环境:

sdk install java 22.3.r17-nik
sdk use java 22.3.r17-nik

通过检查 java -version 的输出来验证是否配置了正确的版本:

$ java -version
openjdk version "17.0.5" 2022-10-18 LTS
OpenJDK Runtime Environment GraalVM 22.3.0 (build 17.0.5+8-LTS)
OpenJDK 64-Bit Server VM GraalVM 22.3.0 (build 17.0.5+8-LTS, mixed mode)

资源文件准备

在构建应用之前,需要在应用 pom.xml 文件中添加如下相关构建工具插件。

<build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <jvmArguments>
                        -agentlib:native-image-agent=config-merge-dir=src/main/resources/META-INF/native-image/
                    </jvmArguments>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.graalvm.buildtools</groupId>
                <artifactId>native-maven-plugin</artifactId>
            </plugin>
        </plugins>
</build>

添加完上述插件后,通过以下命令生成应用中反射、序列化和动态代理所需的hint配置文件。

mvn -Pnative spring-boot:run

运行成功以后,停止应用以后,可发现项目resource/META-INF/native-image目录下会生成以下一些hint文件:

  • resource-config.json:应用中资源hint文件
  • reflect-config.json:应用中反射定义hint文件
  • serialization-config.json:应用中序列化内容hint文件
  • proxy-config.json:应用中Java代理相关内容hint文件
  • jni-config.json:应用中Java Native Interface(JNI)内容hint文件

由于GraalVM 无法直接感知代码的动态元素,因此需要这些hint原生帮助生成的原生应用镜像进行运行。 注意:执行以上命令启动应用进行应用属性解析的过程是动态的,在该阶段需要完整测试一遍应用的所有功能才能确保完整生成应用运行过程中的所有必须动态属性,否则会出现生成的配置文件中内容不完整造成运行阶段报错。社区在适配 Nacos 服务注册与消费测试过程中就因为测试不充分导致过类似错误。

编译原生应用

上述步骤一切就绪以后,通过以下命令进行原生应用构建:

mvn -Pnative native:compile 

原生应用构建阶段会比较耗时,根据本地环境资源情况会耗费几分钟时间,以上过程都顺利执行以后,出现如下结果则表示构建成功:

Finished generating 'nacos-discovery-provider-example' in 2m 36s.
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  02:51 min
[INFO] Finished at: 2022-12-21T13:43:22+08:00
[INFO] ------------------------------------------------------------------------

接下来我们通过 target/nacos-discovery-provider-example 启动应用,如下图显示结果可见,启动速度非常迅速,仅 0.3s 多就完成了应用启动和服务注册:

...... : [REGISTER-SERVICE] public registering service DEFAULT_GROUP@@service-provider with instance: Instance{instanceId='null', ip='30.221.144.116', port=18082, weight=1.0, healthy=true, enabled=true, ephemeral=true, clusterName='DEFAULT', serviceName='null', metadata={preserved.register.source=SPRING_CLOUD}}
...... : null No credential found
...... : nacos registry, DEFAULT_GROUP service-provider 30.221.144.116:18082 register finished
...... : Started ProviderApplication in 0.328 seconds (process running for 0.339)

另外,我们可以通过 vmmap pid | grep Physical 命令查看运行过程中的内存占用情况: 

image.png

 以上过程则为一个 Spring Cloud Alibaba 应用使用 GraalVM技术构建应用并完成向Nacos注册的整个过程,相关示例代码可以参考 SCA Nacos Example。特别需要注意的是,OpenFeign 使用GraalVM 过程中需要进行一些调整,比如添加 spring.cloud.refresh.enabled=false 配置,具体设置过程可参考相关 OpenFeign说明文档

升级建议与注意事项

  1. 此次支持Spring Boot 3.0 的 Spring Cloud Alibaba 版本相关内容改动整体还是比较大的,老项目特别是 Spring Boot 2.4以下的直接迁移到存在一定的兼容性风险,建议相关迁移操作先进行充分验证和测试以后再进行。
  2. 此次引入 Spring Boot 3.0 中的 GraalVM 技术在应用启动速度、运行时内存占用率和包大小方面相比于传统的 JVM 虚拟机模式有非常显著的优势,在一定程度上解决Java语言一直被诟病的启动速度慢、构建包过大等问题。但相关技术目前也还在发展中,段时间内还有一定问题需要处理,比如本次发布的 Spring Cloud Alibaba 版本中除了服务注册与发现和分布式事务模块实现了初步的 GraalVM 支持,其他模块或多或少存在一些问题还无法直接使用 GraalVM,这块社区也在持续努力中。

社区未来规划

目前,本次发布的 Spring Cloud Alibaba 版本初步实现了对 GraalVM 支持,Sentinel/Seata/RocketMQ 等模块也正在火热支持中,社区也会在后续完成兼容适配以后进行发布,这块也是未来 2022.x 分支的短期工作重心!大家目前可以先通过社区 Examples 模块完成新版本的功能体验,云原生应用脚手架对 Spring Cloud Alibaba 的 2022.0.0.0-RC1 版本的支持也会在近期支持上线,届时大家可以通过 start.aliyun.com 更加便捷的构建新应用,云原生应用脚手架是一款基于 Spring Initializr 项目基础之上,支持多种工程架构、提供代码示例片段、组件更丰富、生态更开放的一款脚手架。其致力于在当下云原生时代,为广大开发者提供更简单、更高效的项目构建体验。目前该项目已经开源,Github 地址是 GitHub - alibaba/cloud-native-app-initializer: Cloud Native App Initializer is committed to providing developers with a simpler and more efficient project construction experience in the current cloud-native era.。 另外在未来,Spring Cloud Alibaba社区的工作重心会投入到构建Spring Cloud生态的微服务治理能力上。当前社区已经基于 Istio VirtualService 和 DestinationRule 流量以及安全规范实现了标签路由和服务鉴权等能力,在未来用户仅需通过编写 CRD 规则通过 Istio 控制面进行解析和下发到系统中的 Spring Cloud Alibaba 应用。便可轻松具备原生微服务治理能力。欢迎感兴趣的同学扫描下方钉钉二维码加入社区交流群,一起参与社区未来建设! 

image.png

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值