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

广州东圃网站建设公司谷歌paypal官网下载

广州东圃网站建设公司,谷歌paypal官网下载,苏州搜狗关键词优化,网站建设督查报告4次迭代#xff0c;让我的HttpClient提速100倍 在大家的生产项目中#xff0c;经常需要通过Client组件#xff08;HttpClient/OkHttp/JDK Connection)调用第三方接口。 尼恩的一个生产项目也不例外。 在一个高并发的中台生产项目中。有一个比较特殊的请求#xff0c;一次…4次迭代让我的HttpClient提速100倍 在大家的生产项目中经常需要通过Client组件HttpClient/OkHttp/JDK Connection)调用第三方接口。 尼恩的一个生产项目也不例外。 在一个高并发的中台生产项目中。有一个比较特殊的请求一次请求包含 10个 Web 外部服务调用每个服务调用的预定时间200ms。 为了并行使用了一个很大的线程池最大100个线程。 注意这里100个线程已经很多了因为其他的环节也需要很多线程。所以不能太多了。 尼恩和团队小伙伴经过4次迭代把这个客户端调用不断提升最终的提升了100倍。 为啥写此文呢 尼恩最近在指导小伙伴的简历发现很多小伙伴没有素材简历写得太low、太low。在尼恩读者50交流群中尼恩经常指导小伙伴改简历。 改简历所涉及的一个要点是 在 XXX 项目中完成了 XXX 模块的代码优化 另外在面试的过程中面试官也常常喜欢针对提问来考察候选人对代码质量的追求、对设计模式的应用能力 你做过哪些代码优化 大家一般的套路都是通过模板模式、策略模式等完成 XXXXX 模块的重构提升代码的可扩展行可维护性。 如果有类似扩展场景、类似优化经历的小伙伴还好。 头疼的是很多小伙伴确实没有。然后无奈的说没有做过代码的优化。 所以为了能帮到大家上一次给大家提供了一个人人可用的、涉及到切面思想、非常高明的的代码优化点 阿里一面你做过哪些代码优化来一个人人可以用的极品案例 这一次又是一个大大的代码优化、性能优化点甚至比上次的更为出彩。固尼恩通过这个文章把Client性能提升100倍的迭代过程记录下来再一次为大家提供一个代码优化的参考答案。 大家可以对着实操一下然后写入简历为简历增加一个不小的亮点。当然如果确实不知道怎么优化简历可以来找40岁老架构师尼恩。 接下来看看尼恩团队是怎么做到的。 注本文以 PDF 持续更新最新尼恩 架构笔记、面试题 的PDF文件请从这里获取码云 第1次迭代使用 CompletableFuture 完成并发 最早的代码是通过向线程池中提交任务的方式完成的从代码的优雅程度上来说比使用CompletableFuture 的方式差得太远。 所以第1轮迭代是通过CompletableFuture进行代码的优化。这个环节对性能没有本质的提升但是CompletableFuture 这种 函数式编程的风格为后面的迭代打下来一些技术基础。 使用CompletableFuture 并发10个远程api 接口有两个方法 方法1CompletableFuture 和 CountDownLatch方法2CompletableFuture.allOf 算子 在代码实现的时候使用了结合使用CompletableFuture 和 CountDownLatch 进行并发回调 为了大家能体验效果给大家提供了一段原始代码的参考程序具体如下 package com.crazymaker.springcloud;import com.crazymaker.springcloud.common.util.ThreadUtil; import org.junit.Test;import java.util.concurrent.CompletableFuture; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService;public class CoCurrentDemo {/*** 使用CompletableFuture 和 CountDownLatch 进行并发回调*/Testpublic void testMutiCallBack() {CountDownLatch countDownLatch new CountDownLatch(10);//批量异步ExecutorService executor ThreadUtil.getIoIntenseTargetThreadPool();long start System.currentTimeMillis();for (int i 0; i 10; i) {CompletableFutureLong future CompletableFuture.supplyAsync(() - {long tid ThreadUtil.getCurThreadId();try {doRpc(tid); //异步执行 远程调用} catch (InterruptedException e) {e.printStackTrace();}return tid;}, executor);future.thenAccept((tid) - {System.out.println(线程 tid 结束了);countDownLatch.countDown();});}try {countDownLatch.await();//输出统计结果float time System.currentTimeMillis() - start;System.out.println(所有任务已经执行完毕);System.out.println(运行的时长为(ms) time);} catch (InterruptedException e) {e.printStackTrace();}}private void doRpc(long tid) throws InterruptedException {System.out.println(线程 tid 开始了,模拟一下远程调用);Thread.sleep(200);} }尼恩提示CompletableFuture 的知识非常重要。具体请大家去阅读尼恩在清华大学出版社出版的《Java 高并发核心编程 卷2 加强版》。 很多小伙伴和尼恩说这本书写得太好之前读博客的时候很多高并发的知识看不懂的通过卷2加强版都看懂了。 第2次迭代响应式 Flux 流进行异步回调改造 回顾一下咱们这个优化的案例一次请求触发 10 个 Web 服务调用。 什么分析一下发现一个秘密执行一次WEB调用操作所需的实际工作非常少。实际的工作就2点 生成并触发一个请求等等一段时间会收到一个响应。 而且其中有一个节非常低性能这个环节是在请求和响应之间线程根本没有做任何工作而且在等待等待200ms。 线程资源是宝贵的。咱们一个java应用不能开始太多的线程一般最多就400个左右。如果开启太多很多的cpu资源就用去做线程上下文切换了。 如何要让这些线程不等待去干别的工作该当如何 这是使用异步框架。使用异步框架发出 Web 请求的核心优势之一在请求进行中时您不会占用任何线程。第2次迭代响应式 Flux 流进行异步回调改造。 使用异步框架的核心逻辑如下所以 Flux.range(0,100) .subscribeOn(Schedulers.boundedElastic()) .flatMap(i - webClientCallApi(i)) .subscribe(...) //定义结果响应式的本质是回调。其原理具体请参考 尼恩的深度文章《京东一面20种异步你知道几种 含协程》 响应式编程门槛非常高学习曲线很长。但是一旦掌握了其编程的风格之后其实也就简单了。 有关响应式编程的内容尼恩给大家准备了一本10W字的《响应式 圣经pdf可以找尼恩获取》 在响应式框架中我们的线程不用再死耗了底层的逻辑是把异步任务加入响应式组件的内部的队列之后就去干起别的事情了不需要去死死等200ms。 so我们进行了第2次迭代响应式Flux流进行异步回调改造。 为了大家能体验效果给大家提供了一段原始代码的参考程序具体如下 private FluxInteger doRpcFlux(int key) {return Flux.create(sink - {log.info(模拟远程调用参数为 key);ThreadUtil.sleepMilliSeconds(100);sink.next(key);sink.complete();}); }Test public void mergeTest5() throws InterruptedException {long startTime LocalTiker.SINGLETON.now();IterableInteger targetKeys Arrays.asList( 101, 102, 103, 104, 105);Flux.fromIterable(targetKeys).publishOn(Schedulers.fromExecutorService(ThreadUtil.getMixedTargetThreadPool())).flatMap(key - doRpcFlux(key)).doOnError(ReactorPrallelDemo::doOnError).doOnComplete(ReactorPrallelDemo::doOnComplete).doFinally(signalType - log.info(并发执行的时间: LocalTiker.SINGLETON.gapFrom(startTime))).subscribe(responseData - log.info(responseData.toString()), e - log.info(error: e.getMessage()));Thread.sleep(200000); } 第3次迭代响应式 parallel Flux 流进行并行异步回调改造 在刚开始使用响应式编程的时候感觉也没有耗费太长时间就把传统的命令式代码切换到了响应式的风格不免洋洋得意。 第2次迭代响应式Flux流进行异步回调改造以为十全十美改造成功了。 实际不然改造之后虽然线程资源得到了有效的利用。但是由于前期对flux流的机制不是太清楚。实际上的情况是性能反而下降了。 实际上flux的内部机制flux流里边的任务默认是串行执行的。 所以上面的代码实际上是让10次调用 串行执行。初心是并行实际上适得其反变成了串行性能反而大大下降。 怎么回到并行呢需要使用 Flux parallel流。 下面是一段 使用paralle Flux 的demo: Flux.range(0,100) .parallel() .runOn(Schedulers.boundedElastic()) .flatMap(i - webClientCallApi(i)) .sequential().collecttoList();so我们进行了第3次迭代响应式 parallel Flux 流进行并行异步回调改造。 为了大家能体验效果给大家提供了一段原始代码的参考程序具体如下 Test public void mergeTest6() throws InterruptedException {long startTime LocalTiker.SINGLETON.now();IterableInteger targetKeys Arrays.asList(100, 101, 102, 103, 104, 105, 106, 107);Flux.fromIterable(targetKeys).parallel().runOn(Schedulers.fromExecutorService(ThreadUtil.getMixedTargetThreadPool())).flatMap(key - doRpcFlux(key)).sequential().doOnError(ReactorPrallelDemo::doOnError).doOnComplete(ReactorPrallelDemo::doOnComplete).doFinally(signalType - log.info(并发执行的时间: LocalTiker.SINGLETON.gapFrom(startTime))).subscribe(i - log.info(- i));Thread.sleep(200000); }private static void doOnComplete() {log.info(并发远程调用异常完成); }运行的结果如下 12:31:34.138 [Biz-1-cpu-2] INFO com.crazymaker.springcloud.user.main.ReactorPrallelDemo - this taskB start 12:31:34.138 [Biz-1-cpu-1] INFO com.crazymaker.springcloud.user.main.ReactorPrallelDemo - this taskA start 12:31:34.227 [main] DEBUG reactor.util.Loggers$LoggerFactory - Using Slf4j logging framework 12:31:34.296 [Biz-2-mixed-18] INFO com.crazymaker.springcloud.user.main.ReactorPrallelDemo - 模拟远程调用参数为101 12:31:34.296 [Biz-2-mixed-22] INFO com.crazymaker.springcloud.user.main.ReactorPrallelDemo - 模拟远程调用参数为105 12:31:34.296 [Biz-2-mixed-23] INFO com.crazymaker.springcloud.user.main.ReactorPrallelDemo - 模拟远程调用参数为106 12:31:34.296 [Biz-2-mixed-24] INFO com.crazymaker.springcloud.user.main.ReactorPrallelDemo - 模拟远程调用参数为107 12:31:34.296 [Biz-2-mixed-20] INFO com.crazymaker.springcloud.user.main.ReactorPrallelDemo - 模拟远程调用参数为103 12:31:34.296 [Biz-2-mixed-21] INFO com.crazymaker.springcloud.user.main.ReactorPrallelDemo - 模拟远程调用参数为104 12:31:34.296 [Biz-2-mixed-17] INFO com.crazymaker.springcloud.user.main.ReactorPrallelDemo - 模拟远程调用参数为100 12:31:34.296 [Biz-2-mixed-19] INFO com.crazymaker.springcloud.user.main.ReactorPrallelDemo - 模拟远程调用参数为102 12:31:34.398 [Biz-2-mixed-20] INFO com.crazymaker.springcloud.user.main.ReactorPrallelDemo - 并发执行的结果-103 12:31:34.398 [Biz-2-mixed-20] INFO com.crazymaker.springcloud.user.main.ReactorPrallelDemo - 并发执行的结果-100 12:31:34.398 [Biz-2-mixed-20] INFO com.crazymaker.springcloud.user.main.ReactorPrallelDemo - 并发执行的结果-101 12:31:34.398 [Biz-2-mixed-20] INFO com.crazymaker.springcloud.user.main.ReactorPrallelDemo - 并发执行的结果-102 12:31:34.398 [Biz-2-mixed-20] INFO com.crazymaker.springcloud.user.main.ReactorPrallelDemo - 并发执行的结果-104 12:31:34.398 [Biz-2-mixed-20] INFO com.crazymaker.springcloud.user.main.ReactorPrallelDemo - 并发执行的结果-105 12:31:34.398 [Biz-2-mixed-20] INFO com.crazymaker.springcloud.user.main.ReactorPrallelDemo - 并发执行的结果-106 12:31:34.398 [Biz-2-mixed-20] INFO com.crazymaker.springcloud.user.main.ReactorPrallelDemo - 并发执行的结果-107 12:31:34.398 [Biz-2-mixed-20] INFO com.crazymaker.springcloud.user.main.ReactorPrallelDemo - 并发远程调用异常完成 12:31:34.398 [Biz-2-mixed-20] INFO com.crazymaker.springcloud.user.main.ReactorPrallelDemo - 并发执行的时间: 105响应式Flux parallel流进行并行异步回调改造看上去已经圆满了。 终于尼恩和小伙伴实现了两个效果 并行没有线程阻塞等待异步回调 还有点问题没有解决就是底层组件是httpclient没有使用异步非阻塞的netty组件。虽然底层IO组件还是存在线程阻塞只是这个下一次迭代再说。 至少从业务维度第三次迭代之后没有线程阻塞等待。 接下来说说parallel Flux并行 流的使用场景和基础原理。因为尼恩的社群中经常有这块的生产问题被小伙伴抛出来。说明这个组件在生产场景有很大的使用价值。 parallel Flux 流的使用场景 Flux 本质上是将通量元素划分为单独的轨道元素之间是串行。 Flux parallel 模式就是将通量元素划分为并行的轨道才是真正并行的。 Flux parallel 并行流在生产场景经常用到。 下面是来自尼恩的社群50群中的一个生产问题 架构师尼恩 假设我上游有一个元素下游需要根据这个元素有多个Task处理但是需要等多个Task处理完成后才能返回如果我不用ConnectFlux的话 还有什么其他方法解决吗 类似于 Mono.just(1).map(a- { executeTaskA(a); executeTaskB(a); }).subscribe(); 我这个executeTaskA 和 executeTaskB 是并行操作的不存在依赖关系 以上这样的生产问题都可以使用并行流。 parallel Flux 的底层原理 1. parallel FLux 分配上游元素过程是 parallel操作符执行过后会生成一个新的flux 即parallelFLux。parallelFLux能够接受多个订阅者他会从原始flux中请求perfetch个元素将上游传递push过来的元素依次按顺序分配给子订阅者。 parallelFLux分配上游元素过程是 依次分配给下游每个订阅者当某个子订阅者请求数已经满足时将跳过此订阅者继续向下一个子订阅者分配。 他有两个参数 parallelism 和 prefetch parallelism 第一个参数表示划分子流的数量默认等于cpu核心数prefetch表示向原始流预取的数量。 parallel本质上是包装每个子订阅者将接受到的数据存入子订阅者的queue中然后使用线程池处理queue内的数据。 2. parallel 操作符后接 map/flapMap 操作符 map/flapMap操作符会将真实订阅者生成代理他将上游onNext的值使用map/flapMap操作符进行转换。 在parallelFlux场景下它会将每个子订阅者包装起来进行转换。 3. parallel 后面可以接 sequential 操作符 sequential 可以将parallelFlux转成普通flux 他的原理是创建parallel需要的子订阅者使用子订阅者订阅parallelFlux然后将数据依次从每个子订阅者中获取到数据向下游发送。 在sequential操作执行时数据可能来自多个线程这里采用的是哪个线程先到则负责将其他子订阅者队列中的值向下发没获取到锁的线程存入队列直接退出。 sequential允许传递参数表示每个子订阅者身上能存储的元素最大数。 4.parallel 后接 runOn 操作符 parallel本质上是包装每个子订阅者将接受到的数据存入子订阅者的queue中然后使用线程池处理queue内的数据。 runOn处理的逻辑也是和上面sequential类似使用AtomicInteger限制每个子订阅者同时只会有一个线程在执行如果当前已经存在一个线程在执行后来的数据存入queue后会直接退出。 它还可以传递第二个参数表示每个子订阅者预取的数量这里为什么要预取呢 是因为如果下游订阅者请求了非常大的数量而runOn将任务分配到线程池中本身是非堵塞的也就是任务全部堆积在线程池中可能导致内存溢出。所以使用预取参数分批次满足下游的请求数量。 第4次迭代响应式 WebClient 组件去掉底层的io线程阻塞 对于客户端调用要提升100倍没有那么容易。 路漫漫其修远尼恩团队上下求索。 虽然httpclient也支持高性能的nio 模式但是httpclient 线程模型是阻塞的httpclient没有和Netty这样的reactor反应器线程模型。 httpclient底层的io线程是阻塞式的具体如下图 Netty这样的reactor反应器线程模型底层的io线程是非阻塞式的 所以要彻底提升性能底层需要非阻塞。 如果底层的io传输也需要使用反应器线程怎么办 3个措施 那么要么使用netty要么使用基于netty的http组件。或者基于netty自己进行封组 这里使用了响应式的http组件WebClient组件。使用 WebClient 进行了第四次迭代。 为了大家能体验效果给大家提供了一段原始代码的参考程序具体如下 Test public void mergeTest7() throws InterruptedException {long startTime LocalTiker.SINGLETON.now();IterableInteger targetKeys Arrays.asList( 101, 102, 103, 104, 105);Flux.fromIterable(targetKeys).parallel().runOn(Schedulers.fromExecutorService(ThreadUtil.getMixedTargetThreadPool())).flatMap(key - doRpcUseWebClient(key)).sequential().doOnError(ReactorPrallelDemo::doOnError).doOnComplete(ReactorPrallelDemo::doOnComplete).doFinally(signalType - log.info(并发执行的时间: LocalTiker.SINGLETON.gapFrom(startTime))).subscribe(responseData - log.info(responseData.toString()), e - log.info(error: e.getMessage()));Thread.sleep(200000); }private FluxRestOutJSONObject doRpcUseWebClient(int key) {//响应式客户端WebClient client null;WebClient.RequestBodySpec request null;//方式一极简创建//方式二使用builder创建client WebClient.builder().baseUrl().defaultHeader(HttpHeaders.CONTENT_TYPE, application/json).defaultHeader(HttpHeaders.USER_AGENT, Spring 5 WebClient).build();String restUrl http://crazy.api/demo/hello/v1?key key;/*** 是通过 WebClient 组件构建请求*/request client// 请求方法.method(HttpMethod.GET)// 请求url 和 参数// .uri(restUrl, params).uri(restUrl)// 媒体的类型.accept(MediaType.APPLICATION_JSON);WebClient.ResponseSpec retrieve request.retrieve();// 处理异常 请求发出去之后判断一下返回码retrieve.onStatus(status - status.value() 404,response - Mono.just(new RuntimeException(Not Found)));ParameterizedTypeReferenceRestOutJSONObject parameterizedTypeReference new ParameterizedTypeReferenceRestOutJSONObject() {};// 返回流MonoRestOutJSONObject resp retrieve.bodyToMono(parameterizedTypeReference);return Flux.from(resp); }终于让我的 HttpClient 提速100倍 最终通过测试的验证实际效果提升了100多倍。 这里咱们从理论上计算一下这里的4次迭代为啥能够提升了100多倍 假设一次请求的10个 Web 外部服务调用每个服务调用的预定时间200ms使用了100个线程的线程池 那么100个线程同时可以并发完成10个请求1s可以并发50个请求吞吐量为 50qps 经过异步改造之后线程没有任何阻塞在网卡千兆限制范围内 和后端的吞吐量保证 下可以轻松实现5000qps甚至更多。 最终性能轻松提速了100倍。 说在最后 以上内容作为生产案例收录于《响应式圣经 V2》供大家学习和参考此书pdf电子版可以找尼恩获取。 另外很多小伙伴的小伙伴没有技术亮点可以参考这个案例做个实操然后作为一个小亮点放到简历里边。如果不会刷入简历可以来找尼恩做简历指导。 在云原生时代、高并发时代很多底层组件都开始响应式编程所以响应式编程将会越来越流行。 虽然说响应式编程虽然很晦涩难懂但是掌握了、习惯了后其实也就那么回事反而会享受响应式编程的优雅。 关于响应式编程的技术问题可以来找尼恩交流。 最后送大家一本不断迭代的电子书帮助大家在响应式时代游刃有余。 《响应式圣经10W字实现响应式编程自由 v2》 推荐阅读 《字节二面10Wqps超高流量系统如何设计》 《全链路异步让你的 SpringCloud 性能优化10倍》 《Linux命令大全2W多字一次实现Linux自由》 《阿里一面谈一下你对DDD的理解2W字帮你实现DDD自由》 《网易二面CPU狂飙900%该怎么处理》 《阿里二面千万级、亿级数据如何性能优化 教科书级 答案来了》 《峰值21WQps、亿级DAU小游戏《羊了个羊》是怎么架构的》 《场景题假设10W人突访你的系统如何做到不 雪崩》 《2个大厂 100亿级 超大流量 红包 架构方案》 《Nginx面试题史上最全 持续更新》 《K8S面试题史上最全 持续更新》 《操作系统面试题史上最全、持续更新》 《Docker面试题史上最全 持续更新》 《Springcloud gateway 底层原理、核心实战 (史上最全)》 《Flux、Mono、Reactor 实战史上最全》 《sentinel 史上最全》 《Nacos (史上最全)》 《TCP协议详解 (史上最全)》 《分库分表 Sharding-JDBC 底层原理、核心实战史上最全》 《clickhouse 超底层原理 高可用实操 史上最全》 《nacos高可用图解秒懂史上最全》 《队列之王 Disruptor 原理、架构、源码 一文穿透》 《环形队列、 条带环形队列 Striped-RingBuffer 史上最全》 《一文搞定SpringBoot、SLF4j、Log4j、Logback、Netty之间混乱关系史上最全》 《单例模式史上最全》 《红黑树 图解 秒懂 史上最全》 《分布式事务 秒懂》 《缓存之王Caffeine 源码、架构、原理史上最全10W字 超级长文》 《缓存之王Caffeine 的使用史上最全》 《Java Agent 探针、字节码增强 ByteBuddy史上最全》 《Docker原理图解秒懂史上最全》 《Redis分布式锁图解 - 秒懂 - 史上最全》 《Zookeeper 分布式锁 - 图解 - 秒懂》 《Zookeeper Curator 事件监听 - 10分钟看懂》 《Netty 粘包 拆包 | 史上最全解读》 《Netty 100万级高并发服务器配置》 《Springcloud 高并发 配置 一文全懂》
http://www.hkea.cn/news/14506229/

相关文章:

  • 广州专业网站设计公司前端网站开发实例视频
  • 您身边的网站建设专家儿童才艺网站建设模板
  • 公众号视频网站开发建电影网站程序
  • 南宁兴宁区建设局网站网络营销推广的目的
  • 怎样做关键词网站连接网站网页区别是什么
  • 网站主页作品欣赏网站开发验收资料
  • 网站3d展示怎么做手机模拟装修app
  • 服务器网站跳转怎么做兰州网站seo费用
  • 廊坊小程序公司网站建设制作设计推广优化
  • 开通域名后怎样建设网站wordpress 响应式产品展示站
  • 网站营销型浏阳市网站建设
  • 在腾讯云怎样建设网站苏州工业园区公共资源交易中心
  • x站源码免费分享网站搭建网站管理
  • 建设网站呼叫中心有什么好处医院网站建设规划书
  • 网站建设公司好做吗wordpress自定义目录
  • 网站建设论坛快速建站室内设计平面图手绘图
  • 合肥做网站123cms家里的电脑怎样做网站赚钱
  • 外贸网站如何推广出去电子商务网站的建设与维护
  • 在源码之家下载的网站模板可以作为自己的网站吗济源建设网站的公司
  • wordpress 技术类主题嘉兴做网站seo的
  • 建设门户网站培训通知商品关键词优化的方法
  • 深圳商业网站建设哪家犀牛网站建设
  • 南宁营销型网站建设哪家好域名代理商
  • 企业免费网站系统能翻到国外的浏览器
  • 广东网站备案江西短视频搜索seo推荐
  • 深圳建网站制作维护个人注册网站
  • c2c网站建设策划书电商网站建设的内容
  • 福州软件优化网站建设庆阳市建设局网站
  • 福州网站开发私人绵阳高端网站建设
  • 网站开发小程序开发公司百度广州分公司是外包吗