• [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进阶面试训练营(分布式篇)-- 中华石杉

  • 相关阅读:
    KVM(Keyboard、Video、Mouse)
    javascript valueof
    javascript的typeof的返回值
    javascript的===和==
    WGestures全局鼠标手势工具
    向win+x快捷目录添加功能
    好用的影子系统软件
    备份任务栏
    修改多个调用提示最小值_改变多选右键菜单
    执行Windows Update更新
  • 原文地址:https://www.cnblogs.com/fyql/p/12170502.html
Copyright © 2020-2023  润新知