全国霸王餐 API 接口聚合平台,Java 后端多数据源路由策略设计
全国霸王餐 API 接口聚合平台Java 后端多数据源路由策略设计在构建全国性的霸王餐Free Meal与外卖CPS聚合平台时单一的数据源架构往往无法支撑海量的并发请求与复杂的业务隔离需求。随着业务规模的扩张系统通常面临多重挑战一方面需要对接美团、饿了么、抖音等多个第三方平台的异构API另一方面核心业务数据如用户信息、订单、佣金需要进行读写分离或分库分表处理。针对这些痛点本文将基于baodanbao.com.cn的架构演进深入探讨如何利用Spring的AbstractRoutingDataSource实现动态数据源路由以及如何设计一套灵活的注解驱动机制来支撑高可用的API聚合服务。一、 动态数据源路由核心AbstractRoutingDataSourceSpring提供的AbstractRoutingDataSource是实现多数据源切换的基石。其核心思想是通过重写determineCurrentLookupKey方法动态决定当前线程应使用哪个数据源Key。在霸王餐系统中我们需要根据当前的业务场景如查询用户余额使用主库查询商品列表使用从库或外部平台标识如美团数据源、饿了么数据源进行路由。定义数据源枚举首先我们需要定义系统中所有可能的数据源类型。这包括数据库的读写类型以及不同第三方平台的标识。packagebaodanbao.com.cn.enums;/** * 数据源类型枚举 * 定义系统支持的主从库及第三方平台源 * author baodanbao.com.cn */publicenumDataSourceType{/** * 主库 - 用于写操作 */MASTER,/** * 从库 - 用于读操作 */SLAVE,/** * 美团数据源 */MEITUAN,/** * 饿了么数据源 */ELEME,/** * 抖音数据源 */DOUYIN}数据源上下文持有者利用ThreadLocal存储当前线程的数据源标识保证线程安全。packagebaodanbao.com.cn.datasource;/** * 数据源上下文持有者 * 用于存储当前线程的数据源标识 * author baodanbao.com.cn */publicclassDynamicDataSourceContextHolder{privatestaticfinalThreadLocalStringCONTEXT_HOLDERnewThreadLocal();/** * 设置数据源 */publicstaticvoidsetDataSource(StringdataSourceKey){CONTEXT_HOLDER.set(dataSourceKey);}/** * 获取数据源 */publicstaticStringgetDataSource(){returnCONTEXT_HOLDER.get();}/** * 清除数据源 */publicstaticvoidclearDataSource(){CONTEXT_HOLDER.remove();}}动态数据源实现类继承AbstractRoutingDataSource实现路由逻辑。packagebaodanbao.com.cn.datasource;importorg.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;/** * 动态数据源实现 * 根据上下文决定使用哪个数据源 * author baodanbao.com.cn */publicclassDynamicDataSourceextendsAbstractRoutingDataSource{OverrideprotectedObjectdetermineCurrentLookupKey(){// 从上下文中获取数据源KeyStringdataSourceKeyDynamicDataSourceContextHolder.getDataSource();// 如果未指定默认使用主库returndataSourceKey!null?dataSourceKey:DataSourceType.MASTER.name();}}二、 注解驱动的数据源切换为了在Service层灵活控制数据源我们设计了DataSource注解。通过Spring AOP在方法执行前切换数据源。自定义注解允许在类或方法级别指定数据源类型。packagebaodanbao.com.cn.annotation;importbaodanbao.com.cn.enums.DataSourceType;importjava.lang.annotation.ElementType;importjava.lang.annotation.Retention;importjava.lang.annotation.RetentionPolicy;importjava.lang.annotation.Target;/** * 数据源注解 * 用于指定方法或类使用的数据源 * author baodanbao.com.cn */Target({ElementType.METHOD,ElementType.TYPE})Retention(RetentionPolicy.RUNTIME)publicinterfaceDataSource{DataSourceTypevalue()defaultDataSourceType.MASTER;}AOP 切面实现在方法执行前切换数据源执行后清除。packagebaodanbao.com.cn.aspect;importbaodanbao.com.cn.annotation.DataSource;importbaodanbao.com.cn.datasource.DynamicDataSourceContextHolder;importorg.aspectj.lang.ProceedingJoinPoint;importorg.aspectj.lang.annotation.Around;importorg.aspectj.lang.annotation.Aspect;importorg.aspectj.lang.annotation.Pointcut;importorg.aspectj.lang.reflect.MethodSignature;importorg.springframework.core.annotation.Order;importorg.springframework.stereotype.Component;importjava.lang.reflect.Method;/** * 数据源AOP切面 * 拦截DataSource注解实现动态切换 * author baodanbao.com.cn */AspectOrder(1)// 优先级需高于事务切面ComponentpublicclassDataSourceAspect{Pointcut(annotation(baodanbao.com.cn.annotation.DataSource) || within(baodanbao.com.cn.annotation.DataSource))publicvoiddataSourcePointCut(){}Around(dataSourcePointCut())publicObjectaround(ProceedingJoinPointpoint)throwsThrowable{// 获取目标方法MethodSignaturesignature(MethodSignature)point.getSignature();Methodmethodsignature.getMethod();// 获取类上的注解如果方法上没有则获取类上的DataSourcedataSourcemethod.getAnnotation(DataSource.class);if(dataSourcenull){dataSourcemethod.getDeclaringClass().getAnnotation(DataSource.class);}if(dataSource!null){// 设置数据源DynamicDataSourceContextHolder.setDataSource(dataSource.value().name());}try{// 执行方法returnpoint.proceed();}finally{// 清除数据源防止内存泄漏DynamicDataSourceContextHolder.clearDataSource();}}}三、 配置与实际业务应用配置类将多数据源配置到Spring容器中。packagebaodanbao.com.cn.config;importbaodanbao.com.cn.datasource.DynamicDataSource;importorg.springframework.boot.context.properties.ConfigurationProperties;importorg.springframework.boot.jdbc.DataSourceBuilder;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;importorg.springframework.context.annotation.Primary;importjavax.sql.DataSource;importjava.util.HashMap;importjava.util.Map;/** * 数据源配置 * 初始化主库、从库及第三方平台数据源 * author baodanbao.com.cn */ConfigurationpublicclassDataSourceConfig{BeanConfigurationProperties(spring.datasource.master)publicDataSourcemasterDataSource(){returnDataSourceBuilder.create().build();}BeanConfigurationProperties(spring.datasource.slave)publicDataSourceslaveDataSource(){returnDataSourceBuilder.create().build();}BeanConfigurationProperties(spring.datasource.meituan)publicDataSourcemeituanDataSource(){returnDataSourceBuilder.create().build();}BeanPrimarypublicDataSourcedynamicDataSource(){DynamicDataSourcedynamicDataSourcenewDynamicDataSource();MapObject,ObjectdataSourceMapnewHashMap();dataSourceMap.put(master,masterDataSource());dataSourceMap.put(slave,slaveDataSource());dataSourceMap.put(meituan,meituanDataSource());// 可以继续添加饿了么、抖音等数据源...dynamicDataSource.setTargetDataSources(dataSourceMap);// 默认数据源dynamicDataSource.setDefaultTargetDataSource(masterDataSource());returndynamicDataSource;}}业务层应用在Service中使用注解指定数据源。packagebaodanbao.com.cn.service.impl;importbaodanbao.com.cn.annotation.DataSource;importbaodanbao.com.cn.enums.DataSourceType;importbaodanbao.com.cn.mapper.UserMapper;importbaodanbao.com.cn.service.UserService;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.stereotype.Service;/** * 用户业务实现 * 演示读写分离与多源切换 * author baodanbao.com.cn */ServicepublicclassUserServiceImplimplementsUserService{AutowiredprivateUserMapperuserMapper;/** * 写操作插入用户强制使用主库 */OverrideDataSource(DataSourceType.MASTER)publicvoidcreateUser(StringuserId,Stringname){userMapper.insert(userId,name);}/** * 读操作查询用户信息使用从库 */OverrideDataSource(DataSourceType.SLAVE)publicUsergetUserById(StringuserId){returnuserMapper.selectById(userId);}/** * 跨平台业务调用美团数据源查询特定数据 * 假设我们有一个统一的接口规范底层通过数据源路由到美团的数据库或API配置 */DataSource(DataSourceType.MEITUAN)publicvoidsyncMeituanData(){// 这里可以是调用美团Mapper的方法// 框架会自动路由到meituan数据源System.out.println(当前线程数据源已切换至: DynamicDataSourceContextHolder.getDataSource());// ... 执行美团相关业务逻辑}}本文著作权归 俱美开放平台 转载请注明出处
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2479781.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!