WebClient 同步、异步调用实现对比

//goto docker\docker-compose.yml version: '3.7' services: hello: image: registry.cn-shanghai.aliyuncs.com/00fly/web-client:0.0.1 container_name: web-client deploy: resources: limits: cpus: '1' memory: 200M reservations: cpus: '0.05' memory: 100M environment: JAVA_OPTS: -server -Xms100m -Xmx100m -Djava.security.egd=file:/dev/./urandom restart: on-failure logging: driver: json-file options: max-size: 5m max-file: '1' //goto docker\restart.sh #!/bin/bash docker-compose down && docker system prune -f && docker-compose up -d && docker stats //goto docker\stop.sh #!/bin/bash docker-compose down //goto Dockerfile FROM openjdk:8-jre-alpine RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo 'Asia/Shanghai' >/etc/timezone COPY target/web-client-*.jar /app.jar ENTRYPOINT ["java","-jar","/app.jar"] //goto pom.xml <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.fly</groupId> <artifactId>web-client</artifactId> <version>0.0.1</version> <name>web-client</name> <packaging>jar</packaging> <properties> <docker.hub>registry.cn-shanghai.aliyuncs.com</docker.hub> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <java.version>1.8</java.version> <skipTests>true</skipTests> </properties> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webflux</artifactId> <version>5.2.3.RELEASE</version> </dependency> <dependency> <groupId>io.projectreactor.netty</groupId> <artifactId>reactor-netty</artifactId> <version>0.9.4.RELEASE</version> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-slf4j-impl</artifactId> <version>2.12.1</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.13.0</version> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>3.10</version> </dependency> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.5</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.12</version> <scope>provided</scope> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency> </dependencies> <build> <finalName>${project.artifactId}-${project.version}</finalName> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.10.1</version> <configuration> <source>1.8</source> <target>1.8</target> <encoding>UTF-8</encoding> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>3.4.0</version> <configuration> <createDependencyReducedPom>false</createDependencyReducedPom> </configuration> <executions> <execution> <phase>package</phase> <goals> <goal>shade</goal> </goals> <configuration> <minimizeJar>false</minimizeJar> <filters> <filter> <artifact>*:*</artifact> </filter> </filters> <transformers> <!--MANIFEST文件中写入Main-Class是可执行包的必要条件。ManifestResourceTransformer可以轻松实现。 --> <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> <mainClass>com.fly.http.RunMain</mainClass> </transformer> </transformers> </configuration> </execution> </executions> </plugin> <!-- 添加docker-maven插件 --> <plugin> <groupId>io.fabric8</groupId> <artifactId>docker-maven-plugin</artifactId> <version>0.40.0</version> <executions> <execution> <phase>package</phase> <goals> <goal>build</goal> <goal>push</goal> <goal>remove</goal> </goals> </execution> </executions> <configuration> <!-- 连接到带docker环境的linux服务器编译image --> <!-- <dockerHost>http://192.168.182.10:2375</dockerHost> --> <!-- Docker 推送镜像仓库地址 --> <pushRegistry>${docker.hub}</pushRegistry> <images> <image> <name> ${docker.hub}/00fly/${project.artifactId}:${project.version}</name> <build> <dockerFileDir>${project.basedir}</dockerFileDir> </build> </image> </images> </configuration> </plugin> </plugins> </build> </project> //goto src\main\java\com\fly\http\FluxWebClient.java package com.fly.http; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; import org.apache.commons.lang3.RandomUtils; import org.apache.commons.lang3.StringUtils; import org.springframework.http.MediaType; import org.springframework.web.reactive.function.client.WebClient; import lombok.extern.slf4j.Slf4j; /** * WebClient是RestTemplete的替代品,有更好的响应式能力,支持异步调用<br> * * https://blog.****.net/zzhongcy/article/details/105412842 * */ @Slf4j public class FluxWebClient { private List<String> urls = new ArrayList<>(); // 缓冲区默认256k,设为-1以解决报错Exceeded limit on max bytes to buffer : 262144 private WebClient webClient = WebClient.builder().codecs(configurer -> configurer.defaultCodecs().maxInMemorySize(-1)).build(); public void visitAll() { // block转换为同步调用 if (urls.isEmpty()) { log.info("★★★★★★★★ urls isEmpty, now get urls from api ★★★★★★★★"); String resp = webClient.get().uri("https://00fly.online/upload/urls.txt").acceptCharset(StandardCharsets.UTF_8).accept(MediaType.TEXT_HTML).retrieve().bodyToMono(String.class).block(); urls = Arrays.asList(StringUtils.split(resp, "\r\n")); } // 异步访问 AtomicInteger count = new AtomicInteger(0); urls.stream() .filter(url -> RandomUtils.nextBoolean()) .forEach(url -> webClient.get() .uri(url) .acceptCharset(StandardCharsets.UTF_8) .accept(MediaType.TEXT_HTML) .retrieve() .bodyToMono(String.class) .subscribe(r -> log.info("process complted: {}. {}", count.incrementAndGet(), url), e -> log.error(e.getMessage()))); log.info("total:{} ==> ############## 异步请求已提交 ##############", urls.size()); } } //goto src\main\java\com\fly\http\RunMain.java package com.fly.http; import java.util.Timer; import java.util.TimerTask; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; @Slf4j public class RunMain { private static FluxWebClient webClient = new FluxWebClient(); /** * 程序运行入口 * */ public static void main(String[] args) { scheduledThreadPoolExecutorStart(); } private static void scheduledThreadPoolExecutorStart() { new ScheduledThreadPoolExecutor(2).scheduleAtFixedRate(() -> { webClient.visitAll(); }, 0L, 30, TimeUnit.SECONDS); log.info("======== ScheduledThreadPoolExecutor started!"); } /** * Timer线程安全, 但单线程执行, 抛出异常时, task会终止 */ @Deprecated protected static void timeStart() { new Timer().scheduleAtFixedRate(new TimerTask() { @Override public void run() { webClient.visitAll(); } }, 0L, 30 * 1000L); log.info("======== Timer started!"); } } //goto src\main\resources\log4j2.xml <?xml version="1.0" encoding="UTF-8"?> <configuration status="off" monitorInterval="0"> <appenders> <console name="Console" target="system_out"> <patternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} %5p %pid --- [%t] %-30.30c{1.} : %m%n" /> </console> </appenders> <loggers> <root level="INFO"> <appender-ref ref="Console" /> </root> </loggers> </configuration> //goto src\test\java\com\fly\http\ApiTest.java package com.fly.http; import java.awt.Desktop; import java.io.ByteArrayInputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.nio.charset.StandardCharsets; import java.util.Arrays; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; import
上一篇:CSS案例-2.简单版侧边栏练习-知识点


下一篇:Vue中slot是什么?有什么作用?原理是什么?