[Java复习]架构部署 超时重试 幂等防重
画一下你们系统的整体架构图,说说各个服务在生产环境怎么部署的?
核心:服务框架、注册中心、网关
即使你没有用很多微服务架构里的东西,只要有上述三个东西,配合上写一些文档,接口文档,分布式系统架构,其实就出来了,很多中小型公司,一个小型技术团队,后端开发工程师总共就10多个人。
常见生产实践问题:
关注分布式系统一些生产实践的问题,应对你们公司的流量,各个服务、网关、注册中心,都是如何部署的?
部署几台机器,每台机器的配置是什么,每天整体的流量有多少,高峰期的请求量有多少,你的整体系统是否抗住了?
各个服务之间的超时、重试、幂等性?
中小型系统,拆分10-20个微服务。大型互联网公司,一般几百个,几千个微服务。
中小型,一般2-3台机器足够,把服务上线,服务发现优化到极致。
服务上线:注册表多级缓存同步至1秒,拉取频率降低至1秒。
服务心跳:1秒报1次。
故障发现:1秒检查一次,2,3秒没有认为没有故障等。
服务注册中心没有压力,服务注册中心部署2台机器,每台4C8G,高可用,每秒轻松几百请求,甚至上千。前提是数据库SQL别写的太烂。
网关机器配置稍微高一些,4C8G,一台扛每秒几百个请求,部署3~4台,保证每台网关机器压力较小,进一步保证可靠性。
为什么网关Zuul之前还要配置Nginx?
Nginx反向代理,软负载,把请求均匀负载到多台Zuul的机器上。LVS和Nginx处于不同的负载维度,主要是运维工程师负责管理。
数据库,MYSQL,16C32G,物理机最佳,平时扛每秒几百请求,高峰期最多每秒扛三四千请求。
扛几千请求时机器会负载很高,CPU,IO,网络负载很高。DBA在优化一下。
你们系统每天有多大访问量?每个服务高峰QPS多少?压测过服务最大QPS吗?
每天服务多少请求量,高峰每秒qps,在代码里稍微加一些metrics代码,对自己运行过程中各种请求量,每秒请求量,成功次数,失败次数,在内存里直接做一些计数。
在负责的核心服务里,核心接口,开发一个简单的metric统计机制,AtomicLong,保证原则性,并发数据统计准确。
每个接口被调用时,可以对每个接口每分钟做一个metric统计,每个接口每天统计计数。
再通过Log4j, logback等日志组件,把次数直接打印到日志文件,统计出高峰期每秒系统被访问的次数,每条每个接口访问量。
响应延时:
计算一下每个接口从请求到执行完毕,需要耗费多长时间,算一下每个接口平均的请求延时,
TP99,TP95,TP90,TP50,TP99,99%的请求耗费的时间在100ms以内,但是1%的请求可能耗费的时间在100ms以上
TP99 = 100ms TP95 = 50ms,95%的请求耗费的时间多在50ms以内,但是5%的请求耗费的时间在50ms以上
压测工具,java压测工具,开源的可以用的,模拟出来同时有多少用户发起多少请求,每秒发起1000请求能抗住吗?每秒钟发起2000请求能抗住吗?
假设你的系统每秒钟最多抗800请求,如果你的压测工具每秒发起了1000个请求,此时会发现最多只有800个请求同时可以被处理,
剩余200个请求需要进行排队被阻塞住了,表示你这个系统每秒钟最多抗800个请求。
如果系统访问量比现在增加10倍,你们考虑过系统的扩容方案吗?
网关直接多部署10倍的机器即可,前面的Nginx做会负载均衡,把流量均匀分发给各个网关机器。
服务扩容,都很简单的,多加机器,部署启动,自动注册到注册中心去,此时其他服务会自动感知到你的服务多加了一些机器。
服务实例变多了10倍,此时几十个服务实例,几百个服务实例,对eureka机器会造成每秒几百请求,没问题,eureka机器,8核16G的配置,单机抗上千请求,很轻松。
数据库本来是每秒几百请求,10倍,每秒高峰期是三四千请求,横向扩容很麻烦,
此时可以考虑给单个数据库部署的机器提高配置,32核128G高配物理机,每秒钟抗几千请求问题不大。
总结: 最基本的操作就是扩容。
网关:横向加机器。
注册中心:纵向升配置。
数据库:纵向升配置。
当然还有很多其他专门针对分布式,高并发的优化和操作,不过加机器都是最简单直接的。
你们生产环境的服务是怎么配置超时和重试参数的?为什么要这样配置?
背景:Spring Cloud生产优化,系统第一次启动的时候,调用请求经常出现timeout。
原因:每个服务第一次被请求的时候,他会去初始化一个Ribbon的组件,初始化这些组件需要耗费一定的时间,所以很容易会导致超时。
解决方案:让每个服务启动的时候就直接初始化Ribbon相关的组件,避免第一次请求的时候初始化。
ribbon:
eager-load:
enabled: true zuul:
ribbon:
eager-load:
enabled: true feign:
hystrix:
enabled: false
线上的服务,每个服务部署上线的时候,一般来说都需要配置相关的超时时间还有重试次数
订单服务 -> 积分服务、库存服务、仓促服务
订单服务对于其他服务的调用,一般来说限制在多长时间就必须认为是超时了,如果超时之后如何进行重试
积分服务部署了两台机器,机器1和机器2
订单服务在一次请求积分服务的机器1的时候,超过1秒钟,超时了;此时需要进行重试,对积分服务当前的这台机器1重试几次?如果说机器1不行,是否可以重试一下积分服务的机器2?
ribbon:
ConnectTimeout: 3000
ReadTimeout: 3000
OkToRetryOnAllOperations: true
MaxAutoRetries: 1
MaxAutoRetriesNextServer: 1
中小型的系统,没必要直接开启hystrix,资源隔离、熔断、降级,如果你没有设计好一整套系统高可用的方案。
增加重试机制依赖:
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
</dependency>
如果出现服务请求重试,会不会出现类似重复下单的问题?
可能会。
订单服务 -> 创建订单 -> 库存服务 -> 扣减库存 -> wms服务 -> 通知发货 -> 积分服务 -> 增加积分
场景:
订单服务调用库存服务的时候,因为网络抖动,请求超时了,超过了秒钟,此时订单服务会重试,再次调用一下库存服务,发送一模一样的请求过去。
比如说,订单服务第一次请求库存服务,库存服务其实是把扣减库存的业务逻辑执行成功了,
只不过网络问题,导致响应迟迟没有返回给订单服务,可能在1.2s之后返回了响应给订单服务。
订单服务就认为请求超时了,他就再次发送了一个一模一样的请求给库存服务,库存服务可能会再次对库存进行扣减。
对于核心接口的防重幂等性,你们是怎么设计的?怎么防止重复下单问题?
常见方案:
1. 数据库唯一索引
2. 基于Redis实现幂等性防重
核心接口,幂等性都是自己保证,对应Create操作,通过DB唯一索引来保证;对于Update操作,建议在核心接口基于业务逻辑,配合Redis,来保证幂等性。
比如库存,定制化的针对接口开发幂等性的机制,比如说一旦库存扣减成功之后,就立马要写一条数据到redis里去,order_id_11356_stock_deduct,写入redis中,如果写入成功,就说明之前这个订单的库存扣减,没人执行过。
但是如果此时有一些重试的请求过来了,调用了你的库存扣减接口,他同时也进行了库存的扣减,但是他用同样的一个key,order_id_11356_stock_deduct,写入redis中,此时会发现已经有人写过key,key已经存在了。
此时你就应该直接对刚才的库存扣减逻辑做一个反向的回滚逻辑,
update product_stock set stock = stock - 100,update product_stock set stock = stock + 100,反向逻辑,回滚自己,避免重复扣减库存。
参考资料:
21天互联网Java进阶面试训练营(分布式篇)-- 中华石杉
[Java复习]架构部署 超时重试 幂等防重的更多相关文章
- dubbo超时重试和异常处理
dubbo超时重试和异常处理 dubbo超时重试和异常处理 参考: https://www.cnblogs.com/ASPNET2008/p/7292472.html https://www.tuic ...
- Java Web架构总结
转载至:http://www.cnblogs.com/wuxl360/p/7489763.html 初始搭建 开始的开始,就是各种框架一搭,然后扔到Tomcat容器中跑就是了,这时候我们的文件,数据库 ...
- [Java复习] 分布式PRC - Dubbo
分布式RPC框架 dubbo常见问题: 1. 问dubbo的工作原理:服务注册,注册中心,服务生产者,消费者,代理通信,负载均衡 2. 问网络通信,序列化: dubbo协议,长连接,NIO,hessi ...
- 图灵学院JAVA互联网架构师专题学习笔记
图灵学院JAVA互联网架构师专题学习笔记 下载链接:链接: https://pan.baidu.com/s/1xbxDzmnQudnYtMt5Ce1ONQ 密码: fbdj如果失效联系v:itit11 ...
- JMicro微服务之超时&重试
JMicro是本人开发的基于Java实现的微服务框架,当前正式版本为0.0.3,并已发布到maven中央仓库.项目源码github:https://github.com/mynewworldyyl/j ...
- paip.提升用户体验--提升java的热部署热更新能力
paip.提升用户体验--提升java的热部署热更新能力 想让java做到php那么好的热部署能力 "fix online"/在线修复吗??直接在服务器上修改源码生效,无需重启应 ...
- Java应用架构的演化之路
Java应用架构的演化之路 当我们架设一个系统的时候通常需要考虑到如何与其他系统交互,所以我们首先需要知道各种系统之间是如何交互的,使用何种技术实现. 1. 不同系统不同语言之间的交互 现 在我们常见 ...
- java企业架构 spring mvc +mybatis + KafKa+Flume+Zookeeper
声明:该框架面向企业,是大型互联网分布式企业架构,后期会介绍linux上部署高可用集群项目. 项目基础功能截图(自提供了最小部分) 平台简介 Jeesz是一个分布式的框架,提供 ...
- 15套java互联网架构师、高并发、集群、负载均衡、高可用、数据库设计、缓存、性能优化、大型分布式 项目实战视频教程
* { font-family: "Microsoft YaHei" !important } h1 { color: #FF0 } 15套java架构师.集群.高可用.高可扩 展 ...
随机推荐
- Pandas_数据清洗与整理_全
# 数据清洗与整(全) # 1) 常见的数据清洗方法 # 2) 数据合并:多源数据的合并和连接 # 3) 数据重塑:针对层次化索引,学会 stack和 unstack # 4) 字符串处理:学会 Da ...
- 类和对象在JVM中是如何存储的,竟然有一半人回答不上来!
前言 这篇博客主要来说说类与对象在JVM中是如何存储的,由于JVM是个非常庞大的课题,所以我会把他分成很多章节来细细阐述,具体的数量还没有决定,当然这不重要,重点在于是否可以在文章中学到东西,是否对J ...
- Selective Acknowledgment 选项 浅析 1
抓包的时候,发现 tcp 三次握手中一般会有几个options 一个是mss 一个是ws 一个sack perm 这次主要是来说一说 sack 这个选项: 1. 只重传超时的数据包,比较实用与后 ...
- mysql 常用命令和笔记
第一招.mysql服务的启动和停止 net stop mysql net start mysql 第二招.登陆mysql 语法如下: mysql -u用户名 -p用户密码 键入命令mysql -uro ...
- parted命令采用gpt分区过程
Gpt无分区限制,故只有主分区,无扩展分区和逻辑分区.分区直接按容量算,不按柱面算. 查看分区:parted -l 将分区表类型转换为gpt.: 主要命令mklabel gpt 对sdc盘分区: [r ...
- 重写ceph-lazy
前言 这个工具最开始是从sebastien的blog里面看到的,这个是 Gregory Charot(工具的作者)写的,通常我们在获取一个ceph的信息的时候,需要敲一连串的命令去获得自己需要的信息, ...
- Golang中的OO(面向对象)
组合 > 继承 Go中的设计,以为继承的被诟病,所以Golang的设计团队在语言的设计时并没有采用经典的OO模式 那Golang中各个部分是怎么联系到一起的呢 type ReadWriter i ...
- BeanFactory and FactoryBean
BeanFactory,这是Spring容器的基础实现类,它负责生产和管理Bean的一个工厂.当然BeanFactory只是一个接口,它的常用实现有XmlBeanFactory.DefaultList ...
- Linux 入侵痕迹清理技巧
清除history历史命令记录 vim ~/.bash_history //编辑history记录文件,删除部分不想被保存的历史命令 history -c //清除当前用户的history命令记录 H ...
- Guitar Pro小课堂之弹唱和弦转换小技巧
吉他相对其他乐器的便携性,还有其便于弹唱的特点,受到了很多音乐萌新们的喜爱.对于刚刚接触吉他的萌新来说,学琴初期弹唱的时候经常会因为和弦卡顿的转换,和因为食指力度不够或技巧不对无法顺利演奏的大横按,导 ...