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. 在启动项目的环境变量中指定下游的泳道环境
相关推荐
有梦想的攻城狮1 小时前
maven中的maven-antrun-plugin插件详解
java·maven·插件·antrun
硅的褶皱5 小时前
对比分析LinkedBlockingQueue和SynchronousQueue
java·并发编程
MoFe15 小时前
【.net core】天地图坐标转换为高德地图坐标(WGS84 坐标转 GCJ02 坐标)
java·前端·.netcore
季鸢5 小时前
Java设计模式之观察者模式详解
java·观察者模式·设计模式
Fanxt_Ja5 小时前
【JVM】三色标记法原理
java·开发语言·jvm·算法
Mr Aokey6 小时前
Spring MVC参数绑定终极手册:单&多参/对象/集合/JSON/文件上传精讲
java·后端·spring
14L6 小时前
互联网大厂Java面试:从Spring Cloud到Kafka的技术考察
spring boot·redis·spring cloud·kafka·jwt·oauth2·java面试
小马爱记录7 小时前
sentinel规则持久化
java·spring cloud·sentinel
地藏Kelvin7 小时前
Spring Ai 从Demo到搭建套壳项目(二)实现deepseek+MCP client让高德生成昆明游玩4天攻略
人工智能·spring boot·后端
一个有女朋友的程序员7 小时前
Spring Boot 缓存注解详解:@Cacheable、@CachePut、@CacheEvict(超详细实战版)
spring boot·redis·缓存