做彩票网站需要什么服务器,wordpress点击文字弹窗,一般网站使用什么做的,恒丰建设集团有限公司 网站如果让你设计一个接口#xff0c;你会考虑哪些问题#xff1f; 1.接口参数校验
接口的入参和返回值都需要进行校验。 入参是否不能为空#xff0c;入参的长度限制是多少#xff0c;入参的格式限制#xff0c;如邮箱格式限制 返回值是否为空#xff0c;如果为空的时候是… 如果让你设计一个接口你会考虑哪些问题 1.接口参数校验
接口的入参和返回值都需要进行校验。 入参是否不能为空入参的长度限制是多少入参的格式限制如邮箱格式限制 返回值是否为空如果为空的时候是否返回默认值这个默认值需要和前端协商
2.接口扩展性
举个例子比如用户在进行某些操作之后后端需要进行消息推送那么是直接针对这个业务流程来开发一个专门为这个业务流程服务的消息推送功能呢还是说将消息推送整合为一个通用的接口其他流程都可以进行调用并非针对特定业务。
这个场景可能光靠说不是很能理解大家想想策略工厂设计模式是不是可以根据不同的策略来选择不同的实现方式呢再结合上面的这个例子是否对扩展性有了进一步的理解呢
3.接口幂等设计
什么是幂等呢幂等是指多次调用接口不会改变业务状态可以保证重复调用的结果和单次调用的结果一致。
举个例子在购物商场里面你用手机下单要买某个商品你需要去支付然后你点击了支付但是因为网速问题始终没有跳转到支付界面于是你又连点了几次支付那在没有做接口幂等的时候是不是你点击了多少次支付我们就需要执行多少次支付操作
所以接口幂等到的是什么防止用户多次调用同一个接口 对于查询和删除类型的接口不论调用多少次都是不会产生错误的业务逻辑和数据的因此无需幂等处理 对于新增和修改例如转账等操作重复提交就会导致多次转账这是很严重的影响业务的接口需要做接口幂等的处理跟前端约定好一个固定的token接口先通过用户的id获取全局的token写入到Redis缓存请求时带上Token后端做处理 4.关键接口日志打印
关键的业务代码是需要打印日志进行监测的在入参和返回值或者如catch代码块中的位置进行日志打印 方便排查和定位线上问题划清责任 生产环境是没有办法进行debug的必须依靠日志查问题看看到底是出现了什么异常情况
5.核心接口要进行线程池隔离
分类查询啊首页数据等接口都有可能使用到线程池某些普通接口也可能会使用到线程池如果不做线程池隔离万一普通接口出现bug把线程池打满了会导致你的主业务受到影响 6.第三方接口异常重试
如果有场景出现调用第三方接口或者分布式远程服务的话需要考虑的问题 异常处理 比如你在调用别人提供的接口的时候如果出现异常了是要进行重试还是直接就是当做失败 请求超时 有时候如果对方请求迟迟无响应难道就一直等着吗肯定不是这样的需要设法预估对方接口响应时间设置一个超时断开的机制以保护接口提高接口的可用性举个例子你去调用别人对外提供的一个接口然后你去发http请求始终响应不回来此时你又没设置超时机制最后响应方进程假死请求一直占着线程不释放拖垮线程池。 重试机制 如果调用对外的接口失败了或者超时了是否需要重新尝试调用呢还是失败了就直接返回失败的数据
7.接口是否需要采用异步处理
举个例子比如你实现一个用户注册的接口。用户注册成功时发个邮件或者短信去通知用户。这个邮件或者发短信就更适合异步处理。总不能一个通知类的失败导致注册失败吧。那我们如何进行异步操作呢可以使用消息队列就是用户注册成功后生产者产生一个注册成功的消息消费者拉到注册成功的消息就发送通知。 8.接口查询优化串行优化为并行
假设我们要开发一个网站的首页我们设计了一个首页数据查询的接口这个接口需要查用户信息需要查头部信息需要查新闻信息
等等之类的最简单的就是一个一个接口串行调用那要是想要提高性能那就采取并行调用的方式同时查询而不是阻塞
可以使用CompletableFuture(推荐)或者FutureTask(不推荐) MapLong, ListSubjectLabelBO map new HashMap(); ListCompletableFutureMapLong, ListSubjectLabelBO completableFutureList categoryBOList.stream().map(category - CompletableFuture.supplyAsync(() - getLabelBOList(category), labelThreadPool) ).collect(Collectors.toList()); completableFutureList.forEach(future - { try { MapLong, ListSubjectLabelBO resultMap future.get(); //这里会阻塞 map.putAll(resultMap); } catch (Exception e) { e.printStackTrace(); } }); public MapLong, ListSubjectLabelBO getLabelBOList(SubjectCategoryBO category) {...} 9.高频接口注意限流
自定义注解 AOP Target(ElementType.METHOD) Retention(RetentionPolicy.RUNTIME) public interface RateLimiter { int value() default 1; int durationInSeconds() default 1; } Aspect Component public class RateLimiterAspect { private final ConcurrentHashMapString, RateLimiter rateLimiters new ConcurrentHashMap(); Pointcut(annotation(RateLimiter)) public void rateLimiterPointcut(RateLimiter rateLimiterAnnotation) { } Around(rateLimiterPointcut(rateLimiterAnnotation)) public Object around(ProceedingJoinPoint joinPoint, RateLimiter rateLimiterAnnotation) throws Throwable { int permits rateLimiterAnnotation.value(); int durationInSeconds rateLimiterAnnotation.durationInSeconds(); // 使用方法签名作为 RateLimiter 的 key String key joinPoint.getSignature().toLongString(); com.google.common.util.concurrent.RateLimiter rateLimiter rateLimiters.computeIfAbsent(key, k - com.google.common.util.concurrent.RateLimiter.create((double) permits / durationInSeconds)); // 尝试获取令牌如果获取到则执行方法否则抛出异常 if (rateLimiter.tryAcquire()) { return joinPoint.proceed(); } else { throw new RuntimeException(Rate limit exceeded.); } } } RestController public class ApiController { GetMapping(/api/limited) RateLimiter(value 10, durationInSeconds 60) //限制为每分钟 10 次请求 public String limitedEndpoint() { return This API has a rate limit of 10 requests per minute.; } GetMapping(/api/unlimited) public String unlimitedEndpoint() { return This API has no rate limit.; } } 10.保障接口安全
配置黑白名单用Bloom过滤器实现黑白名单的配置
具体代码不贴出来了大家可以去看看布隆过滤器的具体使用
11.接口控制锁粒度
在高并发场景下为了防止超卖等情况我们会对共享资源进行加锁的操作来保证线程安全的问题但是如果加锁的粒度过大是会影响
到接口性能的。那什么是加锁粒度呢举一个例子你带了一封情书回家但是不想被爸妈发现然后你偷偷回到房间里放到一个可以锁
住的抽屉里面而不用把房间的门锁给锁上。无论是使用synchronized加锁还是redis分布式锁只需要在共享临界资源加锁即可不涉
及共享资源的就不必要加锁。 锁粒度过大 把方法A和方法B全部进行加锁但是实际上我只是想要对A加锁这就是锁粒度过大 void test(){ synchronized (this) { B(); A(); } } 缩小锁粒度 void test(){ B(); synchronized (this) { A(); } }
12.避免长事务问题
长事务期间可能伴随cpu、内存升高、严重时会导致服务端整体响应缓慢导致在线应用无法使用
产生长事务的原因除了sql本身可能存在问题外和应用层的事务控制逻辑也有很大的关系。 如何尽可能的避免长事务问题呢 RPC远程调用不要放到事务里面 一些查询相关的操作如果可用尽量放到事务外面 并发场景下尽量避免使用Transactional注解来操作事务使用TransactionTemplate的编排式事务来灵活控制事务的范围
在原先使用Transactional来管理事务的时候是这样的 Transactional public int createUser(User user){ //保存用户信息 userDao.save(user); passCertDao.updateFlag(user.getPassId()); // 该方法为远程RPC接口 sendEmailRpc(user.getEmail()); return user.getUserId(); }
使用TransactionTemplat进行编排式事务 Resource private TransactionTemplate transactionTemplate; public int createUser(User user){ transactionTemplate.execute(transactionStatus - { try { userDao.save(user); passCertDao.updateFlag(user.getPassId()); } catch (Exception e) { // 异常手动设置回滚 transactionStatus.setRollbackOnly(); } return true; }); // 该方法为远程RPC接口 sendEmailRpc(user.getEmail()); return user.getUserId(); } 总结
感谢每一个认真阅读我文章的人
作为一位过来人也是希望大家少走一些弯路如果你不想再体验一次学习时找不到资料没人解答问题坚持几天便放弃的感受的话在这里我给大家分享一些自动化测试的学习资源希望能给你前进的路上带来帮助。 软件测试面试文档
我们学习必然是为了找到高薪的工作下面这些面试题是来自阿里、腾讯、字节等一线互联网大厂最新的面试资料并且有字节大佬给出了权威的解答刷完这一套面试资料相信大家都能找到满意的工作。 视频文档获取方式 这份文档和视频资料对于想从事【软件测试】的朋友来说应该是最全面最完整的备战仓库这个仓库也陪伴我走过了最艰难的路程希望也能帮助到你以上均可以分享点下方小卡片即可自行领取。