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. 在启动项目的环境变量中指定下游的泳道环境
相关推荐
用户094248568035 分钟前
第11章:OpenJDK反射、动态代理与 MethodHandle 初探
java·jvm
小蒜学长12 分钟前
基于SpringBoot+Vue的游戏论坛系统的设计与实现(代码+数据库+LW)
java·后端·springboot·游戏论坛系统·社区生态
SimonKing17 分钟前
文档杂乱怎么查找:用 Papra 搭一个极简文档管理系统
java·后端·程序员
captain37618 分钟前
网络原理(7)-NAT(Network Address Translation)
java·网络·网络协议·java-ee
jaysee-sjc25 分钟前
【苍穹外卖】Day01:从零认识企业级项目开发
java·开发语言·数据库·mysql·spring·intellij-idea·mybatis
雨辰AI26 分钟前
多租户数据库资源配额管控|避免租户资源抢占雪崩(金仓 / 达梦 / 高斯 /openGauss 全库原生适配)
java·大数据·数据库·后端
AI深栈29 分钟前
第 12 章 · AI智能体的结构化输出与流式响应
java·人工智能
君顾134 分钟前
本地AI错题纠正小程序:端侧推理与错题闭环实战
java·开发语言·错题
Wang's Blog39 分钟前
Java 服务器: Linux-yum在线安装与lrzsz文件传输
java·服务器
Java内核笔记1 小时前
Spring Boot 4 与 Spring AI 2.0 深度集成:ChatClient、Advisor 链与 MCP(源码级实战)
java·后端