当前位置: 首页 > news >正文

襄阳手机网站建设公司申请域名费用

襄阳手机网站建设公司,申请域名费用,室内装修培训,手机传奇开服网什么是接口幂等性 接口幂等性这一概念源于数学#xff0c;原意是指一个操作如果连续执行多次所产生的结果与仅执行一次的效果相同#xff0c;那么我们就称这个操作是幂等的。在互联网领域#xff0c;特别是在Web服务、API设计和分布式系统中#xff0c;接口幂等性具有非常…什么是接口幂等性 接口幂等性这一概念源于数学原意是指一个操作如果连续执行多次所产生的结果与仅执行一次的效果相同那么我们就称这个操作是幂等的。在互联网领域特别是在Web服务、API设计和分布式系统中接口幂等性具有非常重要的意义。 具体到HTTP接口或者服务间的API调用接口幂等性就可以理解为当客户端对同一接口发起多次相同的请求时服务端系统也应该确保只执行一次相应的操作并且不论接收到了多少次请求系统的状态变更始终是一致的不会因为重复的请求而导致数据的错误。 比如我们常常遇到的订单创建支付等业务。 如果一个“创建订单”接口实现了幂等性当收到两次同样的创建请求时系统应该要么拒绝第二个请求因为它已经是重复请求要么确保只有一个订单被创建而不是两个完全一样的订单。对于一个“支付”接口幂等性要求即便用户由于网络原因反复点击支付按钮服务端也只会扣除用户账户一次金额避免重复扣费。 导致接口幂等性问题的原因 要向杜绝幂等性那么我们就要之道导致接口幂等性问题的原因有哪些。接口幂等性问题通常由以下多种原因引起 网络波动不稳定 网络通信中的丢包、延迟等情况可能导致客户端未收到服务端的响应或服务端未收到客户端的请求此时客户端可能会重试发送请求导致接口被重复调用。 用户操作 用户快速重复点击导致例如用户在等待响应时由于不确定是否操作成功可能会多次点击提交按钮进而发送多次相同的请求。再比如页用户频繁刷新页面尤其是在某些提交操作尚未完成时刷新页面可能会重新发送请求。还有用户可能在浏览器上点击回退然后再重复之间的提交操作这都可能会导致重新发送请求。 重试机制 在高可用性设计中客户端常常设置有重试机制当请求失败或超时时会自动重新发起请求。而在分布式系统中服务间调用也可能有重试策略以应对临时故障。比如Nginx重试RPC重试或者调用方业务层中进行重试。 定时任务或异步处理 在定时任务中如果定时任务调度或逻辑设计不当可能会导致同一任务被执行多次。或者在消息队列中消息可能会因为异常等原因被重复消费。 并发控制 缺乏有效的并发控制手段导致在并发环境下针对同一资源的操作被多次执行。 总的来说导致接口幂等性问题可以粗略的归类于两种情况前端调用以及服务端调用那么我们可以针对这两种情况看一下如何去保证接口幂等。 如何保证接口幂等 前端调用 页面控制 页面调用接口时可以通过禁用如按钮置灰或显示加载状态防止用户在请求未完成前重复点击从而减少不必要的重复请求和可能的数据冲突。虽然在前端进行按钮置灰等操作可以辅助提高系统的幂等性表现但是这个方式只是从用户体验和用户行为控制的角度来避免重复提交的一种方法并没有从系统设计层面完全解决接口本身的幂等性问题。 使用RPG模式 PRGPOST/Redirect/GET模式是一种前端交互策略旨在解决用户刷新页面时可能导致表单数据重复提交的问题。它巧妙地利用了HTTP协议的特性具体的交互流程如下 用户在网页表单中填写数据并通过POST请求将其发送至服务器进行处理例如创建新资源或更新现有数据。服务器接收到POST请求后对提交的数据进行有效处理和持久化存储并在操作成功后不直接返回处理结果而是通过HTTP响应码302或303实现重定向指示客户端发起一个新的GET请求去访问一个特定的URL。客户端遵照服务器的重定向指示自动发送GET请求访问新的URL此时返回的页面将展示之前POST操作处理完毕的结果。当用户在此后刷新页面时浏览器只会按照常规方式重新发起GET请求而非重新提交POST数据因此有效地避免了重复提交引发的潜在问题 Token机制 Token机制是一种广泛应用互联网领域的认证与授权方法特别是Web服务系统。token可以理解为一种安全凭证它是由服务端生成并颁发给客户端的一段经过加密处理的字符串或数据结构用来代表用户的某种状态或权限。 通过Token机制我们可以解决接口幂等性问题。在接口中我们允许重复提交但是要保证重复提交不产生副作用比如点击n次只产生一条记录客户端每次请求都需要携带一个唯一的Token而服务器则验证这个Token的有效性。如果服务器收到了一个已经使用过的Token就会认为这是一个重复请求并拒绝处理从而确保接口的幂等性具体流握如下Token机制是一种常用的方法用于确保接口的幂等性和防止重复请求。具体流程如下 生成Token 当用户开始执行一个需要确保幂等性的操作如支付、下单、更新用户信息等时服务端会生成一个唯一的、有时效性的token。这个token可以是一个随机字符串或者带有时间戳和其他相关信息的哈希值确保其唯一性。 存储Token 生成的token会被存储在服务端的一个临时存储介质中如Redis、Memcached或数据库同时设置一个合理的过期时间例如15分钟。 传递Token 将生成的token返回给客户端客户端在进行后续的API调用时需将此token作为请求参数或放在请求头中一并发送给服务端。 验证Token 服务端在接收到带有token的请求时首先检查token是否存在并且有效未过期且未被使用过。如果token有效且未被使用则执行相应的业务逻辑并在执行完成后立即从存储介质中移除或标记为已使用。若token已失效或已被使用则拒绝此次请求返回相应的错误提示确保同一个操作不会被执行两次。 限制并发 在并发场景下通过原子操作如Redis的SETNX命令确保在验证token有效的同时将其删除或更新状态避免多个请求同时通过验证。 服务端控制 在服务端接口处理逻辑时可以通过通过一些特定的标识符或请求参数来校验请求的幂等性以确保同样的请求不会被重复处理。 唯一标识符 客户端每次发起请求会携带一个全局唯一的标识符。服务器接收到请求后就会对这个标识符进行检查若服务器发现该标识符已经在系统中存在表明这是一个重复请求此时服务器可以选择忽略该请求或者向客户端返回已处理过相同请求的结果信息。若服务器未找到该标识符存在于系统内则认定该请求为新请求服务器将继续对其进行正常处理并将此唯一标识符保存至系统中以便于后续对接收的请求进行有效性校验防止同一请求的重复处理。比如我们在要求上游ERP系统对接订单平台时就会要求上游传递一个账号下全局唯一的一个参考单号这个参考单号一个很重要的作用就是保证接口幂等性。 请求参数 某些请求参数确实可以用来辅助校验请求的幂等性。例如时间戳可以作为一种可能的请求参数在处理请求时服务器可以通过比较时间戳与服务器当前时间来判断请求的有效性。若时间戳与当前时间之间的差异超出预设的合理范围如几秒钟到几分钟不等具体阈值视业务场景而定服务器可以推测该请求可能是由于网络延迟或者其他原因导致的重复提交。 单纯依靠时间戳来判断幂等性和重复请求并不完全准确因为不同的客户端时间可能并不精确同步而且时间戳本身无法保证全局唯一性。但是它可以作为一种有效的辅助手段来减少重复处理的可能性 状态机设计 对于状态转移类的操作类型的业务可采用状态机设计每次请求只允许合法的状态变迁非法状态变迁如已经完成的订单不允许再次支付将被拒绝。 乐观锁 在更新数据时可以通过版本号或时间戳等机制判断数据是否已被修改防止因并发请求导致的多次更新问题。具体做法 在数据库表中增加一个版本号字段version或者时间戳字段timestamp。客户端第一次请求时获取数据的版本号或时间戳。客户端发起更新操作时将上次读取的版本号或时间戳一起发送回服务器。服务器在执行更新操作前首先检查当前数据库中的版本号或时间戳是否与客户端提交的一致。 如果一致说明在这期间数据没有被其他事务修改过于是更新数据并递增版本号或更新时间戳。如果不一致说明数据已经被修改过此时服务器拒绝本次更新请求返回错误提示客户端可以根据错误信息决定是否重新获取最新数据再尝试更新。 通过这种方式即使客户端因为网络原因或其他因素导致同一请求被多次发送乐观锁机制能确保只有在数据未被其他事务修改的前提下才会执行更新操作从而达到接口幂等的效果。 实现幂等性方案示例 从上述的几种解决幂等性问题的方案来看使用token机制可以保证在不同请求动作下的幂等性。所以我们以此作为方案作为示例方案。 准备工作 我们使用Redis保存Token令牌引入SpringBootRedisULID相关的依赖 dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-data-redis/artifactIdversion2.7.0/version /dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-web/artifactIdversion2.7.0/version /dependencydependencygroupIdcom.github.f4b6a3/groupIdartifactIdulid-creator/artifactIdversion5.2.0/version /dependencyRedis相关的配置 spring.redis.database0 spring.redis.host127.0.0.1 spring.redis.port6379 spring.redis.password spring.redis.pool.max-active8 spring.redis.pool.max-wait-1 spring.redis.pool.max-idle8 spring.redis.pool.min-idle0 spring.redis.timeout60 server.port8080 server.servlet.context-path/coderacademy生成Token令牌 使用ULID生成随机字符串然后将其保存在Redis当中。这里以idempotent_token账户请求操作类型token作为key。 private StringRedisTemplate stringRedisTemplate;/*** 存入 Redis 的 Token 键的前缀*/ private static final String IDEMPOTENT_TOKEN_PREFIX idempotent_token:%s:$s:%s;/*** 生成token令牌** param accountSecret 账户令牌* param operatorType 接口请求类型可以是接口url或者其他可以区分接口服务类型的值* return token令牌*/ Override public String generateToken(String accountSecret, String operatorType) {// 创建或获取ULID生成器实例long timestampInMillis LocalDateTime.now().atZone(ZoneOffset.systemDefault()).toInstant().toEpochMilli();Ulid ulid UlidCreator.getUlid(timestampInMillis);String token ulid.toString();// 设置存入 Redis 的 KeyString key String.format(IDEMPOTENT_TOKEN_PREFIX, accountSecret, operatorType, token);// 存储 Token 到 Redis且设置过期时间为5分钟stringRedisTemplate.opsForValue().set(key, accountSecret, 5, TimeUnit.MINUTES);// 返回 Tokenreturn token; }校验Token令牌 这里我们使用Redis执行Lua命令去查找以及删除keyLua 表达式能保证命令执行的原子性。 /*** 验证 Token 正确性** param token token 字符串* param operatorType 接口请求类型可以是接口url或者其他可以区分接口服务类型的值* return 验证结果*/ private boolean validToken(String token, String accountSecret, String operatorType) {// 设置 Lua 脚本其中 KEYS[1] 是 keyKEYS[2] 是 valueString script if redis.call(get, KEYS[1]) KEYS[2] then return redis.call(del, KEYS[1]) else return 0 end;RedisScriptLong redisScript new DefaultRedisScript(script, Long.class);// 根据 Key 前缀拼接 KeyString key String.format(IDEMPOTENT_TOKEN_PREFIX, accountSecret, operatorType, token);// 执行 Lua 脚本Long result stringRedisTemplate.execute(redisScript, Arrays.asList(key, operatorType));// 根据返回结果判断是否成功成功匹配并删除 Redis 键值对若果结果不为空和0则验证通过if (result ! null result ! 0L) {System.out.println(String.format(验证 token%s,key%s,value%s 成功, token, key, operatorType));return true;}System.err.println(String.format(验证 token%s,key%s,value%s 失败, token, key, operatorType));return false; }业务代码以及接口 我们在实现模拟创建订单的服务在创建订单之前首先校验token令牌。 /*** 创建订单接口** param requestVO 创建订单参数* param accountSecret 账户令牌* param token token令牌* return 生成的订单号*/ Override public String createOrder(OrderCreateRequestVO requestVO, String accountSecret, String token) {// 根据 Token 和与用户相关的信息到 Redis 验证是否存在对应的信息boolean result validToken(token, accountSecret, createOrder);if (!result){// 这里需要自定义异常统一处理异常再统一响应返回throw new RuntimeException(重复的请求);}// 根据验证结果响应不同信息return Success; }校验如果不存在token则说明请求时重复请求直接抛出异常由统一异常管理直接返回客户端请求失败的错误信息。关于SpringBoot中统一异常处理统一结果响应请查看 我们在定义获取Token令牌的接口以及创建订单的接口 RestController RequestMapping(order) public class OrderController {private IOrderService orderService;/*** 获取token接口* param secret 账户令牌* return*/GetMapping(getToken)public String getToken(RequestHeader(secret) String secret){return orderService.generateToken(secret, createOrder);}/*** 创建订单接口* param requestVO 参数* param token token令牌* param secret 账户令牌* return 响应信息*/PostMapping(create)public OrderCreateResponseVO createOrder(RequestBody OrderCreateRequestVO requestVO,RequestHeader(token) String token,RequestHeader(secret) String secret){OrderCreateResponseVO responseVO new OrderCreateResponseVO();String result orderService.createOrder(requestVO, secret, token);responseVO.setSuccess(Boolean.TRUE);responseVO.setMsg(result);return responseVO;}Autowiredpublic void setOrderService(IOrderService orderService) {this.orderService orderService;} }我们使用Apifox模拟3个请求并发操作 执行结果如下 控制台打印日志如下 可以看见只有1个请求成功了并且控制台中打印只有一个token校验成功。 总结 幂等性是开发当中很常见也很重要的一个需求尤其是订单支付以及与金钱挂钩的服务保证接口幂等性尤其重要。在实际开发中我们需要针对不同的业务场景我们需要灵活的选择幂等性的实现方式 如果是web服务客户端可以采取在页面上使用按钮置灰禁用使用PRG模式或者搭配后端的Token令牌进行解决。在服务端我们可以采取唯一标识符乐观锁Token令牌状态机等校验方式。 最后强调一下实现幂等性需要先理解自身业务需求根据业务逻辑来实现这样才合理处理好其中的每一个结点细节完善整体的业务流程设计才能更好的保证系统的正常运行。 本文已收录于我的个人博客码农Academy的博客专注分享Java技术干货包括Java基础、Spring Boot、Spring Cloud、Mysql、Redis、Elasticsearch、中间件、架构设计、面试题、程序员攻略等。
http://www.pierceye.com/news/520519/

相关文章:

  • 有免费做海报的网站吗制作表情包
  • 网站建设的平台做微课的网站
  • 有没有专门做美食海报的网站郑州网站建设搜q.479185700
  • 公司网站宣传做网站时版权怎么写
  • 可以在哪些网站 app做推广的建站官网模板
  • 网站建设标书卧龙区建网站
  • 东莞做网站软件嘉兴网站制作价格
  • 学网站建设 去那里合肥专业网站优化
  • 个人网站 备案 广告建设国际网站
  • 苏州建站推广公司做网站费用怎么记分录
  • 做的比较好的家具网站首页在win10下建设网站
  • 住房和城乡建设部网站 绿地网站备案有时间吗
  • 新开传奇手游新服网谷歌seo运营
  • 新河网站建设网站空间 jsp
  • 网站视频如何下载中国建盏
  • 做网站的叫什么软件细谈电商网站外链建设的策略
  • 免费网站制作视频教程广东东莞营销
  • 女生做网站运营累不累贵州省铁路建设办公室网站
  • 全球外贸网站排名go生物网站做蛋白定位
  • 网站的规划和建设方案中教在线3d建模培训
  • 禾天姿网站开发设计上海官网
  • 个人备案后可以做电影网站吗做网站要注意哪些问题
  • 为什么我的网站在百度搜不到登封郑州网站建设
  • 中国建设部网站能查叉车证wordpress预览
  • 域名申请网页制作网站建设和外国人做古玩生意的网站
  • win7用自己ip做网站邯郸营销型网站建设
  • 织梦免费网站模块下载地址加强网站建设技术培训
  • 网站源码商城建设成都建站优化
  • 网站销售如何做业绩狗狗和人做网站
  • dede 手机站 怎么获取跳转网站安卓软件开发环境