百度网盘javascript
提取码:qhhv css
问题分析:电商和咱们平时app中,90% 以上都是数据读取操做,在海量数下,数据库最后可能成为高并发的瓶颈,所以减小数据库交互是首先须要考虑的事情。可是要区分静态数据和动态数据。长期不变的数据,好比商品详情,图片,介绍等适合作缓存,可是评论就不适合作缓存。html
查询一次数据库后,把商品详情,图片,介绍等放入redis,而后下次redis有的话直接从reids查询,避免再次查数据库。
具体切换到 step2-静态数据优化 分支java
git checkout step2-静态数据优化
安装redisnginx
docker pull redis; docker run -d --name redis1 -p 6379:6379 redis --requirepass "123456"
安装完redis,对应在yml中修改本身的redis配置,访问下面地址,查看redis,就会发现redis中缓存了商品相关信息,具体实现,查看代码,很简单。git
http://localhost:8080/good?gid=2000
页面静态化是指把动态页面,jsp,freemarker等为每个商品生成一个html静态页面。动态数据例如评论就在html页面用ajax异步获取。这样,就直接访问html避免了页面数据查询,解析的过程。web
总结:http://localhost/page/2000.html这里的流程
是首先去容器内部/usr/share/nginx/html/去找html文件,而后实际上是访问到了挂载在本地生成html的目录,而后html里面发起ajax请求去获取评论,实际是经过nginx把请求经过upstream转发到本地。ajax
--- nginx docker pull nginx; docker run -d --name nginx -p 80:80 -v /Users/along/websoft/nginx:/etc/nginx/conf.d -v /Users/along/Desktop/template:/usr/share/nginx/html nginx 上面启动脚本意思是:映射80端口,而后挂载配置文件目录和放html的目录到nginx里面 启动脚本和html位置在要和上面启动命令中的一致。 --- nginx 脚本 #由于容器内部须要访问到外部的接口,因此须要在容器内容用ip+端口访问本地接口 upstream seckill { server 192.168.5.3:8080; } server { listen 80; server_name localhost; #把接口转发到本地起的项目,个人是192.168.5.3:8080; location / { proxy_pass http://seckill; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } #页面转发地址是容器内部地址 location /page { index index.html; alias /usr/share/nginx/html/; } } 监听80端口,访问/放转发到本地接口,访问page的时候,定位到nginx的html放置目录,而后以前挂载过这个目录,就能访问到本机的挂载目录。
两种方案总结:redis
使用redis以前的通常作法是,查询数据库,若是剩余大于0,就抢到商品,并把剩余数量减一,并更新数据库。算法
int num = goodDao.selectRate(num) ; if(num>0){ //处理生成订单逻辑 num = num -1; //更新数据 }
可是很明显,查询数量和更新数量以前是有时差的,有的请求执行到了生成订单逻辑,东西抢到了,可是没来得及更新数据库,可是有的请求在这时获取了剩余数量,那么就会超卖。
选取redis由于它是单线程模型,内存存储,官网宣称支持10w qps。并且天生分布式支持。
逻辑流程
t_promotion_seckill
操做流程:
t_promotion_seckill
, 若是扫不到,请查看sql,修改数据的状态为0在抢购之后,每每会发起存数据库,支付等操做,可是很明显,以前的从redis中取商品,并添加中奖人到redis这个操做是很快的,可是订单入库,支付等操做是很慢的。假设处理取商品,存中奖人每秒能够处理1000,可是处理订单,支付等一秒处理100个,那么,若是是一连串操做,很明显,后面瓶颈,形成前面操做等待。严重的状况,因为支付过慢崩溃,致使前面一系列流程所有崩溃。
总而言之就是前台业务处理能力和后台业务能力不对称所致使的
由于能够分离业务,前台业务处理快,尽管处理,而后后面生成订单,支付等在mq中按本身能处理的量异步处理。
rabbitMQ是使用Erlang开发,也有本身的虚拟机,编译后处处运行,并且编写分布式应用简单。
exchange-order
的交换机,而且建立一个queue-order
的队列,把他们绑定docker pull rabbitmq; docker run -d -p 15672:15672 -p 5672:5672 -e RABBITMQ_DEFAULT_USER=admin -e RABBITMQ_DEFAULT_PASS=admin --name rabbitmq rabbitmq
用admin和admin打开loaclhost:5672.
LoadBalance:负载均衡,把任务分配到多个服务器上进行处理,进而提升效率,缩短执行时间。
当一台机器性能到达极限的状况下,横向拓展机器的架构是很是好的,能在不改动代码的状况下成倍的提高效率。
step5-nginx负载均衡
分支,其中新增了一个 LBController
测试负载均衡的控制器。localhost/LB
这个地址,会发现,请求到不一样的端口。我比较喜欢使用权重策略,基本都是根据服务器性能来分配。
#nginx.conf,配置中的server是本地ip,使用权重的策略 upstream lb { #least_conn ; 最少链接 #ip hash ; ip策略 #权重 server 192.168.5.3:8081 weight=4; server 192.168.5.3:8082 weight=1; server 192.168.5.3:8083 weight=2; } location / { proxy_pass http://lb; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } nginx在docker中的启动脚本和上面相同。
在部署的多个服务中若是使用session传递数据,可能存在获取不到的状况,由于假设在8081中执行登录,session只会存在8081这个服务中,可是下次请求分发到8082或者8083就获取不到session了。
step6-解决各个服务间session不一样步问题
分支localhost/login?u=along
,而后在屡次请求localhost/check
发现,有时候能获取到session,有时不能获取到。像js,css,图片,字体等静态资源,他们都是一个个的url,每次访问的tamcat都会进行url解析和绑定。可是上线之后,它们几乎是不会修改的。因此在高并发的状况下很浪费资源。
nginx区分静态资源和接口url,把url接口送日后端服务器处理,静态资源在nginx端缓存处理。
主要是修改nginx的配置,配置以下
#在nginx容器内的/home下面定义缓存文件夹。并设定2层目录,缓存大小以及过时时间。 proxy_temp_path /home/nginx-temp; proxy_cache_path /home/nginx-cache levels=1:2 keys_zone=lb-cache:100m inactive=7d max_size=20g; upstream lb { #least_conn ; 最少链接 #ip hash ; ip策略 #权重 server 192.168.5.3:8081 weight=4; server 192.168.5.3:8082 weight=1; server 192.168.5.3:8083 weight=2; } #用正则匹配静态资源,~*是不区分大小写。 location ~* \.(gif|jpg|css|png|js|woff|html)(.*){ proxy_pass http://lb; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; #使用上面定义的缓存地址 proxy_cache lb-cache; proxy_cache_valid 200 302 24h; proxy_cache_valid 301 5d; proxy_cache_valid any 5m; expires 90d; } location / { proxy_pass http://lb; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; }
而后重启nginx就行了,访问之后,进入容器
docker exec -it nginx /bin/bash cd /home/nginx-cache 若是上面的文件夹出现了两层目录的静态文件,说明设置成功。
当静态资源被压缩后,下降了后端tomcat的压力,可是在实际开发过程当中,大量的压力不在于处理速度,而是在于带宽。带宽决定了下载的总速度,在总速度不变的状况下,资源传到浏览器的大小约小越好。越快下载完资源,卡顿的越少。
带宽是网络中某一点到另外一点所能经过的"最高数据率",也就是瞬时最高的下载速度。
关于带宽和下载速度:首先了解一下存储的单位换算
1M = 10^6; bits换成B除以8,B换成kb除以1024 1M bits/s = 1000000bits/s = 125000 B/s ≈ 128kb/s
nginx将静态资源打包成gzip传给浏览器,而后浏览器解压缩gizp(这一步浏览器自动完成)获取到资源文件。最少能较少30%内存,最多减小80%的内存损耗。
#打开gzip配置 gzip on; gzip_min_length 1k; gzip_types text/plain application/javascript text/css application/x-javascript font/woff; #禁止IE 1-6 gzip_disable "MSIE [1-6]\."; gzip_buffers 32 4k; #压缩级别1-9,选1就好了,大小差异不大 gzip_comp_level 1; #在nginx容器内的/home下面定义缓存文件夹。并设定2层目录,缓存大小以及过时时间。 proxy_temp_path /home/nginx-temp; proxy_cache_path /home/nginx-cache levels=1:2 keys_zone=lb-cache:100m inactive=7d max_size=20g; upstream lb { #least_conn ; 最少链接 #ip hash ; ip策略 #权重 server 192.168.5.3:8081 weight=4; server 192.168.5.3:8082 weight=1; server 192.168.5.3:8083 weight=2; } #用正则匹配静态资源,~*是不区分大小写。 location ~* \.(gif|jpg|css|png|js|woff|html)(.*){ proxy_pass http://lb; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; #使用上面定义的缓存地址 proxy_cache lb-cache; proxy_cache_valid 200 302 24h; proxy_cache_valid 301 5d; proxy_cache_valid any 5m; expires 90d; } location / { proxy_pass http://lb; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; }
在docker重启nginx。访问页面,当看到浏览器,检查看到css,js等的response header中,编码为gzip。就说明设置成功了。
对静态文件完成了gzip压缩,可是对图片等已经被压缩过的资源gzip传输效果并很差,因此对图片的带宽消问题并无解决。
图片能够考虑使用第三方cdn解决带宽问题。
cdn全称Content dekivery network,就是内容分发网络。
例如中国很大,北京和深圳就隔者2000多千米,若是北京访问深圳的网络,必然延时很高。cnd就是把内容放在一台中心服务器上,而后各地有不少节点服务器,中心服务器会把内容同步到各地的节点服务器,而后就进访问资源。
能够买阿里云,腾讯云,七牛的cdn服务。
主要流程是买服务,下载客户端,把图片等资源上传到客户端,自动同步,而后为oss配置cdn,进行域名解析。就能经过域名访问到图片,最后就去修改项目中静态资源的路径。
有些人会恶意一直访问网站,甚至用脚本去刷页面。
因此在必定时间内只容许一个用户访问固定的次数,一旦超过了就不容许访问。
会有人用爬虫,爬网站,利用超连接分析内容,提取网站的重要信息,不只拷贝走了数据,并且,还很是消耗服务器资源。
step7-流量防刷与反爬虫
分支localhost/lb
,并屡次刷新终于写完啦。这篇文章主要是对代码和网络等几个层面作了优化,主要使用了nginx,redis,rabbitMQ等热门工具,但愿对各位有帮助,若是有问题,欢迎指正,一块儿讨论。