前言:在这个知识分享的爆炸时代,鉴于java生态的完整和繁荣,各类框架、中间件和工具包供咱们使用。连新培训出来的人都知道ssm,微服务、集群、多线程、队列、高并发等技术,技术的间隔性正变得愈来愈小,仿佛咱们只须要循序渐进的去使用别人说的框架等技术就能够解决问题.若是刨除redis、rabbitmq、kafka、dubbo、springcloud这些具体的技术框架,你有没有静下心来真正思考过架构是什么呢?这些框架是到底是扮演怎么样的角色?若是让你给架构下一个定义,你会选择如何去描述架构呢?前端
背景: 从业快4年.我记得在我刚从业的时候,当时流行的框架是spring、struts二、hibernate,前端使用的是jsp,业务也不是那么复杂,整个项目并发量并不大,QPS都不会超过5,当时的作法全部的前端和后端放在一块儿部署,打成war包直接部署到centos上的tomcat上就能够运行了,这样彻底能够承载实际生产环境的请求量,问题也不大。后来当我换了一家公司,公司采用dubbo微服务化,全部的业务均被划分红了一个个服务来提供给接口调用,当时的业务场景也比之前的复杂,采用23台服务器分开部署,容纳的线上负载大概在几百万左右.服务进行修改逻辑不再用像之前那么麻烦须要把整个项目从新打包再部署了.以后就在微服务的路上走的更远了,全部的服务独立部署,打包成镜像文件成为docker实例,独立部署在docker的服务器上,结合git,部署、运维、开发的效率获得了迅速提高java
目录 nginx
一:架构究竟是什么git
二:经常使用的架构技术web
三:安全性问题redis
四: 架构设计的误区算法
五:总结spring
一:架构究竟是什么sql
架构究竟是什么?首先来看一下维基百科对架构的解释:docker
软件架构:是一个系统的草图。软件架构描述的对象是直接构成系统的抽象组件。各个组件之间的链接则明确和相对细致地描述组件之间的通信。在实现阶段,这些抽象组件被细化为实际的组件,好比具体某个类或者对像。
软件架构师:软件架构师定义和设计软件的模块化,模块之间的交互,用户界面风格,对外接口方法,创新的设计特性,以及高层事物的对象操做、逻辑和流程
按照维基百科的解释:软件架构实则是各个组件的互相搭配和组件之间的相互配合,是抽象的高层事务的的逻辑流程。简单来讲架构就是各个系统组件如何通信、协调、以及控制操做的逻辑。能够类比人体的结构来举个简单的例子来理解就是:人体是由心肝脾肺胃、耳鼻嘴等多个重要器官组成,各个器官各司其职,它们之间相互配合共同维持人的正常生活。这里的心、胃等就是整我的体架构的组件,血液就是数据,血管就是传输数据的媒介,人的皮肤和长相就是用户的界面风格,逻辑组织就是食物要首先进入胃去消化而后才会进入大肠,而不是进入肾脏。按照这个解释,咱们使用的kafka、redis、ssm、rabbitmq、xxljob等都是组件,这些组件各有各的做用,各自承担本身的责任去共同完成整个系统的高效流转.
二:经常使用的架构技术
2.1:分布式
分布式:将同一套业务代码按照业务功能或者自定义的维度拆分不一样的子系统,各个系统分开部署,每一个子系统叫作服务,每一个服务之间通常经过rpc或者webservice来调用
2.1.1: 分布式的优势
分布式的好处就是解耦了原系统,从而便于运维部署和水平扩展,提供软件的伸缩性,甚至服务能够经过不一样的语言来实现.各个模块交给不一样的人员去开发,每一个人各司其职,出现问题也能够快速定位
2.1.1:分布式的缺点
分布式也并非毫完好点的,存在如下的问题:
①:服务调用经过网络来调用,通常微服务之间使用rpc来调用的,而rpc的底层就是TCP协议,若是网络故障或者延迟高一点,那么服务调用就有出现超时的可能性,好比dubbo的话会出现RpcException
②:分布式在业务体量比较小或者粒度划分的状况下就是一种灾难式开发,开发和运维的成本都会直线上升
③:分布式的数据一致性和事务比较难以保障,业务目前使用最多的是两阶段提交2pc,须要本地事务和远程事务综合提交,性能比较差
④:分布式session的维护在单体工程中是不须要考虑session的安全性的,而在分布式环境中就必须考虑如何去维护session的一致
⑤:分布式事务问题:分布式下如何保证各个服务的数据一致性也是一种挑战,当程序出现异常崩溃的时候可以保证各个服务可以正常回滚是很重要的。
分布式最多见的技术:分布式缓存、分布式存储、分布式计算、分布式静态资源
2.2:集群
集群:同一套代码部署在多个服务器上,而多个服务器能够提供更多的cpu、内存、硬盘等资源,从而提高整理的处理请求能力。集群的每一个服务器叫作节点,每一个节点提供的是相同的服务,节点的关系只是一种简单的复制,具体是哪一个节点处理,则是根据负载均衡策略来决定;在网站的处理能力出现下滑的时候,简单的在集群中增长服务器台数就能够显著增长总体的数据量处理能力(不过存在上限);
原理很简单:所谓众人拾柴火焰高,多台服务器一块儿聚合处理数据量和并发访问的能力确定比单台服务器要高不少;在遇到请求处理的瓶颈时候,能够经过简单的增长服务器台数来提升并行处理的能力,不过须要注意的是增长服务器台数在出现大于某个数量以后性能会停滞不前。
2.3:缓存
缓存是提升软件的性能第一手段,最有效和最具表明性的方法,缓存分为单机缓存和分布式缓存。最多见的分布式缓存技术为redis、memorycache等,单机缓存好比hashmap、concurrentHashmap、guava等。单机缓存的承载容量有限,而分布式缓存的伸缩性和的存储容量会比较可观,就算缓存的空间不足了,也能够经过增长服务器来扩展。
缓存最显著的做用有两个:①加快数据的访问速度②分担后端的数据访问和存储的负载能力,保护数据库
使用缓存须要注意如下几点:
①:缓存雪崩
缓存雪崩指的是全部的缓存在统一时间所有失效,致使大量的请求直接涌入数据库,数据库被击垮。
解决缓存雪崩的方法:缓存过时值在必定的基础上设置随机值
②:缓存击穿
缓存击穿是指某些热点key在某一时间所有失效了,致使大量的请求涌入后台DB数据库
解决缓存击穿的方法:热点数据设置永不过时
③:缓存穿透
一直请求不存在的数据,最终走的仍是数据库就是缓存穿透
解决缓存穿透的方法:采用布隆过滤器(bloomFilter),布隆过滤会有必定的偏差,可是能够晒选出必定不存在的数据,缺点是没法断定某个key是否肯定存在。
2.4:队列
试想这样一个的高请求量场景:各大电商的双11,在双11的那一刻,有大量订单涌入,后端会接受请求,而后写入数据库,等待数据库的返回.若是请求量很是大的话,数据库读写IO就会阻塞,那么程序就会出现卡死,数据库崩溃等问题
若是采用队列的话,将下单请求发送到队列中,而后马上返回(能够按照业务决定,好比返回处理中,等到真正成功再通知用户),这样就不须要等待后端必须返回成功。消费端能够按照请求的顺序平滑的去消费,缓解了高峰的请求,而且实现了请求下单和实现下单的解耦。从如下图能够看出使用队列之后处理起来比较平滑~
2.5:多线程
多线程真正的意义有两个①提升cpu的利用率 ②:加快程序执行效率,目前已是多核的时代,服务器六核、八核家常便饭,在多核的cpu中若是使用单线程那么无疑是对多核cpu的浪费,多线程可以有效提升cpu利用的效率,多个任务分给多个cpu去处理,能够实现真正的并行处理。若是在单核cpu中,只是cpu在不停的切换cpu时间。假设咱们有十个表格的数据须要分析处理(计算密集型),采用单线程须要一个个的轮询表格,而多线程在合理分配线程数的状况下就能够同时处理,提升开发的效率
2.6:限流
限流是面对高并发的利器之一,例如秒杀场景:在大量的请求涌入后台,QPS高达几十万,若是不能作到有效控制就可能致使请求击垮数据库,DB基本上是一个网站的命脉。缓存、队列、限流等方式的本质其实都是为了保护DB。限流的简单理解其实就是过滤掉无效的请求,将请求限制在一个能够控制的范围内,最多见的限流有如下方式:
①: Redis限流
Redis限流的基本思路是采用redis的key过时策略,将业务id和业务值放入到redis中设置必定的过时时间,等请求再次进入的时候,若是能从redis获取到值,那么我就由于是重复性请求。Redis过滤限流是最基础的限流手段,适用于过滤同一个用户请求的场景
②:令牌桶算法
令牌桶算法的思路是在必定的时间内生成以固定的速度生成有限个令牌数量放入桶中,全部的请求首先从令牌桶中去尝试获取令牌,若是能获取到就能够继续执行,不然请求就会被抛弃。Google开源的guava中有RateLimter能够实现单机限流,令牌桶算法是限流很是有效的手段,
③: 漏桶算法
漏桶算法的基本原理是将请求直接存放在一个漏斗中,请求过多的话,那么就会漏斗就会溢出,溢出的请求则会被拒绝服务。漏桶算法能够控制端口的流量输出速率,平滑请求的突发流量,实现流量整形.
由于漏桶算法的漏出速率是有效的,所以漏桶算法相比于令牌桶算法有一个显著的缺点是没法应对突发性的流量.可令牌桶算法是能够的
④: 滑动窗口
http为了控制流量的速率采用的方法就是滑动窗口机制。若是要分布式限流,可采用阿里的Sentinel框架,其基本原理是滑动窗口机制,利用Entry映射资源来平滑的限流
此外还有nginx限流,好比使用参数来限制某一个ip的在时间范围内的访问频率。客户端限流:发起请求按钮点击后,在后面的几秒内(由业务决定)设置为disabled,这一操做步骤虽然很小,可是带来的限流做用很可观
2.7:服务降级和熔断
不少人会忽视这个问题,对本身设计出来的架构盲目自信,认为不可能出问题。而事实上,一旦随着微服务和分布式架构的持续推动,服务器会愈来愈多,宕机的几率和可能性会逐步提高,虽然出现宕机的可能性基本上很渺茫,不过也应该作好服务降级和熔断的准备,以防止那万分之一的几率宕机。假设有1000台服务器发生宕机的几率是0.001%,就由于存在0.001%的几率会致使咱们的服务并不是100%高可用。
服务的降级和熔断通常采用的是netfly(没错,就是那个美剧巨头公司)出的hystrix,能够实现服务熔断和降级
三:安全性问题
安全性的问题老是不被重视,其实安全的问题要比咱们想像的要严重的多.大公司每时每刻都会有不一样程度被攻击者发起攻击,一旦被黑客获取到数据库信息,那么将会有丢失用户信息、服务器被植入木马病毒、服务瘫痪等不容小觑的危险
3.1 sql注入
sql注入是目前全部方式中最频繁也是最严重的攻击手段,sql注入若是被居心叵测的黑客攻击极可能整个数据库都会被删除掉,其情节和结果十分恶劣。防止sql注入的有效方式就是
采用jdbc提供的preparementStatement进行预编译,它能有效保证sql的总体结构不会被破坏,万一被sql攻击也能够在预编译阶段失败,而不会执行成功
3.2 跨域攻击
与主站的域名、端口、协议不一致性的请求均可以理解为跨域访问,浏览器有同源策略:浏览器会限制来自于不一样源的documet和脚本对当前的document读取或设置部分属性,可是好比src\form表单提交\< img >\< iframe >\< link >是没有跨域限制的。
csrf攻击:登录网站A,获取到了网站A的cookie用户信息,而后点击了一个恶意网站外链B,网站B能够利用csrf漏洞模拟A网站的用户信息去请求A的某些敏感接口,好比转帐、发送消息、邮件、获取部分信息、发起恶意代码等。
如何防止csrf攻击:①接口请求加上随机的token值或者token约束的规则,或者是有时效性的token码。这样的话,外链去访问接口在拦截器中验证token是否有效,②在http的头部加入自定义参数:放到 HTTP 头中自定义的属性里。经过 Ajax,能够一次性给全部该类请求加上 csrftoken 这个 HTTP 头属性,并把 token 值放入其中
③减小使用get提交,get提交会下降门槛
3.3:XSS攻击
xss攻击指的是攻击者对包含有漏洞的服务器注入js代码,会诱使受害者打开攻击的服务器URL,其中里面的URL会包含一些恶意代码,好比植入病毒、添加广告片断代码、篡改接口信息等。
预防xss攻击的方法:对于用户提交的内容,须要过滤任何有执行能力的脚本或者影响页面的CSS,
四: 架构设计的误区
4.1:为了高大上而设计出复杂的架构
试想若是在业务体量不是特色大的状况下,若是一味的追求时髦,追求新颖,采用分布式微服务架构,那么将会增长业务开发的难度,为了维护大量的微服务而多出不少成本。好的架构必定是适应于自身的业务发展的,而高于业务的,它具备顺应业务发展的前瞻性。
4.3:用技术能够解决一切问题
企图用技术解决一切问题,认为技术是一切的解决之道,是万能的,其实有的时候技术解决不了的问题能够用从业务角度来考虑解决。好比以前楼主作个售票系统,主要是卖某个知名景点的票的业务。后期上线后发现不少人买了不少特价免费票,特价票是针对导游带领的团员的,每一个导游天天只能买一张特价免费票和一张半价票,以后看数据发现了不少导游配了两张票,而后那张半价票被退掉,只剩下一张免费票被刷了。技术总监就决定查这部分数据是怎么回事?结果发现部分人利用导游证这个特惠故意购买无价票,这个问题如何从技术上解决呢?若是不容许导游买特惠票不合理,不容许退票也不合理。技术上貌似没有好的手段去杜绝这个问题,只能从线下去处理。
五:总结
本篇文章的主要概略图我总结了一下,大概以下,其中包括分布式、集群、缓存、微服务、队列等。架构的话题弥足长远和复杂,不是一篇简单的文章能描述清楚的。若是要讲明白,估计得写个连载了。本篇文章只是提纲挈领如下,说实话也是走马观花,但愿能起到抛砖引玉的效果,不过在工做中思考、在实践中总结学习,是有助于提升咱们的内功心法的。
最后:若是对学习java有兴趣能够加入群:618626589.本群不一样于其余的垃圾群,旨在打造绝无培训广告、无闲聊扯淡、无注水斗图的纯技术交流群,群里天天会分享有价值的问题~目前已分享200多道,欢迎各位技术er随时加入