业务描述:
在微服务搭建中经常会使用到多数据库情形这个时候,多数据源的切换将显得尤为重要下面是以Mysql数据库为数据源来实现的多数据源的切换方案之一。
实现过程:
1、
编写SpringCloud服务项目的配置文件,通常是修改项目中resources包下的bootstrap.yml文件(PS:也有可能是application.yml文件)这里使用yml文件格式来编写配置。
spring:
datasource:
test1:
jdbc-url: jdbc:mysql://${数据库连接地址IP}:${数据库连接端口号}/${数据库名称}?characterEncoding=utf-8&serverTimezone=GMT%2B8&useSSL=false
username: ${用户名}
password: ${密码}
type: com.alibaba.druid.pool.DruidDataSource
initialSize: 5
minIdle: 5
maxActive: 50
maxWait: 60000
timeBetweenEvictionRunsMillis: 60000
minEvictableIdleTimeMillis: 300000
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
poolPreparedStatements: true
maxPoolPreparedStatementPerConnectionSize: 50
filters: stat
asyncInit: true
test2:
jdbc-url: jdbc:mysql://${数据库连接地址IP}:${数据库连接端口号}/${数据库名称}?characterEncoding=utf-8&serverTimezone=GMT%2B8&useSSL=false
username: ${用户名}
password: ${密码}
type: com.alibaba.druid.pool.DruidDataSource
initialSize: 5
minIdle: 5
maxActive: 50
maxWait: 60000
timeBetweenEvictionRunsMillis: 60000
minEvictableIdleTimeMillis: 300000
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
poolPreparedStatements: true
maxPoolPreparedStatementPerConnectionSize: 50
filters: stat
asyncInit: true
2、 在项目中创建config->mybatis包在其中进行实现多数据源的编写(PS:也可以放在别的包下这个包是自定义的)
3、 新建DataSourceConfig类用来注入Mysql数据的配置创建连接池并注入事务管理
代码如下:
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.core.MybatisConfiguration;
import com.baomidou.mybatisplus.core.config.GlobalConfig;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.BlockAttackInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
import org.apache.ibatis.logging.stdout.StdOutImpl;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.type.JdbcType;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;
@Configuration
@MapperScan(basePackages = "com.yasun.**.mapper", sqlSessionFactoryRef = "SqlSessionFactory")
public class DataSourceConfig {
@Primary
@Bean(name = "${数据库1}DataSource")
@ConfigurationProperties(prefix = "spring.datasource.group")
public DataSource getGroupDateSource() {
return DataSourceBuilder.create().build();
@Bean(name = "${数据库2}DataSource")
@ConfigurationProperties(prefix = "spring.datasource.mobile")
public DataSource getMobileDateSource() {
return DataSourceBuilder.create().build();
* 装载多个数据库源
* @param groupDataSource yasun_group_db数据库
* @param mobileDataSource yasun_mobile_db数据库
* @return 返回数据源集合
@Bean(name = "dynamicDataSource")
public DynamicDataSource dataSource(@Qualifier("${数据库1}DataSource") DataSource ${数据库1}DataSource,
@Qualifier("${数据库2}DataSource") DataSource ${数据库2}DataSource) {
Map<Object, Object> targetDataSource = new HashMap<>(16);
targetDataSource.put(DataSourceType.DataBaseType.test1, ${数据库1}DataSource);
targetDataSource.put(DataSourceType.DataBaseType.test2, ${数据库2}DataSource);
DynamicDataSource dataSource = new DynamicDataSource();
dataSource.setTargetDataSources(targetDataSource);
dataSource.setDefaultTargetDataSource(groupDataSource);
return dataSource;
* 装配数据源添加扫描mapper.xml文件的路径位置
* @param dynamicDataSource 多数据库源对象
* @return 返回sql会话工厂
@Bean(name = "SqlSessionFactory")
public SqlSessionFactory setSqlSessionFactory(@Qualifier("dynamicDataSource") DataSource dynamicDataSource) throws Exception {
MybatisSqlSessionFactoryBean sessionFactory = new MybatisSqlSessionFactoryBean();
sessionFactory.setDataSource(dynamicDataSource);
sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:/mapper/**/*Mapper.xml"));
sessionFactory.setTypeAliasesPackage("com.yasun.${项目的包名}.*.entity");
MybatisConfiguration configuration = new MybatisConfiguration();
configuration.setJdbcTypeForNull(JdbcType.NULL);
configuration.setMapUnderscoreToCamelCase(true);
configuration.setCacheEnabled(false);
configuration.setLogImpl(StdOutImpl.class);
sessionFactory.setConfiguration(configuration);
sessionFactory.setPlugins(mybatisPlusInterceptor());
sessionFactory.setGlobalConfig(globalConfig());
return sessionFactory.getObject();
* Mybatis-plus插件添加
* @return 返回插件集合
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor();
paginationInnerInterceptor.setDbType(DbType.MYSQL);
paginationInnerInterceptor.setOverflow(true);
BlockAttackInnerInterceptor blockAttackInnerInterceptor = new BlockAttackInnerInterceptor();
interceptor.addInnerInterceptor(paginationInnerInterceptor);
interceptor.addInnerInterceptor(blockAttackInnerInterceptor);
return interceptor;
@Bean
public GlobalConfig globalConfig() {
GlobalConfig globalConfig = new GlobalConfig();
globalConfig.setMetaObjectHandler(new MetaHandler());
return globalConfig;
* 注入事务管理
@Bean
public DataSourceTransactionManager transactionManager(DynamicDataSource dynamicDataSource) {
return new DataSourceTransactionManager(dynamicDataSource);
4、 新建DataSourceType类,用来标记获取不同数据库的类型通俗点说就是给你的几个不同的数据库打上标记好来找到它们。
代码如下:
package com.yasun.config.mybatis;
public class DataSourceType {
*数据库类型
public enum DataBaseType {
* 连接 ${数据库1}数据库
${数据库1},
* 连接 ${数据库2}数据库
${数据库2},
* 连接 ${数据库3}数据库
${数据库3}
* 使用ThreadLocal保证线程安全
private static final ThreadLocal<DataBaseType> TYPE = new ThreadLocal<>();
* 往当前线程里设置数据源类型
* @param dataBaseType 数据源类型
public static void setDataBaseType(DataBaseType dataBaseType) {
if (dataBaseType == null) {
throw new NullPointerException();
TYPE.set(dataBaseType);
* 获取数据源类型
* @return 返回数据源的类型
public static DataBaseType getDataBaseType() {
return TYPE.get() == null ? DataBaseType.${数据库1}: TYPE.get();
* 清空数据类型
public static void clearDataBaseType() {
TYPE.remove();
5、 创建DynamicDataSource类存储多个数据库源并记录他们(PS:这个说法并不准确个人理解)
代码如下:
package com.yasun.config.mybatis;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
public class DynamicDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
return DataSourceType.getDataBaseType();
6、 创建扫描切面使用Spring框架中的AOP功能实现在特定的包下使用特定的数据源创建DataSourceAop类。
代码如下:
package com.yasun.config.mybatis;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class DataSourceAop {
* 设定切面地址在所有调用以下包下的任意类的任意方法或接口时切换数据源成指定数据源
@Before("execution(public * ${自定义包名1}.*.mapper.${自定义包名1}..*(..))")
public void setDataSource${数据库1}() {
DataSourceType.setDataBaseType(DataSourceType.DataBaseType.${数据库1});
@Before("execution(public * ${自定义包名2}.*.mapper.${自定义包名2}..*(..))")
public void setDataSource${数据库2}()) {
DataSourceType.setDataBaseType(DataSourceType.DataBaseType.${数据库2});
以上所有配置均在SpringCloud的框架中实现。
**业务描述:**在微服务搭建中经常会使用到多数据库情形这个时候,多数据源的切换将显得尤为重要下面是以Mysql数据库为数据源来实现的多数据源的切换方案之一。实现过程:**1、**编写SpringCloud服务项目的配置文件,通常时修改项目中resources包下的bootstrap.yml文件(PS:也有可能是application.yml文件)这里使用yml文件格式来编写配置。spring: #MySql数据源 datasource: #test1数据库配置
lamp-cloud微服务脚手架的前身是zuihou-admin-cloud,从3.0.0版本开始,改名为lamp-cloud,它是lamp项目的其中一员。
lamp-cloud微服务脚手架是一个基于SpringCloud(Hoxton.SR10) + SpringBoot(2.3.10.RELEASE)的SaaS微服务脚手架,具有统一授权、认证后台管理系统,其中包含具备用户管理、资源权限管理、网关API、分布式事务、大文件断点分片续传等多个模块,支持多业务系统并行开发,可以作为后端服务的开发脚手架。代码简洁,架构清晰,适合学习和直接项目中使用。核心技术采用Nacos、Fegin、Ribbon、Zuul、Hystrix、JWT Token、Mybatis、SpringBoot、Redis、RibbitMQ等主要框架和中间件。
lamp-cloud微服务脚手架功能:
1、服务注册&发现与调用:
基于Nacos来实现的服务注册与发现,使用使用Feign来实现服务互调, 可以做到使用HTTP请求远程调用时能与调用本地方法一样的编码体验,开发者完全感知不到这是远程方法,更感知不到这是个HTTP请求。
2、服务鉴权:
通过JWT的方式来加强服务之间调度的权限验证,保证内部服务的安全性。
3、负载均衡:
将服务保留的rest进行代理和网关控制,除了平常经常使用的node.js、nginx外,Spring Cloud系列的zuul和ribbon,可以帮我们进行正常的网关管控和负载均衡。其中扩展和借鉴国外项目的扩展基于JWT的Zuul限流插件,方面进行限流。
4、熔断机制:
因为采取了服务的分布,为了避免服务之间的调用“雪崩”,采用了Hystrix的作为熔断器,避免了服务之间的“雪崩”。
5、监控:
利用Spring Boot Admin 来监控各个独立Service的运行状态;利用turbine来实时查看接口的运行状态和调用频率;通过Zipkin来查看各个服务之间的调用链等。
6、链路调用监控:
利用Zipkin实现微服务的全链路性能监控, 从整体维度到局部维度展示各项指标,将跨应用的所有调用链性能信息集中展现,可方便度量整体和局部性能,并且方便找到故障产生的源头,生产上可极大缩短故障排除时间。有了它,我们能做到:
请求链路追踪,故障快速定位:可以通过调用链结合业务日志快速定位错误信息。 可视化:各个阶段耗时,进行性能分析。 依赖优化:各个调用环节的可用性、梳理服务依赖关系以及优化。 数据分析,优化链路:可以得到用户的行为路径,汇总分析应用在很多业务场景。
7、数据权限
利用基于Mybatis的DataScopeInterceptor拦截器实现了简单的数据权限
8、SaaS(多租户)的无感解决方案
使用Mybatis拦截器实现对所有SQL的拦截,修改默认的Schema,从而实现多租户数据隔离的目的。 并且支持可插拔。
9、二级缓存
采用J2Cache操作缓存,第一级缓存使用内存(Caffeine),第二级缓存使用 Redis。 由于大量的缓存读取会导致 L2 的网络成为整个系统的瓶颈,因此 L1 的目标是降低对 L2 的读取次数。 该缓存框架主要用于集群环境中。单机也可使用,用于避免应用重启导致的缓存冷启动后对后端业务的冲击。
10、优雅的Bean转换
采用Dozer组件来对 DTO、DO、PO等对象的优化转换
11、前后端统一表单验证
严谨的表单验证通常需要 前端+后端同时验证, 但传统的项目,均只能前后端各做一次检验, 后期规则变更,又得前后端同时修改。 故在hibernate-validator的基础上封装了zuihou-validator-starter起步依赖,提供一个通用接口,可以获取需要校验表单的规则,然后前端使用后端返回的规则, 以后若规则改变,只需要后端修改即可。
12、防跨站脚本攻击(XSS)
通过过滤器对所有请求中的 表单参数 进行过滤
通过Json反序列化器实现对所有 application/json 类型的参数 进行过滤
13、当前登录用户信息注入器
通过注解实现用户身份注入
14、在线API
由于原生swagger-ui某些功能支持不够友好,故采用了国内开源的swagger-bootstrap-ui,并制作了stater,方便springboot用户使用。
15、代码生成器
基于Mybatis-plus-generator自定义了一套代码生成器, 通过配置数据库字段的注释,自动生成枚举类、数据字典注解、SaveDTO、UpdateDTO、表单验证规则注解、Swagger注解等。
16、定时任务调度器:
基于xxl-jobs进行了功能增强。(如:指定时间发送任务、执行器和调度器合并项目、多数据源)
17、大文
sk-spring-cloud-master
定位用当下最流行的springcloud技术,搭建了一套易理解、高可用、高扩展的分布式微服务框架,方便实现快速开发。
sk-spring-cloud-master
├── sk-base -- 公共模块
├───── common-base -- 公共核心模块(mybatis等)
├───── spring-social -- 三方登陆模块
├── sk-example -- 相关example模块
├───── sk-fastdfs -- fastdfs使用相关模块
├───── sk-multiple-data-sources -- 多数据源模块
├───── sk-rabbitmq -- rabbitmq相关demo模块
├───── sk-redis -- redis相关demo模块
├── spring-cloud-p
使用Consul来替换Eureka 21
使用Zookeeper来替换Eureka 25
Consistency(一致性), 数据一致更新,所有数据变动都是同步的 Availability(可用性), 好的响应性能 Partition tolerance(分区容忍性) 可靠性 28
客户端负载均衡器 29
客户端负载均衡器 29
Ribbon与Nginx区别 29
RestTemplate 31
请求类型 31
负载均衡器源码分析 33
负载均衡器重试机制 33
服务保护机制SpringCloud Hystrix 33
微服务高可用技术 33
服务降级、熔断、限流概念 34
服务学崩效应 34
服务降级 34
服务熔断 35
服务隔离 35
服务限流 36
Hystrix简单介绍 36
Hystrix环境搭建 37
Maven依赖信息 37
开启Hystrix断路器 37
服务降级处理 38
Hystrix仪表盘 39
Turbine集群监控 39
声明式服务调用SpringCloud Feign 39
feign介绍 39
环境搭建 40
Maven依赖信息 40
feign客户端接口 40
feign继承特性 41
创建springcloud-2.0-parent 42
Ribbon配置 45
配置Feign客户端超时时间 45
Api网关服务SrpingCloud Zuul 45
网关分类 46
网关设计 46
网关框架 48
网关作用 49
网关与过滤器区别 49
Nginx与Zuul的区别 49
Zuul网关 49
动态网关 53
网关集群 55
分布式配置中心SrpingCloud config 57
SpringCloud分布式配置中心 57
Config架构 58
Git环境搭建 58
服务端详解 58
Maven依赖信息 58
application.yml配置 59
项目启动 60
客户端详解 60
Maven依赖信息 60
bootstrap.yml 61
读取配置文件 62
动态刷新数据 62
actuator端点刷新数据 63
Maven依赖信息 63
Bootstrap.xml新增 63
include: "*" 63
生效前提 63
private String itmayieduInfo; 63
当配置更改时,标有@RefreshScope的Bean将得到特殊处理来生效配置 64
手动刷新接口 64
分布式服务跟踪SpringCloud sleuth 64
什么是Sleuth 64
环境搭建 64
构建server-zipkin 64
会员服务 65
订单服务 65
Swagger2API接口管理 65
课题引入 65
传统的API文档编写存在以下几个痛点: 66
Swagger具有以下优点 66
Swagg er 2.0 集成配置 66
Maven依赖信息 66
SwaggerConfig 68
Zull整合Swagger管理微服务所有API 68
会员和订单引入Maven依赖 68
ZuulGateway网关 69
想法2020.3 吉特邮差导航外壳MobaXterm Mobaxterm redis-desktop-manager 崇高测试
春云纳科斯假装MySQL 8.0 mybatis-plus(代码生成器待实现) 网关redis(单机,待完善完善) rocketMQ(单机,待完善体现) seata(待分布式测试) xxl-job(待完成) zookeeper(待完成)
多线程-螺纹池(这里需要组装统一管理的工具类)代码生成器fastjson Lombok阿里连接池(ali-durid) commons-lang(StringUtils工具) 切面pagehelper(分页) mvn插件(打包,压缩等)
Spring Cloud Config为微服务架构提供了配置管理的功能。通过Spring Cloud Config服务端提供配置中心,在各个微服务应用的客户端读取来自服务端配置中心的配置项。配置中心的数据源可以来自git、svn、数据库、操作系统的本地文件、jar包中的文件、vault、组合
EnvironmentRepository接口
可以看到上图有对应的类负责存储配置中心的配置数据。...
的配置方法。
java的多数据源配置方法是通过使用第三方库或者自定义实现来实现的。
一种常用的方法是使用Spring框架中的AbstractRoutingDataSource类,该类可以动态地切换数据源,从而实现多数据源的配置。
另外,还可以使用Mybatis框架中的SqlSessionFactoryBean类来配置多数据源,该类可以通过配置不同的数据源信息来实现多数据源的配置。
总的来说,jav...
微服务架构
1、项目简介
微服务架构案例核心内容,基于SpringCloud框架几个核心组件,Eureka服务注册与发现组件,Feign声明式的WebService客户端组件,Zuul动态路由网关组件。进行多个数据管理,多个服务管理搭建,多个中间件集成,多业务拆分等模式,搭建SpringCloud微服务框架的综合应用案例。
2、技术选型
基础层框架:Spring5+,SpringBoot2+,SpringCloud2+
持久层框架:MyBatis,MyBatis-Plus
开发组件:Druid,Log4j,FastJson,JodaTime,JavaMail
中间件集成:RocketMQ,Redis,Quart,ElasticSearch
数据存储:MySQL、Redis、ElasticSearch
3、依赖知识点
这是授权服务器和支持和的OpenID提供程序的实现。
该实现是使用 ,JAX-RS 2.0 API和库。 JAX-RS是RESTful Web服务的Java API 。 JAX-RS 2.0 API已通过进行了标准化,并且已包含在Java EE 7中。另一方面,authlete-java-jaxrs库是一个开放源代码库,它为开发人员提供了用于实现授权服务器和资源的实用程序类。服务器。 authlete-java-jaxrs依次使用库,该库是另一个与进行通信的开源库。
此实现是无数据库的。 这意味着您不必具有存储授权数据(例如,访问令牌),授权服务器本身的设置以及客户端应用程序的设置的数据库服务器。 这可以通过将用作后端服务来实现。 阅读以获取有关该体系结构的详细信息。
可以在使用Authlete作为后端服务的资源服务器上使用
若依是一个 Java EE 企业级快速开发平台,基于经典技术组合(Spring Boot、Spring Security、MyBatis、Jwt、Vue),内置模块如:部门管理、角色用户、菜单及按钮授权、数据权限、系统参数、日志管理、代码生成等。在线定时任务配置;支持集群,支持多数据源,支持分布式事务。Spring Boot是一款开箱即用框架,提供各种默认配置来简化项目配置。让我们的Spring应用变的更轻量化、更快的入门。 在主程序执行main函数就可以运行。你也可以打包你的应用为jar并通过使用java -jar来运行你的Web应用。它遵循"约定优先于配置"的原则, 使用SpringBoot只需很少的配置,大部分的时候直接使用默认的配置即可。同时可以与Spring Cloud的微服务无缝结合
Sentinel
Sentinel 是阿里巴巴开源的一款断路器实现,本身在阿里内部已经被大规模采用,非常稳定。
丰富的应用场景: Sentinel 承接了阿里巴巴近10年的双十一大促流量的核心场景,例如秒杀(即突发流量控制在系统容量可以承受的范围)、消息削峰填谷、集群流量控制、实时熔断下游不可用应用等。
完备的实时监控: Sentinel提供了实时的监控功能。通过控制台可以看到接入应用的单台机器秒级数据,甚至500台以下规模的集群的汇总运行情况。
广泛的开源生态: Sentinel提供开箱即用的与其它开源框架/库的整合模块,例如与Spring Cloud、Dubbo.gRPC的整合。只需要引入相应的依赖并进行简单的配置即可快速地接入Sentinel。
完善的SPI扩展点: Sentinel提供简单易用、完善的SPI扩展接口。您可以通过实现扩展接口来快速地定制逻辑。例如定制规则管理、适配动态数据源等。