微服务架构模式的切换

pull/362/head
AlanScipio 2 years ago
parent 2f8326bc84
commit 880916e493

@ -55,3 +55,7 @@ com.ruoyi
15. 服务监控监视当前系统CPU、内存、磁盘、堆栈等相关信息。 15. 服务监控监视当前系统CPU、内存、磁盘、堆栈等相关信息。
16. 在线构建器拖动表单元素生成相应的HTML代码。 16. 在线构建器拖动表单元素生成相应的HTML代码。
17. 连接池监视监视当前系统数据库连接池状态可进行分析SQL找出系统性能瓶颈。 17. 连接池监视监视当前系统数据库连接池状态可进行分析SQL找出系统性能瓶颈。
# 微服务架构模式的切换
详见[微服务架构在不同模式下的切换](./STRUCTURE_MODE.md)

@ -0,0 +1,28 @@
# 微服务架构模式的切换
- 常规微服务架构模式
- all-in-one架构模式将大部分模块集成到ruoyi-system模块里
### 常规微服务架构
1. 确保ruoyi-system模块的maven依赖里**没有**引入其他模块的依赖,需要检查的依赖如下:
- ruoyi-auth鉴权模块
- ruoyi-file文件模块
- ruoyi-job定时任务模块
- 其他后续追加的业务模块...
2. nacos配置使用**GROUP_ALL_IN_1**分组
3. ruoyi-system模块的入口启动类使用`com.ruoyi.system.RuoYiSystemApplication`
4. 注解掉ruoyi-system模块里其他模式的入口启动类
5. 【可选】ruoyi-system模块的`bootstrap.yml`里,关闭配置项:`spring.main.allow-bean-definition-overriding: false`
### all-in-one架构模式
1. 确保ruoyi-system模块的maven依赖里**引入了**其他模块的依赖,需要检查的依赖如下:
- ruoyi-auth鉴权模块
- ruoyi-file文件模块
- ruoyi-job定时任务模块
- 其他后续追加的业务模块...
2. nacos配置使用**DEFAULT_GROUP**分组
3. ruoyi-system模块的入口启动类使用`com.ruoyi.SystemAllApplication`
4. 注解掉ruoyi-system模块里其他模式的入口启动类
5. ruoyi-system模块的`bootstrap.yml`里,确保开启配置项:`spring.main.allow-bean-definition-overriding: true`

@ -219,6 +219,27 @@
<version>${ruoyi.version}</version> <version>${ruoyi.version}</version>
</dependency> </dependency>
<!-- 鉴权模块 -->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-auth</artifactId>
<version>${ruoyi.version}</version>
</dependency>
<!-- 文件模块 -->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-modules-file</artifactId>
<version>${ruoyi.version}</version>
</dependency>
<!-- 定时任务模块 -->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-modules-job</artifactId>
<version>${ruoyi.version}</version>
</dependency>
</dependencies> </dependencies>
</dependencyManagement> </dependencyManagement>

@ -17,25 +17,24 @@ import com.ruoyi.system.api.factory.RemoteLogFallbackFactory;
* @author ruoyi * @author ruoyi
*/ */
@FeignClient(contextId = "remoteLogService", value = ServiceNameConstants.SYSTEM_SERVICE, fallbackFactory = RemoteLogFallbackFactory.class) @FeignClient(contextId = "remoteLogService", value = ServiceNameConstants.SYSTEM_SERVICE, fallbackFactory = RemoteLogFallbackFactory.class)
public interface RemoteLogService public interface RemoteLogService {
{
/** /**
* *
* *
* @param sysOperLog * @param sysOperLog
* @param source * @param source
* @return * @return
*/ */
@PostMapping("/operlog") @PostMapping("/operlog")
public R<Boolean> saveLog(@RequestBody SysOperLog sysOperLog, @RequestHeader(SecurityConstants.FROM_SOURCE) String source) throws Exception; R<Boolean> saveLog(@RequestBody SysOperLog sysOperLog, @RequestHeader(SecurityConstants.FROM_SOURCE) String source) throws Exception;
/** /**
* 访 * 访
* *
* @param sysLogininfor 访 * @param sysLogininfor 访
* @param source * @param source
* @return * @return
*/ */
@PostMapping("/logininfor") @PostMapping("/logininfor")
public R<Boolean> saveLogininfor(@RequestBody SysLogininfor sysLogininfor, @RequestHeader(SecurityConstants.FROM_SOURCE) String source); R<Boolean> saveLogininfor(@RequestBody SysLogininfor sysLogininfor, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);
} }

@ -2,6 +2,7 @@ package com.ruoyi.auth;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import com.ruoyi.common.security.annotation.EnableRyFeignClients; import com.ruoyi.common.security.annotation.EnableRyFeignClients;
@ -10,6 +11,7 @@ import com.ruoyi.common.security.annotation.EnableRyFeignClients;
* *
* @author ruoyi * @author ruoyi
*/ */
@ConditionalOnProperty(name = "spring.cloud.nacos.config.group", havingValue = "DEFAULT_GROUP", matchIfMissing = true)
@EnableRyFeignClients @EnableRyFeignClients
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class }) @SpringBootApplication(exclude = {DataSourceAutoConfiguration.class })
public class RuoYiAuthApplication public class RuoYiAuthApplication

@ -24,8 +24,7 @@ import com.ruoyi.system.api.model.LoginUser;
* @author ruoyi * @author ruoyi
*/ */
@Component @Component
public class SysLoginService public class SysLoginService {
{
@Autowired @Autowired
private RemoteUserService remoteUserService; private RemoteUserService remoteUserService;
@ -41,58 +40,49 @@ public class SysLoginService
/** /**
* *
*/ */
public LoginUser login(String username, String password) public LoginUser login(String username, String password) {
{
// 用户名或密码为空 错误 // 用户名或密码为空 错误
if (StringUtils.isAnyBlank(username, password)) if (StringUtils.isAnyBlank(username, password)) {
{
recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "用户/密码必须填写"); recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "用户/密码必须填写");
throw new ServiceException("用户/密码必须填写"); throw new ServiceException("用户/密码必须填写");
} }
// 密码如果不在指定范围内 错误 // 密码如果不在指定范围内 错误
if (password.length() < UserConstants.PASSWORD_MIN_LENGTH if (password.length() < UserConstants.PASSWORD_MIN_LENGTH
|| password.length() > UserConstants.PASSWORD_MAX_LENGTH) || password.length() > UserConstants.PASSWORD_MAX_LENGTH) {
{
recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "用户密码不在指定范围"); recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "用户密码不在指定范围");
throw new ServiceException("用户密码不在指定范围"); throw new ServiceException("用户密码不在指定范围");
} }
// 用户名不在指定范围内 错误 // 用户名不在指定范围内 错误
if (username.length() < UserConstants.USERNAME_MIN_LENGTH if (username.length() < UserConstants.USERNAME_MIN_LENGTH
|| username.length() > UserConstants.USERNAME_MAX_LENGTH) || username.length() > UserConstants.USERNAME_MAX_LENGTH) {
{
recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "用户名不在指定范围"); recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "用户名不在指定范围");
throw new ServiceException("用户名不在指定范围"); throw new ServiceException("用户名不在指定范围");
} }
// IP黑名单校验 // IP黑名单校验
String blackStr = Convert.toStr(redisService.getCacheObject(CacheConstants.SYS_LOGIN_BLACKIPLIST)); String blackStr = Convert.toStr(redisService.getCacheObject(CacheConstants.SYS_LOGIN_BLACKIPLIST));
if (IpUtils.isMatchedIp(blackStr, IpUtils.getIpAddr())) if (IpUtils.isMatchedIp(blackStr, IpUtils.getIpAddr())) {
{
recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "很遗憾访问IP已被列入系统黑名单"); recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "很遗憾访问IP已被列入系统黑名单");
throw new ServiceException("很遗憾访问IP已被列入系统黑名单"); throw new ServiceException("很遗憾访问IP已被列入系统黑名单");
} }
// 查询用户信息 // 查询用户信息
R<LoginUser> userResult = remoteUserService.getUserInfo(username, SecurityConstants.INNER); R<LoginUser> userResult = remoteUserService.getUserInfo(username, SecurityConstants.INNER);
if (StringUtils.isNull(userResult) || StringUtils.isNull(userResult.getData())) if (StringUtils.isNull(userResult) || StringUtils.isNull(userResult.getData())) {
{
recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "登录用户不存在"); recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "登录用户不存在");
throw new ServiceException("登录用户:" + username + " 不存在"); throw new ServiceException("登录用户:" + username + " 不存在");
} }
if (R.FAIL == userResult.getCode()) if (R.FAIL == userResult.getCode()) {
{
throw new ServiceException(userResult.getMsg()); throw new ServiceException(userResult.getMsg());
} }
LoginUser userInfo = userResult.getData(); LoginUser userInfo = userResult.getData();
SysUser user = userResult.getData().getSysUser(); SysUser user = userResult.getData().getSysUser();
if (UserStatus.DELETED.getCode().equals(user.getDelFlag())) if (UserStatus.DELETED.getCode().equals(user.getDelFlag())) {
{
recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "对不起,您的账号已被删除"); recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "对不起,您的账号已被删除");
throw new ServiceException("对不起,您的账号:" + username + " 已被删除"); throw new ServiceException("对不起,您的账号:" + username + " 已被删除");
} }
if (UserStatus.DISABLE.getCode().equals(user.getStatus())) if (UserStatus.DISABLE.getCode().equals(user.getStatus())) {
{
recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "用户已停用,请联系管理员"); recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "用户已停用,请联系管理员");
throw new ServiceException("对不起,您的账号:" + username + " 已停用"); throw new ServiceException("对不起,您的账号:" + username + " 已停用");
} }
@ -101,29 +91,24 @@ public class SysLoginService
return userInfo; return userInfo;
} }
public void logout(String loginName) public void logout(String loginName) {
{
recordLogService.recordLogininfor(loginName, Constants.LOGOUT, "退出成功"); recordLogService.recordLogininfor(loginName, Constants.LOGOUT, "退出成功");
} }
/** /**
* *
*/ */
public void register(String username, String password) public void register(String username, String password) {
{
// 用户名或密码为空 错误 // 用户名或密码为空 错误
if (StringUtils.isAnyBlank(username, password)) if (StringUtils.isAnyBlank(username, password)) {
{
throw new ServiceException("用户/密码必须填写"); throw new ServiceException("用户/密码必须填写");
} }
if (username.length() < UserConstants.USERNAME_MIN_LENGTH if (username.length() < UserConstants.USERNAME_MIN_LENGTH
|| username.length() > UserConstants.USERNAME_MAX_LENGTH) || username.length() > UserConstants.USERNAME_MAX_LENGTH) {
{
throw new ServiceException("账户长度必须在2到20个字符之间"); throw new ServiceException("账户长度必须在2到20个字符之间");
} }
if (password.length() < UserConstants.PASSWORD_MIN_LENGTH if (password.length() < UserConstants.PASSWORD_MIN_LENGTH
|| password.length() > UserConstants.PASSWORD_MAX_LENGTH) || password.length() > UserConstants.PASSWORD_MAX_LENGTH) {
{
throw new ServiceException("密码长度必须在5到20个字符之间"); throw new ServiceException("密码长度必须在5到20个字符之间");
} }
@ -134,8 +119,7 @@ public class SysLoginService
sysUser.setPassword(SecurityUtils.encryptPassword(password)); sysUser.setPassword(SecurityUtils.encryptPassword(password));
R<?> registerResult = remoteUserService.registerUserInfo(sysUser, SecurityConstants.INNER); R<?> registerResult = remoteUserService.registerUserInfo(sysUser, SecurityConstants.INNER);
if (R.FAIL == registerResult.getCode()) if (R.FAIL == registerResult.getCode()) {
{
throw new ServiceException(registerResult.getMsg()); throw new ServiceException(registerResult.getMsg());
} }
recordLogService.recordLogininfor(username, Constants.REGISTER, "注册成功"); recordLogService.recordLogininfor(username, Constants.REGISTER, "注册成功");

@ -15,8 +15,7 @@ import com.ruoyi.system.api.domain.SysLogininfor;
* @author ruoyi * @author ruoyi
*/ */
@Component @Component
public class SysRecordLogService public class SysRecordLogService {
{
@Autowired @Autowired
private RemoteLogService remoteLogService; private RemoteLogService remoteLogService;
@ -24,23 +23,18 @@ public class SysRecordLogService
* *
* *
* @param username * @param username
* @param status * @param status
* @param message * @param message
* @return
*/ */
public void recordLogininfor(String username, String status, String message) public void recordLogininfor(String username, String status, String message) {
{
SysLogininfor logininfor = new SysLogininfor(); SysLogininfor logininfor = new SysLogininfor();
logininfor.setUserName(username); logininfor.setUserName(username);
logininfor.setIpaddr(IpUtils.getIpAddr()); logininfor.setIpaddr(IpUtils.getIpAddr());
logininfor.setMsg(message); logininfor.setMsg(message);
// 日志状态 // 日志状态
if (StringUtils.equalsAny(status, Constants.LOGIN_SUCCESS, Constants.LOGOUT, Constants.REGISTER)) if (StringUtils.equalsAny(status, Constants.LOGIN_SUCCESS, Constants.LOGOUT, Constants.REGISTER)) {
{
logininfor.setStatus(Constants.LOGIN_SUCCESS_STATUS); logininfor.setStatus(Constants.LOGIN_SUCCESS_STATUS);
} } else if (Constants.LOGIN_FAIL.equals(status)) {
else if (Constants.LOGIN_FAIL.equals(status))
{
logininfor.setStatus(Constants.LOGIN_FAIL_STATUS); logininfor.setStatus(Constants.LOGIN_FAIL_STATUS);
} }
remoteLogService.saveLogininfor(logininfor, SecurityConstants.INNER); remoteLogService.saveLogininfor(logininfor, SecurityConstants.INNER);

@ -23,3 +23,5 @@ spring:
# 共享配置 # 共享配置
shared-configs: shared-configs:
- application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
# 指定分组
group: DEFAULT_GROUP #默认微服务组

@ -5,20 +5,19 @@ package com.ruoyi.common.core.constant;
* *
* @author ruoyi * @author ruoyi
*/ */
public class ServiceNameConstants public class ServiceNameConstants {
{
/** /**
* serviceid * serviceId
*/ */
public static final String AUTH_SERVICE = "ruoyi-auth"; public static final String AUTH_SERVICE = "ruoyi-auth";
/** /**
* serviceid * serviceId
*/ */
public static final String SYSTEM_SERVICE = "ruoyi-system"; public static final String SYSTEM_SERVICE = "ruoyi-system";
/** /**
* serviceid * serviceId
*/ */
public static final String FILE_SERVICE = "ruoyi-file"; public static final String FILE_SERVICE = "ruoyi-file";
} }

@ -23,6 +23,9 @@ spring:
# 共享配置 # 共享配置
shared-configs: shared-configs:
- application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
# 指定分组
# group: DEFAULT_GROUP #默认微服务组
group: GROUP_ALL_IN_1 #多模块集成在system模块里的模式
sentinel: sentinel:
# 取消控制台懒加载 # 取消控制台懒加载
eager: true eager: true

@ -2,6 +2,7 @@ package com.ruoyi.file;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import com.ruoyi.common.swagger.annotation.EnableCustomSwagger2; import com.ruoyi.common.swagger.annotation.EnableCustomSwagger2;
@ -10,6 +11,7 @@ import com.ruoyi.common.swagger.annotation.EnableCustomSwagger2;
* *
* @author ruoyi * @author ruoyi
*/ */
@ConditionalOnProperty(name = "spring.cloud.nacos.config.group", havingValue = "DEFAULT_GROUP", matchIfMissing = true)
@EnableCustomSwagger2 @EnableCustomSwagger2
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class }) @SpringBootApplication(exclude = {DataSourceAutoConfiguration.class })
public class RuoYiFileApplication public class RuoYiFileApplication

@ -23,3 +23,5 @@ spring:
# 共享配置 # 共享配置
shared-configs: shared-configs:
- application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
# 指定分组
group: DEFAULT_GROUP #默认微服务组

@ -23,3 +23,6 @@ spring:
# 共享配置 # 共享配置
shared-configs: shared-configs:
- application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
# 指定分组
# group: DEFAULT_GROUP #默认微服务组
group: GROUP_ALL_IN_1 #多模块集成在system模块里的模式

@ -5,12 +5,14 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
import com.ruoyi.common.security.annotation.EnableCustomConfig; import com.ruoyi.common.security.annotation.EnableCustomConfig;
import com.ruoyi.common.security.annotation.EnableRyFeignClients; import com.ruoyi.common.security.annotation.EnableRyFeignClients;
import com.ruoyi.common.swagger.annotation.EnableCustomSwagger2; import com.ruoyi.common.swagger.annotation.EnableCustomSwagger2;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
/** /**
* *
* *
* @author ruoyi * @author ruoyi
*/ */
@ConditionalOnProperty(name = "spring.cloud.nacos.config.group", havingValue = "DEFAULT_GROUP", matchIfMissing = true)
@EnableCustomConfig @EnableCustomConfig
@EnableCustomSwagger2 @EnableCustomSwagger2
@EnableRyFeignClients @EnableRyFeignClients

@ -23,3 +23,5 @@ spring:
# 共享配置 # 共享配置
shared-configs: shared-configs:
- application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
# 指定分组
group: DEFAULT_GROUP #默认微服务组

@ -88,6 +88,24 @@
<artifactId>ruoyi-common-swagger</artifactId> <artifactId>ruoyi-common-swagger</artifactId>
</dependency> </dependency>
<!-- =============================================================================== -->
<!-- 可选部署:合并鉴权模块 -->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-auth</artifactId>
</dependency>
<!-- 可选部署:合并文件模块 -->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-modules-file</artifactId>
</dependency>
<!-- 可选部署:合并定时任务模块 -->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-modules-job</artifactId>
</dependency>
</dependencies> </dependencies>
<build> <build>

@ -0,0 +1,25 @@
package com.ruoyi;
import com.alibaba.druid.spring.boot3.autoconfigure.DruidDataSourceAutoConfigure;
import com.ruoyi.common.security.annotation.EnableCustomConfig;
import com.ruoyi.common.security.annotation.EnableRyFeignClients;
import com.ruoyi.common.swagger.annotation.EnableCustomSwagger2;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
*
*
* @author Alan Scipio
* created on 2024/1/31
*/
@EnableCustomConfig
@EnableCustomSwagger2
@EnableRyFeignClients
@SpringBootApplication(exclude = {DruidDataSourceAutoConfigure.class})
public class SystemAllApplication {
public static void main(String[] args) {
SpringApplication.run(SystemAllApplication.class, args);
System.out.println("(♥◠‿◠)ノ゙ 系统模块(All-in-one模式)启动成功 ლ(´ڡ`ლ)゙");
}
}

@ -12,13 +12,13 @@ import com.ruoyi.common.swagger.annotation.EnableCustomSwagger2;
* *
* @author ruoyi * @author ruoyi
*/ */
@EnableCustomConfig //@EnableCustomConfig
@EnableCustomSwagger2 //@EnableCustomSwagger2
@EnableRyFeignClients //@EnableRyFeignClients
@SpringBootApplication(exclude = {DruidDataSourceAutoConfigure.class}) //@SpringBootApplication(exclude = {DruidDataSourceAutoConfigure.class})
public class RuoYiSystemApplication { public class RuoYiSystemApplication {
public static void main(String[] args) { public static void main(String[] args) {
SpringApplication.run(RuoYiSystemApplication.class, args); SpringApplication.run(RuoYiSystemApplication.class, args);
System.out.println("(♥◠‿◠)ノ゙ 系统模块启动成功 ლ(´ڡ`ლ)゙"); System.out.println("(♥◠‿◠)ノ゙ 系统模块(常规模式)启动成功 ლ(´ڡ`ლ)゙");
} }
} }

@ -7,6 +7,8 @@ spring:
application: application:
# 应用名称 # 应用名称
name: ruoyi-system name: ruoyi-system
main:
allow-bean-definition-overriding: true # All-in-one模式下必须
profiles: profiles:
# 环境配置 # 环境配置
active: dev active: dev
@ -23,3 +25,6 @@ spring:
# 共享配置 # 共享配置
shared-configs: shared-configs:
- application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
# 指定分组
# group: DEFAULT_GROUP #默认微服务组
group: GROUP_ALL_IN_1 #多模块集成在system模块里的模式

@ -23,3 +23,6 @@ spring:
# 共享配置 # 共享配置
shared-configs: shared-configs:
- application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
# 指定分组
# group: DEFAULT_GROUP #默认微服务组
group: GROUP_ALL_IN_1 #多模块集成在system模块里的模式

Loading…
Cancel
Save