目前的项目很少会采用单机架构了,一是因为单机性能有限,二是因为单机服务一旦故障整个系统就无法继续提供服务了。所以目前集群和分布式的架构使用得很广泛,主要就是为了解决上述两个问题,一个性能问题,一个故障问题,通过分布式架构解决性能(高并发)问题,通过集群架构解决故障服务(高可用)问题。
技术简介
Lombok通过简单注释来精简代码来达到消除冗长代码的目的
优点:提高编程效率、简洁代码、消除冗长代码、避免修改字段名忘记修改方法名
- 增加jar
- 下载idea的lombok插件
- Pojo中的get/set就可以用注解替换
Maven隔离
不同环境配置进行分离清除打包mvn clean package -Dmaven.test.skip=true -Pdev实际项目环境,环境之间的各种差异,maven环境隔离的配置,设置默认环境,验证-重新打包测试
Tomcat集群
能带来什么:1.提高性能、高可用,2.项目横向扩展能力(纵向扩展指提升服务器的性能)实现原理:通过Nginx负载均衡进行请求转发架构对比: 新问题:1.Session登录信息存储与读取,2.服务器定时任务并发解决方案:1.nginx ip hash policy 可以不改变现有技术架构,横向扩展(省事),但负载不平均,ip变化下无法服务。Tomcat单机部署多应用/多机部署多应用:单机配置多个tomcat重新解压两个tomcat取名1和2Tomcat1中8080Tomcat2中9090(为了区分将logo替换)要改三处9080、9009、9005防止乱码加入URIEncoding=”UTF-8”测试:启动tomcat1和tomcat2(此时不能同时启动)配置tomcat环境变量:2个tomcat配置6个修改tomcat2中的catalina.bat (windows)和startup.bat(如果不修改2启动不了)位置:bin\catalina.bat (windows)和startup.bat
- 先修改CATALINNA_BASE,bat和catalina.bat 中的
将CATALINNA_BASE全部替换成CATALINA_2_BASE
- 再替换CATALINNA_HOME
将CATALINNA_HOME全部替换成CATALINNA_2_HOME3.重新再启动tomcat1和tomcat2(可以同时启动)4.测试不同端口出现的logo
Nginx负载均衡
均衡策略轮询(默认):简单,但不考虑每台服务器能力权重:考虑到每台服务器能力(weight默认为1)Ip hash:同一个用户可以访问同一个服务器,但不平均Url hash(第三方):同一个服务访问同一个服务器,但url分配不平均Fair(第三方):按相应时间分配Nginx负载均衡可以将nginx页面重定向到tomcat上
Nginx+Tomcat集群
启动两个Tomcat执行startup.batTomcat2的logo替换修改系统的host:C:\Windows\system32\drivers\etc\hosts增加127.0.0.1 www.chs.comPing www.chs.com来验证host生效访问两个Tomcat的首页验证:Tomcat1——-localhost:8080/www.chs.com:8080Tomcat2——-localhost:9080/www.chs.com:9080启动Nginx(默认端口80)配置Nginx(一期完成):增加include vhost/*.conf;使用权重策略Weight默认是1开始验证负载均衡的集群:访问www.chs.com,可以发现访问的tomcat是不一样的(由图片区别开来)最后测试:重新启动Nginx,再次访问www.chs.com,一直刷新后可以出现不同tomcat服务
Redis
远程字典服务:REmote Dictionary ServerC编写的开源内存数据库,高性能的key-value的数据库,支持数据持久化Redis单实例 启动:redis -cli 关闭:redis -cli shutdown命令:info、ping、quit、save、dbsize、select、flushdb、flushall键命令:set del exists expire ttl type randomkeyTtl 剩余生存时间(-1未设置)Expire 设置倒计时(单点登录有用)Type 查看类型
Redis数据结构
Setex c 100 c 设置一个倒计时的(秒)Psetex d 10000 d(毫秒)Mset 设置多个 mget 拿到多个Setnx 可以判断是否存在Strlen 看长度Zadd 有序集合zCard 查看
单点登录
(Redis+cookie+jackson+filter)更新redis版本添加redispool测试连接数和时间增加Util单点登录问题1:实现过程,将sessionID保存到redis中Tomcat集群加入代码:打开两个idea,分别运行tomcat1和tomcat2运行后配置Nginx,进行反向代理,增加权重策略,输入域名可以看到两个不同tomcat的跳转但是存在redis中的用户sessionID是不一样的,这就意味着跳到不同服务器的相同用户,机器无法识别重启tomcat也会使ID更换解决,使用cookie,将sessionID存在一级域名上,登录成功后会产生新的ID存在login_token中。只要通过一级域名访问的登录后会存相同的tokenID值,之后就可以知道是一个用户了问题2:Cookie的过期时间问题,设置cookie的时间期限是30分钟,如何让用户在不退出且操作的情况下,系统不会自动退出解决:通过过滤器来进行实现,过滤.do结尾的请求,判断然后判断是否有用户,再重置session的时间 过滤器与拦截器的区别过滤器(Filter):它依赖于servlet容器。在实现上,基于函数回调,它可以对几乎所有请求进行过滤,但是缺点是一个过滤器实例只能在容器初始化时调用一次。使用过滤器的目的,是用来做一些过滤操作,获取我们想要获取的数据,比如:在Javaweb中,对传入的request、response提前过滤掉一些信息,或者提前设置一些参数,然后再传入servlet或者Controller进行业务逻辑操作。通常用的场景是:在过滤器中修改字符编码(CharacterEncodingFilter)、在过滤器中修改HttpServletRequest的一些参数(XSSFilter(自定义过滤器)),如:过滤低俗文字、危险字符等。拦截器(Interceptor):它依赖于web框架,在SpringMVC中就是依赖于SpringMVC框架。在实现上,基于Java的反射机制,属于面向切面编程(AOP)的一种运用,就是在service或者一个方法前,调用一个方法,或者在方法后,调用一个方法,比如动态代理就是拦截器的简单实现,在调用方法前打印出字符串(或者做其它业务逻辑的操作),也可以在调用方法后打印出字符串,甚至在抛出异常的时候做业务逻辑的操作。由于拦截器是基于web框架的调用,因此可以使用Spring的依赖注入(DI)进行一些业务操作,同时一个拦截器实例在一个controller生命周期之内可以多次调用。但是缺点是只能对controller请求进行拦截,对其他的一些比如直接访问静态资源的请求则没办法进行拦截处理。 架构的演进会驱动代码的演进,从登陆使用session获取用户到使用cookie加redis来存储用户的token,进而获取用户信息,然后解决tomcat集群问题,获取的token不同,不同的服务器如何来判断登陆人的信息。再到使用cookie计时器集群问题3:忘记密码修改密码的时候,存储的token在GUava中,集群服务器无法同时获得token,使得修改密码出错解决:将Guava改变为Redis,两个集群都会从Redis中找到token
Redis分布式
Redis 高可用方案:Redis SentinelRedis Sentinel 是 Redis 官方推荐的高可用性(HA)解决方案,这是生产环境中最实用也是最常用的方案。方案需要解决两个基本问题:如何提前判断各个节点(尤其是主节点)的运行健康状况?当主节点宕机的时候如何从多个从节点中选出一个作为新的主节点并实现自动切换?这时 Redis Sentinel 应运而生使用了 redis sentinel 之后客户端不再直接连接 redis 节点获取服务,而是使用 sentinel 代理获取 redis 服务,类似 Nginx 的代理模式。那么这里又有一个新问题,就是如果 sentinel 宕机了,那么客户端就找不到 redis 服务了,所以 sentinel 本身也是需要支持高可用。好在sentinel 本身也支持集群部署,并且各个 sentinel 之间支持自动监控,如此一来 redis 主从服务和 sentinel 服务都可以支持高可用。 集群与分布式区别集群是物理形态,分布式是一种工作方式简单说,分布式是以缩短单个任务的执行时间来提升效率的,而集群则是通过提高单位时间内执行的任务数来提升效率。例如:如果一个任务由10个子任务组成,每个子任务单独执行需1小时,则在一台服务器上执行改任务需10小时。采用分布式方案,提供10台服务器,每台服务器只负责处理一个子任务,不考虑子任务间的依赖关系,执行完这个任务只需一个小时。(这种工作模式的一个典型代表就是Hadoop的Map/Reduce分布式计算模型)而采用集群方案,同样提供10台服务器,每台服务器都能独立处理这个任务。假设有10个任务同时到达,10个服务器将同时工作,10小后,10个任务同时完成,这样,整身来看,还是1小时内完成一个任务!Redis的分布式算法原理 启动第二个redis-server redis.windows-service6380.confredis-cli.exe -h 127.0.0.1 -p 6380
Spring Session
对业务没有侵入假如当用户通过浏览器访问应用服务器,session信息中保存了用户的登录信息,并且session信息没有过期失,效那么用户就一直处于登录状态,可以做一些登录状态的业务操作!但是现在很多的服务器都采用分布式集群的方式进行部署,一个Web应用,可能部署在几台不同的服务器上,通过LVS或者Nginx等进行负载均衡(一般使用Nginx+Tomcat实现负载均衡)。此时来自同一用户的Http请求将有可能被分发到不同的web站点中去(如:第一次分配到A站点,第二次可能分配到B站点)。那么问题就来了,如何保证不同的web站点能够共享同一份session数据呢?假如用户在发起第一次请求时候访问了A站点,并在A站点的session中保存了登录信息,当用户第二次发起请求,通过负载均衡请求分配到B站点了,那么此时B站点能否获取用户保存的登录的信息呢?答案是不能的,因为上面说明,Session是存储在对应Web服务器的内存的,不能进行共享,此时Spring-session就出现了,来帮我们解决这个session共享的问题!简单点说就是请求http请求经过Filter职责链,根据配置信息过滤器将创建session的权利由tomcat交给了Spring-session中的SessionRepository,通过Spring-session创建会话,并保存到对应的地方。
Spring MVC全局异常
主要目的就是为了不让异常报错的各种代码出现在页面上
Spring MVC拦截器
Spring Schedule
定时关单处理一句话理解:作业调度,定时任务
Redis 分布式锁
Setnx 只有不存在的时候,才能setGetset 先get再setexpire有效期Del删除为什么要加入redis分布式锁?1、在使用spring schedule定时关订单的时候,很可能定时器在两个redis中同时启动或者同时关闭,会导致订单重复关闭的情况。通过加锁的方式来保证只有一个redis进行操作。2、当一个redis得到关闭订单的信息时,增加5秒锁,处理完毕后解锁。加锁可能出现的问题:当关闭订单信息加锁后出现服务器宕机或者重启的情况,会出现死锁的情况双重防死锁防死锁解决思路:记录锁的设置时间(5s)与进入锁到当前时(进入锁时间—-当前时间),当锁设置时间>阶段时间的时候,可以获取锁,否则旧锁还未失效,重新设置锁时间
Redisson
Redisson是架设在redis基础之上的一个java驻内存数据网络充分利用redis键值数据库提供的一系列优势原本作为单机多线程,降低分布式难度主要用于分布式锁
来源:CSDN
作者:Ares_song
链接:https://blog.csdn.net/Ares_song/article/details/104804204