AOP实现上下游泳道隔离RPC调用

在平时代码项目代码测试的过程中,"隔离"思想就经常被用上,比方说多个并行开发的需求都需要用到服务 A 的能力,但是又需要同时部署 A 不同的代码分支,这个时候"泳道隔离"机制就显得尤为重要了。"泳道隔离"即将相同代码仓库的不同代码分支部署到不同的泳道环境中,代码分支的上下游也可以部署到相同的泳道环境中,我们通过指定对应的泳道环境标就可以将请求打到不同的环境中,真正实现代码隔离,提高程序员并行开发的效率。

但是存在这样一种场景,在基准泳道环境 env_a 上部署了一个项目 project_1,但是我并不想让 project_1 直接调用其在 env_a 中部署好的下游服务 project_2,我反倒想让它 "复用" 另一个泳道环境,泳道环境比方说 env_b 中的 project_2,这个时候就可以在 java 启动项目时的环境变量中动态指定,从而实现"跨泳道"的调用。本文就是想记录下我们如何通过 AOP 机制实现这种跨泳道的泳道环境标设置,具体的跨调用原理可以理解为 泳道基建可以根据设置的环境标帮我们做请求的转发。

主要是复习下 AOP 的用法

  1. 环境依赖搭建
java 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.jxz</groupId>
    <artifactId>AOP_RPC</artifactId>
    <version>1.0-SNAPSHOT</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.5.RELEASE</version>
    </parent>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>

</project>
  1. 注解和切面相关

注解

java 复制代码
package com.jxz.aop;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * @Author jiangxuzhao
 * @Description
 * @Date 2024/11/16
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ThriftEnv {
    String environmentVariable();
}

切面

java 复制代码
package com.jxz.aop;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

/**
 * @Author jiangxuzhao
 * @Description
 * @Date 2024/11/16
 */
@Aspect
@Component
@Slf4j
public class ThriftEnvAspect {


    @Pointcut("@annotation(com.jxz.aop.ThriftEnv)")
    public void pointCut() {

    }

    @Around(value = "pointCut()")
    public Object around(ProceedingJoinPoint jp) throws Throwable {
        Class<?> targetClass = jp.getTarget().getClass();
        log.info("目标类 = {}", targetClass);
        MethodSignature ms = (MethodSignature) jp.getSignature();
        log.info("目标方法签名 = {}", ms);
        Method method = targetClass.getMethod(ms.getName(), ms.getParameterTypes());
        log.info("目标方法 = {}", method);

        ThriftEnv annotation = method.getAnnotation(ThriftEnv.class);
        String env = annotation.environmentVariable();
        log.info("切换到目标泳道 = {}", env);

        return jp.proceed();
    }
}
  1. 调用下游 RPC 时使用注解
java 复制代码
package com.jxz.adapter;

import com.jxz.aop.ThriftEnv;
import org.springframework.stereotype.Service;

/**
 * @Author jiangxuzhao
 * @Description
 * @Date 2024/11/16
 */
@Service
public class AuthAdapter {

    @ThriftEnv(environmentVariable = "auth_thrift_env")
    public String queryAuth(String name) {
        return name + "_auth";
    }
}
  1. 在启动项目的环境变量中指定下游的泳道环境
相关推荐
cfm_29149 分钟前
SpringBoot启动原理
java·spring boot·spring
漫随流水1 小时前
Java——springboot web案例
java·开发语言·spring boot
从此以后自律1 小时前
Java Object 类常用方法全讲解
java·开发语言
念何架构之路1 小时前
Docker 容器状态机 学习
java·学习·docker
你有我备注吗1 小时前
SQL学习之查询
java·sql·学习
xixi09242 小时前
JMeter5.6.3基础使用教程1
java·开发语言
带刺的坐椅2 小时前
用 Solon ReActAgent 落地发票识别与智能报销
java·llm·solon·react-agent
罗超驿2 小时前
15.Java异常处理:从束手无策到从容应对
java·开发语言
半夜修仙2 小时前
RabbitMQ的推模式和拉模式
java·分布式·中间件·rabbitmq·github·java-rabbitmq
掉鱼的猫2 小时前
用 Solon ReActAgent 落地发票识别与智能报销
java·llm·agent