净菜加工系统后台集群部署方案落地实现
@[toc]
净菜加工系统后台集群部署
前言
为什么要使用集群部署
当我们单机部署的时候,前端项目是打包在后台项目中的,通过Spring MVC来访问静态资源的形式来访问页面
劣势一:
使用
Tomcat来作为静态资源的服务器,同时使用Tomcat来作为后台Servlet的容器,无疑是增大了Tomcat的压力劣势二:
单机部署如果项目挂了,或者线程被占用满了,都会成为瓶颈,在生成环境中,至少应该保证项目能够集群部署提高容错率,可用性
集群部署带来的问题
问题一:
前端打包进后台部署,前端后端都是相同的
host,不存在跨域问题,如果前后端分离部署,必然前端服务和后端服务的ip和port不一致导致存在跨域问题问题二:
后台集群部署后,保存用户登录的
Session信息不能在多个服务中共享,存在Session共享问题问题三:
项目中有使用到
WebSocket,用户与后端服务建立的WebSocket长链接只能存在于一个后台服务中,问题是后台服务既不能像Session一样共享长链接,长链接也不能持久化
集群部署落地实现
解决方案
问题一:跨域
跨域问题我们在后端集体配置,后端作为最后的请求响应方,应该统一允许跨域请求的响应
问题二:Session共享
Session共享问题使用Spring Session框架配合Redis将Session统一管理到Redis中,所有的后台读取Session都从Redis中读取实现Session共享
问题三:分布式WebSocket
使用消息队列来驱动WebSocket推送消息,方案落地详细说明
方案落地
跨域
SpringBoot可以很方便的配置全局跨域
先添加一个处理跨域的请求过滤器
CorsFilter/**添加跨域支持
*/
@Configuration
public class GlobalCorsConfiguration {@Bean
public CorsFilter corsFilter() {CorsConfiguration corsConfiguration = new CorsConfiguration(); // 允许携带Cookies corsConfiguration.setAllowCredentials(true); // 允许的请求源,允许哪些来源的host跨域 // TODO 为了安全,此处后期修改成前端的host corsConfiguration.addAllowedOrigin("*"); // 跨域带上所有的header信息 corsConfiguration.addAllowedHeader("*"); // 允许所有的请求类型跨域(GET/POST/DELETE/PUT...) corsConfiguration.addAllowedMethod("*"); // 如果想要在跨域的同时新增自定义的请求头 // corsConfiguration.addExposedHeader("head1"); // corsConfiguration.addExposedHeader("cookies"); UrlBasedCorsConfigurationSource urlBasedCorsConfigurationSource = new UrlBasedCorsConfigurationSource(); // 所有的请求都会经过该过滤器 urlBasedCorsConfigurationSource.registerCorsConfiguration("/**", corsConfiguration); return new CorsFilter(urlBasedCorsConfigurationSource);}
}
如果项目使用了
Spring Security需要添加Spring Security对跨域的支持@Configuration public class WebMvcSecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http .csrf() .disable() // 添加跨域支持 .cors() .and() .authorizeRequests() //处理跨域请求中的Preflight请求,放行option类型的请求 .requestMatchers(CorsUtils::isPreFlightRequest).permitAll() ... } }别忘了对前端的请求框架
axios进行配置// 跨域允许携带cookie axios.defaults.withCredentials = true
Session共享
Spring Session框架集成Redis后默认将系统Session管理放在了Redis中,无需过多配置
首先整合
Redis和Spring Session引入依赖,SpringBoot对spring-session-data-redis有默认的版本约束
<dependency> <groupId>org.springframework.session</groupId> <artifactId>spring-session-data-redis</artifactId> </dependency>剩下都是配置
Redis的工作本文侧重点不在
Redis,所以此处省略,Redis整合好之后直接测试,登录系统后使用Redis图形化工具查看Redis中的数据,就会有Session信息保存了进来
消息驱动WebSocket
当需要服务端通过WebSocket给客户端发送消息时,由于客户端只与其中一台单机服务器建立了长链接,所以无法锁定到具体的某一台单机服务器调用WebSocket发消息给客户端,所以使用消息队列来发送一个广播,广播到每一台服务器上,然后服务器各自查看自己是否与客户端建立了长链接,如果建立,则发送WebSocket通知,反之不处理
使用Nginx对后台服务负载均衡
传递请求域,否则后台无法拿到域名中的公司编号
proxy_set_header Host $host;