快速构建服务发现的高可用能力的实践介绍

简介: 本文是阿里云微服务引擎MSE在服务发现高可用的最佳实践介绍。


1. 背景

本文是阿里云微服务引擎MSE在服务发现高可用的最佳实践介绍。演示的应用架构是由后端的微服务应用实例(Spring Cloud)构成。具体的后端调用链路有Spring Cloud Consumer调用Spring Cloud Provider,这些应用中的服务之间通过Nacos注册中心实现服务注册与发现。

2. 动手实践

2.1 前提条件

2.2 准备工作

开启MSE微服务治理

  1. 开通微服务治理专业版:

  1. 单击开通MSE微服务治理

  2. 微服务治理版本选择专业版,选中服务协议,然后单击立即开通。关于微服务治理的计费详情,请参见价格说明

  1. 安装MSE微服务治理组件:

  1. 容器服务控制台左侧导航栏中,选择市场 > 应用目录

  2. 应用目录页面搜索框中输入ack-mse-pilot,单击搜索图标,然后单击组件。

  3. 详情页面选择开通该组件的集群,然后单击创建。安装完成后,在命名空间mse-pilotmse-pilot-ack-mse-pilot应用,表示安装成功。

  1. 为应用开启微服务治理:

  1. 登录MSE治理中心控制台

  2. 在左侧导航栏选择微服务治理中心 > K8s集群列表

  3. K8s集群列表页面搜索目标集群,单击搜索图标,然后单击目标集群操作列下方的管理

  4. 集群详情页面命名空间列表区域,单击目标命名空间操作列下方的开启微服务治理

  5. 开启微服务治理对话框中单击确认

部署 Demo 应用程序

  1. 容器服务控制台左侧导航栏中,单击集群

  2. 集群列表页面中,单击目标集群名称或者目标集群右侧操作列下的详情

  3. 在集群管理页左侧导航栏中,选择工作负载 > 无状态

  4. 无状态页面选择命名空间,然后单击使用YAML创建资源

  5. 对模板进行相关配置,完成配置后单击创建。本文示例中部署sc-consumer、sc-consumer-empty、sc-provider,使用的是开源的Nacos。

部署示例应用(springcloud)

YAML:

# 开启推空保护的 sc-consumer
apiVersion: apps/v1
kind: Deployment
metadata:
  name: sc-consumer
spec:
  replicas: 1
  selector:
    matchLabels:
      app: sc-consumer
  template:
    metadata:
      annotations:
        msePilotCreateAppName: sc-consumer
      labels:
        app: sc-consumer
    spec:
      containers:
      - env:
        - name: JAVA_HOME
          value: /usr/lib/jvm/java-1.8-openjdk/jre
        - name: spring.cloud.nacos.discovery.server-addr
          value: nacos-server:8848
        - name: profiler.micro.service.registry.empty.push.reject.enable
          value: "true"
        image: registry.cn-hangzhou.aliyuncs.com/mse-demo-hz/demo:sc-consumer-0.1
        imagePullPolicy: Always
        name: sc-consumer
        ports:
        - containerPort: 18091
        livenessProbe:
          tcpSocket:
            port: 18091
          initialDelaySeconds: 10
          periodSeconds: 30
# 无推空保护的sc-consumer-empty
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: sc-consumer-empty
spec:
  replicas: 1
  selector:
    matchLabels:
      app: sc-consumer-empty
  template:
    metadata:
      annotations:
        msePilotCreateAppName: sc-consumer-empty
      labels:
        app: sc-consumer-empty
    spec:
      containers:
      - env:
        - name: JAVA_HOME
          value: /usr/lib/jvm/java-1.8-openjdk/jre
        - name: spring.cloud.nacos.discovery.server-addr
          value: nacos-server:8848
        image: registry.cn-hangzhou.aliyuncs.com/mse-demo-hz/demo:sc-consumer-0.1
        imagePullPolicy: Always
        name: sc-consumer-empty
        ports:
        - containerPort: 18091
        livenessProbe:
          tcpSocket:
            port: 18091
          initialDelaySeconds: 10
          periodSeconds: 30
# sc-provider
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: sc-provider
spec:
  replicas: 1
  selector:
    matchLabels:
      app: sc-provider
  strategy:
  template:
    metadata:
      annotations:
        msePilotCreateAppName: sc-provider
      labels:
        app: sc-provider
    spec:
      containers:
      - env:
        - name: JAVA_HOME
          value: /usr/lib/jvm/java-1.8-openjdk/jre
        - name: spring.cloud.nacos.discovery.server-addr
          value: nacos-server:8848
        image: registry.cn-hangzhou.aliyuncs.com/mse-demo-hz/demo:sc-provider-0.3
        imagePullPolicy: Always
        name: sc-provider
        ports:
        - containerPort: 18084
        livenessProbe:
          tcpSocket:
            port: 18084
          initialDelaySeconds: 10
          periodSeconds: 30
# Nacos Server
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nacos-server
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nacos-server
  template:
    metadata:
      labels:
        app: nacos-server
    spec:
      containers:
      - env:
        - name: MODE
          value: standalone
        image: nacos/nacos-server:latest
        imagePullPolicy: Always
        name: nacos-server
      dnsPolicy: ClusterFirst
      restartPolicy: Always

# Nacos Server Service 配置
---
apiVersion: v1
kind: Service
metadata:
  name: nacos-server
spec:
  ports:
  - port: 8848
    protocol: TCP
    targetPort: 8848
  selector:
    app: nacos-server
  type: ClusterIP

我们只需在Consumer增加一个环境变量profiler.micro.service.registry.empty.push.reject.enable=true,开启注册中心的推空保护(无需升级注册中心的客户端版本,无关注册中心的实现,支持MSE 的 nacos、eureka以及自建的nacos、eureka、console)

分别给Consumer应用增加SLB用于公网访问

image.png  image.png

以下分别使用{sc-consumer-empty}代表sc-consumer-empty应用的slb的公网地址,{sc-consumer}代表sc-consumer应用的slb的公网地址

2.3 应用场景

下面通过上述准备的Demo来分别实践以下场景

架构图_4-8-1 第四章第八节第一张图.jpg

  • 编写测试脚本

vi curl.sh

while :
do
        result=`curl $1 -s`
        if [[ "$result" == *"500"* ]]; then
                echo `date +%F-%T` $result
        else
                echo `date +%F-%T` $result
        fi

        sleep 0.1
done
  • 测试,分别开两个命令行,执行如下脚本,显示如下

% sh curl.sh {sc-consumer-empty}:18091/user/rest

2022-01-19-11:58:12 Hello from [18084]10.116.0.142!

2022-01-19-11:58:12 Hello from [18084]10.116.0.142!

2022-01-19-11:58:12 Hello from [18084]10.116.0.142!

2022-01-19-11:58:13 Hello from [18084]10.116.0.142!

2022-01-19-11:58:13 Hello from [18084]10.116.0.142!

2022-01-19-11:58:13 Hello from [18084]10.116.0.142!

% sh curl.sh {sc-consumer}:18091/user/rest

2022-01-19-11:58:13 Hello from [18084]10.116.0.142!

2022-01-19-11:58:13 Hello from [18084]10.116.0.142!

2022-01-19-11:58:13 Hello from [18084]10.116.0.142!

2022-01-19-11:58:14 Hello from [18084]10.116.0.142!

2022-01-19-11:58:14 Hello from [18084]10.116.0.142!

2022-01-19-11:58:14 Hello from [18084]10.116.0.142!

并保持脚本一直在调用,观察mse控制台分别看到如下情况

image.png

image.png

  • 将coredns组件缩容至数量 0,模拟 dns 网络解析异常场景

image.png

发现实例与nacos的连接断开且服务列表为空

image.png

  • 模拟dns服务恢复,将其扩容回数量2

image.png

2.4 结果验证

在以上过程中保持持续的业务流量,我们发现 sc-consumer-empty 服务出现大量且持续的报错

2022-01-19-12:02:37 {"timestamp":"2022-01-19T04:02:37.597+0000","status":500,"error":"Internal Server Error","message":"com.netflix.client.ClientException: Load balancer does not have available server for client: mse-service-provider","path":"/user/feign"}

2022-01-19-12:02:37 {"timestamp":"2022-01-19T04:02:37.799+0000","status":500,"error":"Internal Server Error","message":"com.netflix.client.ClientException: Load balancer does not have available server for client: mse-service-provider","path":"/user/feign"}

2022-01-19-12:02:37 {"timestamp":"2022-01-19T04:02:37.993+0000","status":500,"error":"Internal Server Error","message":"com.netflix.client.ClientException: Load balancer does not have available server for client: mse-service-provider","path":"/user/feign"}

image.png

相比之下,sc-consumer 应用全流程没有任何报错

image.png

  • 只有重启了Provider,sc-consumer-empty 才恢复正常

image.png

相比之下,sc-consumer 应用全流程没有任何报错

image.png

3. 尾

保障云上业务的永远在线,是 MSE 一直在追求的目标,本文通过面向失败设计的服务发现高可用能力的分享,以及MSE的服务治理能力快速构建起服务发现高可用能力的演示,模拟了线上不可预期的服务发现相关异常发生时的影响以及我们如何预防的手段,展示了一个简单的开源微服务应用应该如何构建起服务发现高可用能力。

作者介绍
目录