Skip to content

Latest commit

 

History

History
158 lines (116 loc) · 6.11 KB

File metadata and controls

158 lines (116 loc) · 6.11 KB

微服务治理设计与使用

设计说明

微服务设计主要参考金丝雀发布应用全链路泳道灰度发布应用,通过配置的灰度策略执行灰度发布过程。框架提供阿里版本实现,在实现中定义了微服务通用依赖组合:服务注册、服务发现、web 支持和 http 客户端,在使用时会自动引入上述依赖无需手动管理。

微服务治理抽象设计如下:

@startuml
package "cloudapp-base-api" {
    interface TrafficService {
        boolean supportTrafficManagement()
        boolean currentTrafficMatchWith(String labelValue)
        String getCurrentEnvironmentLabel()
        boolean isDuringCanaryRelease()
        boolean isInstanceWarmingUp()
        ' String markCurrentTrafficWith(String labelValue)
        Scope withTrafficLabel(String labelValue);
        Map<String, String> getBaggageUserData()
        String getBaggageUserDataValue(String key)
        ' String putBaggageUserData(String key, String value)
        Scope withBaggageUserData(Map<String, String> pairs);
        String currentTraceId()
        ' Collection<?> currentHostingServiceInstance()
        String getCurrentTrafficLabel();
    }
}
@enduml
  1. 定义流量治理服务接口 TrafficService ,主要方法有:

    1. supportTrafficManagement() 检查是否支持流量治理,一般场景中流量治理能力需要服务框架结合 链路追踪(如:阿里巴巴 ARMS、Skywalking、OpenTelemetry等产品)进行支持;

    2. currentTrafficMatchWith(String labelValue) 检查当前请求是否带有流量标签,流量标签通常是一个字符串值,由上游应用程序根据流量规则(如:Http Header、Http Cookies、HTTP Parameters 等服务一定的规则)来进行设置;

    3. getCurrentEnvironmentLabel() 获取当前环境标签,环境标签是一个字符串,可以通过启动参数手动设置,也可以通过类似阿里巴巴 EDAS 应用平台等产品自动设置;

    4. isDuringCanaryRelease() 检查当前应用是否正在执行金丝雀发布;

    5. isInstanceWarmingUp() 检查当前应用在更新期间是否正在预热,EDAS产品请参考链接:EDAS预热支持

    6.  withTrafficLabel(String labelValue) 构建 opentelemetry 范围对象以指定流量标签将被带到的位置;

    7. getBaggageUserData() 获取当前在链路传递中的用户请求数据,例如:eagleeye 请求上下文中的用户数据;

    8. getBaggageUserDataValue(String key) 获取当前在链路传递中用户某个请求数据,例如:eagleeye 请求上下文中的用户数据;

    9. withBaggageUserData(Map<String, String> pairs) 构建 opentelemetry 范围对象以指定用户数据将被带到的位置;

    10. currentTraceId() 获取当前traceid,例如:eagleeye请求上下文中的traceid;

    11. getCurrentTrafficLabel() 获取当前应用的已发布服务实例,例如:Spring Cloud 上下文中的服务实例。

使用说明

配置说明

微服务治理实现的配置如下:

  1. 定义阿里云微服务治理实现的自动配置类 AliyunMicroServiceConfiguration ,使用注解 @ConditionalOnProperty(name = "alicloud.deployment.mode", havingValue = "EDAS_MANAGED") ,应用配置如下:
字段名 数据类型 默认值 备注
alicloud.deployment.mode String EDAS_MANAGED(固定值) 模式

场景一:给应用设置流量标识

POM 配置

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>com.alibaba.cloudapp</groupId>
            <artifactId>cloudapp-framework-dependencies</artifactId>
            <version>${revision}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

<dependencies>
    <dependency>
        <groupId>com.alibaba.cloudapp</groupId>
        <artifactId>spring-boot-starter-cloudapp</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>com.alibaba.cloudapp.microservice</groupId>
        <artifactId>cloudapp-microservice-aliyun</artifactId>
    </dependency>
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        <version>${spring-cloud-alibaba.version}</version>
    </dependency>
</dependencies>

应用配置

spring:
  application:
    name: cloudapp-microservice-aliyun-demo
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848

alicloud:
  deployment:
    mode: EDAS_MANAGED
    
server:
  port: 20001

使用验证

@RestController
public class DemoController {

    private static final Logger logger = LoggerFactory.getLogger(DemoApplication.class);

    @Autowired
    TrafficService trafficService;

    @GetMapping("/{tag}")
    public String tag(HttpServletRequest request,
                      @PathVariable String tag) {
        if (tag == null || tag.isEmpty()) {
            return "";
        }
        logger.info("traffic label before inject: {}", trafficService.getCurrentTrafficLabel());
        try (Scope ignored = trafficService.withTrafficLabel(tag)){
            logger.info("traffic label after inject: {}", trafficService.getCurrentTrafficLabel());
        }
        return tag;
    }
}

image.png