高并发cn.hutool.http.HttpRequest请求优化

news2024/10/5 23:55:11

高并发cn.hutool.http.HttpRequest请求优化

文章目录

  • 高并发cn.hutool.http.HttpRequest请求优化
    • 优化方向
    • @Async线程池管理
    • Http请求处理流程
    • Tomcat接收到请求后的处理流程
    • Tomcat的线程分配和管理
    • 方案一
    • 方案二
    • 方案三
    • 如何启用Spring Boot Actuator

优化方向

在这里插入图片描述

@Async线程池管理

使用@Async注解时,确实可能会遇到与线程池管理相关的问题,这些问题包括但不限于线程池过大、任务队列积压、线程泄漏等。以下是一些常见问题及其解决办法:

1.线程池过大

  • 问题:如果配置的线程池大小不合理,尤其是最大线程数(maxPoolSize)设置得过高,可能导致系统资源被过度消耗,引发内存溢出(OOM)或降低整体性能。
  • 解决办法:
    • 合理配置:根据系统实际负载和资源情况,合理设置线程池的核心线程数(corePoolSize)、最大线程数(maxPoolSize)和队列容量(如queueCapacity)。
    • 动态调整:考虑使用可动态调整大小的线程池,如ThreadPoolExecutor的allowCoreThreadTimeOut设置,允许核心线程超时回收。

2.任务队列积压

  • 问题:当线程池中的线程都在忙且任务队列已满时,新提交的任务可能会被拒绝,导致任务积压或丢失。
  • 解决办法:
    • 监控队列长度:定期检查任务队列的长度,通过监控工具或日志记录来预警。
    • 适当扩容队列:根据实际情况适度增大队列容量,但需注意这可能只是暂时缓解问题,并非根本解决办法。
    • 拒绝策略:自定义线程池的拒绝策略,比如记录日志、抛出异常、丢弃最老的任务等,以更优雅地处理拒绝的情况。

3.线程泄漏

  • 问题:如果异步任务中存在未正确关闭的资源或异常处理不当,可能导致线程无法正常回收,进而线程池中的线程数持续增长,最终耗尽系统资源。
  • 解决办法:
    • 确保任务代码健壮:确保所有资源在任务完成后都能被正确关闭,使用try-with-resources或finally块确保资源释放。
    • 异常处理:在异步方法中全面捕获并处理异常,避免因未捕获异常导致线程中断或无法完成任务。

4.默认线程池问题

  • 如前文所述,如果不自定义线程池,@Async默认使用的是SimpleAsyncTaskExecutor,它为每个任务创建新线程,容易导致线程爆炸。
  • 解决办法:始终自定义线程池配置,避免使用默认的SimpleAsyncTaskExecutor。

实践建议

  • 配置示例:在Spring Boot应用中,通过@Configuration类自定义一个TaskExecutor,并使用@EnableAsync开启异步方法支持,确保线程池配置合理且符合应用需求。
  • 监控与日志:集成监控工具,监控线程池的状态,包括活动线程数、队列长度、拒绝的任务数等,以便于及时发现并解决问题。

Http请求处理流程

一个HTTP请求从客户端打到服务器,再到服务器处理并返回响应的整个流程涉及多个环节,主要包括网络传输、服务器接收、请求解析、业务处理、响应构建和网络返回。下面详细描述这一过程,以及在Java Web应用中(以Servlet容器如Tomcat为例)线程的生成与处理情况:

1.网络传输

  • 客户端发起请求:用户通过浏览器、APP或其他HTTP客户端发起请求,请求通过互联网到达服务器。
  • DNS解析:客户端首先将域名解析为服务器的IP地址。
  • TCP连接:客户端与服务器之间建立TCP连接(三次握手)

2.服务器接收

  • 监听端口:服务器上的Web服务器(如Nginx、Apache)或应用服务器(如Tomcat、Jetty)监听特定端口(如80、443)等待请求。
  • 接收请求:服务器接收到客户端的HTTP请求包,包括请求行、请求头和可能的请求体。

3. 请求分配与线程管理

在Java Web应用中,以Tomcat为例,处理流程如下:

  • 连接器(Connector)接收请求:Tomcat的Connector组件(如HTTP/1.1 Connector)负责监听端口并接收请求。
  • 线程生成:Tomcat使用线程池模型来处理请求。默认情况下,它有一个固定的线程池Executor来管理线程。当请求到达时,从线程池中取出一个空闲线程来
  • 处理该请求。如果线程池中的线程都处于忙碌状态,且达到了最大线程数限制,超出的请求可能会被放入请求队列中等待,或根据配置直接拒绝。
  • 线程处理请求:取出的线程负责执行接下来的全部处理流程,直到响应构建完成并返回给客户端。

4. 请求解析与业务处理

  • Servlet容器:线程将请求信息封装成ServletRequest对象,然后根据URL映射找到对应的Servlet(或Spring MVC的Controller)。
  • Servlet初始化:如果Servlet尚未初始化,容器会负责它的初始化。
  • 业务逻辑处理:Servlet或Controller处理请求,可能包括数据库操作、业务计算等。此过程中,可能会涉及到Spring框架的依赖注入、AOP切面等机制。
  • 响应构建:处理完业务逻辑后,生成ServletResponse对象,填充响应内容、状态码、响应头等。

5. 响应返回

  • 响应构建完成:Servlet或Controller处理完毕后,将响应对象返回给容器。
  • 响应编码与传输:容器将响应对象转换为HTTP响应报文,通过已建立的TCP连接发送回客户端。
  • TCP连接关闭:根据HTTP协议的不同(长连接或短连接),TCP连接可能在响应发送后保持一段时间或立即关闭。

6. 线程归还

  • 处理请求的线程在完成响应构建并发送后,会将自身归还给线程池,等待处理下一个请求,从而实现线程的复用。

Tomcat接收到请求后的处理流程

当一个HTTP请求到达Spring Boot应用的Tomcat服务器时,其处理流程大致可以分为以下几个步骤,每个步骤都涉及到了特定的组件和操作:

1.请求接收与初步处理

  • 网络层面:请求首先经过网络传输,到达服务器的网络接口卡,操作系统将其从网络缓冲区读取并传递给正在监听指定端口(如8080)的Tomcat服务器。
  • Connector组件:Tomcat的Connector组件负责监听端口并接收请求。它使用Acceptor线程来接受新的连接请求,并为每个连接创建一个新的Socket对象。
  • 线程分配:Tomcat使用线程池来处理请求,从线程池中取出一个线程(通常称为工作线程)来处理该请求。这个工作线程将负责处理从接收请求到发送响应的整个过程。

2.请求解析

  • Request对象创建:Tomcat为每个请求创建一个org.apache.catalina.connector.Request对象,用于存储请求相关的所有信息,包括请求行、请求头和请求体。
  • 协议处理器:Request对象通过org.apache.coyote.ProtocolHandler(如Http11Processor)进行请求的解析,将原始的字节流转换为HTTP请求的结构化表示。

3.Servlet容器处理

  • 请求映射:Tomcat根据请求的URL映射到具体的Servlet。在Spring Boot应用中,主要通过DispatcherServlet来处理。
  • DispatcherServlet介入:DispatcherServlet是Spring MVC的核心,它继承自HttpServlet,负责请求的分发,包括路由到合适的控制器(Controller)。

4.Spring MVC处理流程

  • HandlerMapping:查找处理请求的Controller和方法。
  • Controller调用:根据映射结果,调用对应的Controller方法。
  • 参数解析:Spring MVC使用HandlerAdapter来处理参数解析、类型转换等,将请求参数绑定到方法参数上。
  • 业务逻辑处理:Controller方法执行业务逻辑,可能涉及数据库操作、服务调用等。
  • 视图解析:如果Controller返回一个视图名,Spring MVC会使用ViewResolver来解析视图,并准备渲染数据。
  • 响应构建:根据视图和数据,生成HTTP响应内容。

5.响应处理与发送

  • 响应对象填充:响应内容被填充到ServletResponse对象中。
  • Tomcat处理响应:Tomcat的Response对象根据ServletResponse的内容,构建HTTP响应报文。
  • 网络传输:工作线程通过Socket将响应报文发送回客户端,完成一次HTTP交互。

6.线程归还

  • 线程回收:处理完请求的工作线程会归还给线程池,等待处理下一个请求,实现了线程的复用。

总结

从接收请求到响应的整个流程中,Tomcat作为Servlet容器,负责了请求的接收、解析、分发,

而Spring MVC框架则专注于请求的具体处理逻辑,包括路由、业务处理、视图渲染等。两者协同工作,实现了HTTP请求的高效处理。

Tomcat的线程分配和管理

Tomcat的线程分配和管理主要通过其连接器(Connector)组件实现,特别是与协议处理器(Coyote)相关的部分。以下是对Tomcat线程模型的一个概述以及涉及到的主要源码解析:

线程模型概览

Tomcat支持多种线程模型,包括BIO(阻塞I/O)、NIO(非阻塞I/O)、APR(Apache Portable Runtime,基于本地库)和NIO2。每种模型在处理请求的方式和线程使用上有所不同,但核心都是围绕着接收请求、分配工作线程处理请求、响应客户端这一流程。

线程模型配置

在server.xml配置文件中,可以设置Connector的协议以选择不同的线程模型,例如:

<Connector port="8080" protocol="org.apache.coyote.http11.Http11NioProtocol"/>

这里protocol属性指定了使用的协议处理器。

线程池配置

Tomcat通常使用线程池来管理线程,可以在Connector元素内配置线程池参数,如maxThreads(最大线程数)、minSpareThreads(最小空闲线程数)等。

源码解析

1.初始化线程池

线程池的初始化通常发生在org.apache.coyote.AbstractProtocol.init()方法中,这个方法会被各个具体协议的初始化调用。例如,对于NIO协议,Http11NioProtocol类会调用其父类AbstractProtocol的init()方法来初始化线程池。

2.接收连接

NIO:在NIO模式下,org.apache.tomcat.util.net.NioEndpoint负责接收连接。它使用Java NIO的Selector来监听多个通道的事件,当有新的连接或读写事件发生时,会触发相应的事件处理器。

3.分配线程处理请求

当接收到一个新的请求时,NioEndpoint会从线程池中获取一个线程来处理这个请求。线程的获取通常通过org.apache.tomcat.util.threads.ThreadPoolExecutor实现,这是Tomcat内部对Java标准ThreadPoolExecutor的封装。

4.请求处理

获取到线程后,会创建一个org.apache.coyote.Request对象来封装HTTP请求,并创建一个org.apache.coyote.Response对象来准备响应。然后,这些对象会传递给Coyote处理器(如org.apache.coyote.http11.Http11Processor),处理器通过调用容器(如org.apache.catalina.Container层次结构)来实际处理请求。

5…线程回收

处理完请求后,工作线程会返回线程池等待下一次任务分配。如果线程池中的线程数量超过maxSpareThreads,超出的线程可能会被回收以节省资源。

6.流量控制

Tomcat可以通过调整线程池参数进行流量控制。例如,增加maxThreads可以提高并发处理能力,但过多的线程也会消耗更多系统资源。同时,合理设置acceptCount(排队请求的最大数)可以防止在所有线程都忙碌时,新进来的连接直接被拒绝,而是让它们排队等待。

7.异步支持

Tomcat还支持Servlet 3.0引入的异步处理,这允许工作线程在等待某些操作(如数据库查询)完成时释放,从而提高线程利用率和系统吞吐量。
综上所述,Tomcat的线程分配流程涉及到了多个组件和配置的协作,通过灵活配置和源码理解,可以更好地优化Web应用的性能。

yaml

server:
  port: 8080 # 修改HTTP服务端口
  servlet:
    context-path: /myapp # 应用上下文路径,便于区分不同应用
    session:
      timeout: 30m # 会话超时时间,根据需要调整
  tomcat:
    uri-encoding: UTF-8 # 设置URI编码,避免中文乱码问题
    max-threads: 500 # Tomcat最大工作线程数,根据硬件和负载情况调整
    min-spare-threads: 50 # 最小空闲线程数,保证快速响应
    accept-count: 100 # 队列中允许的最大连接数,超过将拒绝连接
    connection-timeout: 20000 # 连接超时时间(毫秒)
    max-connections: 10000 # 最大连接数,限制同时连接的数量
    max-http-post-size: 100MB # 最大POST数据大小,根据业务需求调整
    basedir: ./tmp/tomcat # Tomcat工作目录,可自定义以隔离临时文件

参数说明

  • server.port: 修改应用的监听端口。
  • server.servlet.context-path: 设置应用的上下文路径,有助于部署在同一个域名下的多个应用区分。
  • server.servlet.session.timeout: 调整会话过期时间,避免长时间无活动会话占用资源。
  • server.tomcat.uri-encoding: 确保正确的字符编码,避免中文等非ASCII字符乱码。
  • server.tomcat.max-threads: 增加最大工作线程数可以提升并发处理能力,但需注意不要超出系统资源限制。
  • server.tomcat.min-spare-threads: 保证有足够的线程随时待命,减少请求等待时间。
  • server.tomcat.accept-count: 当所有线程都在使用且队列已满时,新的连接请求将被拒绝,合理设置可以避免服务过载。
  • server.tomcat.connection-timeout: 控制连接的超时时间,过长可能导致资源占用,过短则可能中断还在处理中的请求。
  • server.tomcat.max-connections: 限制了同时可以建立的连接数,防止过多连接导致的服务崩溃。
  • server.tomcat.max-http-post-size: 调整POST请求体的最大大小,适用于上传大文件等场景。
  • server.tomcat.basedir: 自定义Tomcat的工作目录,便于管理和清理临时文件。

调整这些参数时,请根据实际的硬件资源、预期的并发量和应用特性来决定最佳值,避免过度优化导致资源浪费或服务不稳定。

方案一

考虑到企业级应用的需求,以下是一个使用Hutool的HttpClient进行优化的示例代码,结合了连接池管理、异步请求和简单的异常处理逻辑。请注意,实际部署时还需根据具体业务需求调整,并且考虑引入日志、监控以及进一步的异常处理和资源管理策略。

import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpClient;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.Method;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class HighPerformanceHttpRequestExample {

    // 初始化一个线程池,根据实际情况调整线程数量
    private static final ExecutorService executor = Executors.newFixedThreadPool(100);

    // 配置HttpClient连接池
    private static final HttpClient httpClient = HttpClient.create()
            .setConnectionTimeout(5000) // 连接超时时间
            .setReadTimeout(5000)       // 读取超时时间
            // 根据实际情况调整最大连接数等其他参数
            ;

    public static void main(String[] args) {
        String apiUrl = "http://example.com/api/data";

        // 异步发送请求
        Future<HttpResponse> future = executor.submit(() -> sendRequest(apiUrl));

        try {
            HttpResponse response = future.get(); // 获取响应结果,这里简化处理未捕获InterruptedException和ExecutionException
            if (response.isOk()) {
                String result = response.body();
                System.out.println("Response: " + result);
            } else {
                System.err.println("Error: " + response.getStatus());
            }
        } catch (Exception e) {
            e.printStackTrace();
            // 异常处理逻辑
        }
    }

    /**
     * 使用HttpClient发送请求
     */
    private static HttpResponse sendRequest(String url) {
        try {
            return httpClient.execute(Method.GET, url);
        } catch (Exception e) {
            // 日志记录或其它异常处理逻辑
            System.err.println("Request failed for URL: " + url);
            e.printStackTrace();
            return null;
        }
    }

此示例展示了如何使用Hutool的HttpClient进行异步请求,并通过线程池管理并发执行的请求。请根据实际需求调整线程池大小、超时时间等参数,并确保有适当的异常处理机制和日志记录,以便于监控和故障排查。在生产环境中,还需要考虑更多的因素,如安全性(如HTTPS、证书校验)、重试机制、请求与响应的压缩等。

方案二

<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.8.13</version> <!-- 根据最新版本调整 -->
</dependency>
hutool:
  http:
    client:
      max-total: 500 # 最大连接数
      default-max-per-route: 100 # 每路由最大连接数
      connect-timeout: 5000 # 连接超时时间(毫秒)
      socket-timeout: 5000 # 读取超时时间(毫秒)
@Configuration
@ConfigurationProperties(prefix = "hutool.http.client")
public class HttpClientConfig {

    private int maxTotal;
    private int defaultMaxPerRoute;
    private int connectTimeout;
    private int socketTimeout;

    public HttpClient getClient() {
        return HttpClient.create()
                .setMaxTotal(maxTotal)
                .setDefaultMaxPerRoute(defaultMaxPerRoute)
                .setConnectionTimeout(connectTimeout)
                .setReadTimeout(socketTimeout);
    }

    // Getter and Setter 省略
}

setMaxDefaultPerRoute方法是Apache HttpClient库中用于配置连接管理器(PoolingHttpClientConnectionManager)的一个重要设置项,它用来控制每个路由(route)上默认的最大连接数。这个配置对于管理连接池、优化网络资源利用以及避免对单一主机的过度连接非常重要。下面详细解释这个方法及其作用:

基本概念

在HttpClient中,一个“路由”(route)指的是到特定目标主机(由主机名和端口号唯一确定)的连接路径。当HttpClient发起请求到不同的主机时,它会根据目标主机创建不同的路由。因此,setMaxDefaultPerRoute设置的是针对每个独立路由的最大连接数,而不是全局的总连接数。

方法说明

  • 方法签名:void setMaxPerRoute(HttpRoute route, int maxConnections)
  • 或者更常见的使用方式是在PoolingHttpClientConnectionManager中设置默认值:
  connectionManager.setMaxTotal(maxTotal);
  connectionManager.setDefaultMaxPerRoute(maxPerRoute);
  • 参数解释:
    • route:指定的路由对象,如果不指定,则通过setDefaultMaxPerRoute(int maxConnections)设置所有路由的默认最大连接数。
    • maxConnections:指定的路由上允许的最大连接数。
  • 作用:
    • 确保对于特定目标主机,不会因为过多的并发连接而耗尽资源或违反远程服务器的连接限制。
    • 平衡连接的使用,避免因少数几个繁忙的路由占用了所有可用连接,导致其他路由无法建立连接。

实例配置

PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager();
connectionManager.setMaxTotal(100); // 设置整个连接池的最大连接数
connectionManager.setDefaultMaxPerRoute(10); // 设置默认每个路由的最大连接数为10

// 对于特定的路由(比如需要20个连接的那个服务器),可以单独设置
HttpRoute specificRoute = new HttpRoute(new HttpHost("specific-api.example.com", 80));
connectionManager.setMaxPerRoute(specificRoute, 20);

CloseableHttpClient httpClient = HttpClients.custom()
        .setConnectionManager(connectionManager)
        .build();

注意事项

  • setMaxTotal方法设置了整个连接池的最大连接数,它是setDefaultMaxPerRoute设置的上限。
  • 如果某些特定路由需要的连接数超过默认值,应使用setMaxPerRoute(HttpRoute route, int maxConnections)单独配置。
  • 合理设置这两个参数可以有效管理连接资源,避免资源耗尽或因连接过多而被服务器拒绝服务。

通过精细配置setMaxDefaultPerRoute,开发者能够根据目标服务器的要求和应用的实际需求,高效地管理HttpClient的连接池,从而提升应用的稳定性和性能。

使用Spring的@Async注解实现异步处理,并通过注入配置好的HttpClient实例:

@Service
public class AsyncRequestService {

    @Autowired
    private HttpClientConfig httpClientConfig;

    @Async
    public Future<String> fetchRemoteData(String url) {
        try {
            HttpResponse response = httpClientConfig.getClient().executeGet(url);
            if (response.isOk()) {
                return new AsyncResult<>(response.body());
            } else {
                log.error("Failed to fetch data from {}: {}", url, response.getStatus());
                return new AsyncResult<>("Error: " + response.getStatus());
            }
        } catch (Exception e) {
            log.error("Async request error for {}: ", url, e);
            return new AsyncResult<>("Error: " + e.getMessage());
        }
    }
}

在控制器中调用异步服务,并通过Spring Boot Actuator监控性能指标。

@RestController
public class DataController {

    @Autowired
    private AsyncRequestService asyncRequestService;

    @GetMapping("/fetchData")
    public Callable<String> fetchDataFromExternalApi() {
        String apiUrl = "http://example.com/api/data";
        return () -> asyncRequestService.fetchRemoteData(apiUrl).get();
    }
}

注意事项

  • 通过Spring Boot Actuator监控HttpClient的性能和健康状况。
  • 确保异步处理的线程池配置合理,避免资源耗尽。
  • 考虑使用@Retryable注解实现请求失败的自动重试机制。
  • 在生产环境中,进一步细化异常处理逻辑,确保系统稳定性。
  • 以上示例展示了如何在Spring Boot应用中使用Hutool的HttpClient进行高效、可维护的HTTP请求处理,同时结合Spring的特性进行了性能和可扩展性的优化。

方案三

1. 添加线程池配置

spring:
  task:
    execution:
      pool:
        core-size: 20 # 核心线程数
        max-size: 100 # 最大线程数
        queue-capacity: 500 # 队列容量
        keep-alive: 60s # 空闲线程存活时间
        thread-name-prefix: async- # 线程名称前缀

2. 自定义线程池配置类(可选)

@Configuration
public class ThreadPoolConfig implements AsyncConfigurer {

    @Override
    public Executor getAsyncExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(20);
        executor.setMaxPoolSize(100);
        executor.setQueueCapacity(500);
        executor.setThreadNamePrefix("async-");
        executor.initialize();
        return executor;
    }

    // 可选:自定义异常处理器
    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return (throwable, method, obj) -> {
            log.error("Async method execution failed: {}, Method={}, Params={}", throwable.getMessage(), method.getName(), obj);
        };
    }
}

3. 更新AsyncRequestService

@Service
public class AsyncRequestService {

    @Autowired
    private HttpClientConfig httpClientConfig;

    @Async
    public Future<String> fetchRemoteData(String url) {
        try {
            HttpResponse response = httpClientConfig.getClient().executeGet(url);
            if (response.isOk()) {
                return CompletableFuture.completedFuture(response.body());
            } else {
                log.error("Failed to fetch data from {}: {}", url, response.getStatus());
                return CompletableFuture.completedFuture("Error: " + response.getStatus());
            }
        } catch (Exception e) {
            log.error("Async request error for {}: ", url, e);
            return CompletableFuture.completedFuture("Error: " + e.getMessage());
        }
    }
}

4. 监控与日志

确保应用中已启用Spring Boot Actuator,并通过访问/actuator端点查看线程池状态。同时,利用日志记录异步任务的执行情况和异常,以便于监控和调试。

如何启用Spring Boot Actuator

1. 添加依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

2. 基本配置

management:
  endpoints:
    web:
      exposure:
        include: '*' # 曝光所有端点,生产环境应根据需要选择
  endpoint:
    health:
      show-details: always # 显示健康检查的详细信息

3. 访问端点

http://localhost:8080/actuator/health
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.health.Health;
import org.springframework.stereotype.Service;

@Service
public class HealthInfoService {

    @Autowired
    private HealthEndpoint healthEndpoint;

    public Health getHealthInfo() {
        return healthEndpoint.health();
    }
}
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class CustomHealthController {

    @Autowired
    private HealthInfoService healthInfoService;

    @GetMapping("/customHealthCheck")
    public ResponseEntity<?> customHealthCheck() {
        Health health = healthInfoService.getHealthInfo();
        // 根据需要转换Health对象为自定义的DTO或直接返回
        // 这里简单地将Health对象转为Map,实际应用中可能需要更复杂的转换逻辑
        return ResponseEntity.ok(health.getDetails());
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1857445.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

用户态协议栈06-TCP三次握手

最近由于准备软件工程师职称考试&#xff0c;然后考完之后不小心生病了&#xff0c;都没写过DPDK的博客了。今天开始在上次架构优化的基础上增加TCP的协议栈流程。 什么是TCP 百度百科&#xff1a;TCP即传输控制协议&#xff08;Transmission Control Protocol&#xff09;是…

24 常用到的截图工具

1 语录 从此世界在我面前&#xff0c; 指向着我想去的任何地方&#xff0c; 我完全而绝对的主持着我 定义&#xff1a; 截图是将计算机屏幕上的当前显示内容保存为图片文件的行为。 概念&#xff1a; 全屏截图&#xff1a;捕捉整个屏幕的截图。区域截图&#xff1a;选择屏幕上…

【第十四课】区域经济可视化——标注

一、前言 地图上说明图面要素的名称、质量与数量特征的文字或数字&#xff0c;统称为地图 注记。只有图形符号而没有注记符号的地图&#xff0c;只能是一种令人费解的 “盲图”。 地图上的注记分为名称注记、说明注记和数字注记三种。名称注记用于说明各 种事物的专有名称&…

怎么使用RSI指标分析现货黄金行情走势?

拿到一波现货黄金行情走势&#xff0c;如何着手对其进行分析呢&#xff1f;投资者只要在网络上搜索一下&#xff0c;保管能够找到各种各样的答案&#xff0c;而本文要讨论的就是其中一种&#xff0c;我们借助RSI指标进行分析。 RSI就是相对强弱指标的简称&#xff0c;这是市场中…

车间现场管理那些事

在制造企业中&#xff0c;车间现场管理是至关重要的一环。车间现场管理包括了对生产设备、生产过程、产品质量以及员工行为的管理。有效的车间现场管理能够提高生产效率&#xff0c;降低成本&#xff0c;提高产品质量&#xff0c;并且能够保障员工的安全。那么&#xff0c;车间…

License简介和Licensecc的使用

License简介和Licensecc的使用 License简介什么是LIcense简易License制作加密扫盲对称加密非对称加密 Licensecc使用构建和编译在linux上进行编译UbuntuCentOS 7CentOS 8下载并编译配置编译和测试cmake 后可以跟的参数在Linux上为Windows进行交叉编译 在windos上进行编译MSVC (…

Linux 运维王者从不离手的10款工具

运维工程师在日常工作中频繁运用的10款工具&#xff0c;并细致阐述每款工具的功能、适用场景以及其卓越之处。 1. Shell脚本 功能&#xff1a;主要用于自动化任务和批处理作业。 适用场景&#xff1a;频繁用于文件处理、系统管理、简单的网络管理等操作。 优势&#xff1a;灵…

原装GUVCL-T10GD韩国GENICOM光电二极管紫外线传感器原厂代理商

深圳市宏南科技有限公司是韩国GenUV公司的原厂代理商&#xff0c;所售紫外线传感器均来自于原始生产厂商直接供货&#xff0c;非第三方转售。 GUVCL-T10GD 韩国GENICOM光电二极管光传感器 / 低亮度 / 紫外线 UV-C传感器 GUVCL-T10GD 采用基于氮化铟的材料 肖特基型 光电二极管…

竞赛选题 python 机器视觉 车牌识别 - opencv 深度学习 机器学习

1 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 基于python 机器视觉 的车牌识别系统 &#x1f947;学长这里给一个题目综合评分(每项满分5分) 难度系数&#xff1a;3分工作量&#xff1a;3分创新点&#xff1a;3分 &#x1f9ff; 更多资…

机器学习之Kmeans丨集成学习丨决策树测试

选择题 下面属于决策树的后剪枝的是&#xff1f;【 正确答案: A】 A. 把数据集分成测试集和训练集&#xff0c;用测试集构建一个足够大的决策树&#xff0c;用测试集判断叶节点合并是否能降低误差。 B. 当树到达一定深度的时候停止生长。 C. 当前节点的样本数量小于某个阈值时&…

node.js游戏网站-计算机毕业设计源码031726

摘 要 基于网络游戏的蓬勃发展&#xff0c;游戏网站发挥着吸引玩家和提高玩家之间的互动性的重要作用&#xff0c;因而&#xff0c;建设了一个以游戏为中心的游戏官网。 该游戏提供了一个大型的玩家交流互动平台&#xff0c;包括用户管理、游戏社区、游戏信息、分类信息、游戏资…

蓝卓基于三大服务全“数”推进成渝工业互联网一体化

面向成渝地区的产业特色&#xff0c;蓝卓正不断提供多行业、多场景、多维度的解决方案&#xff0c;通过最佳实践、标杆案例&#xff0c;为企业数字化转型提供可参考的示范效应。 系统解决方案服务涵盖智能石化、汽配行业、智慧大数据等解决方案。以汽配行业为例&#xff0c;针对…

EcmaScript6全新语法特性-----EcmaScript6

{ // var会越狱,但是let会有作用域 var a 1; let b 2; } var m 1; var m 2; // var变量可以多次声明,但是let只能声明一次 let n 1; // let n 2; // var声明的变量会自动提升,这里没有就会显示undefined console.log(x); var x 10; // let变量不会变化,没有就报错 // co…

FISCO BCOS跨境应用获评工信部2024年新型数字服务优秀案例

6月18日&#xff0c;国家工信部公布2024年新型数字服务优秀案例名单&#xff0c;由前海管理局报送的“基于区块链技术打造深港跨境数据验证平台促进深港数据高效可信流动”案例入选。 随着深港合作的深入推进&#xff0c;FISCO BCOS发挥国产关键技术优势&#xff0c;持续助力深…

医院信创数字化运营平台,办公、院务、内控全面数字化,低代码拓展应用、安全可控

随着政策与技术的双重驱动&#xff0c;医院OA需求已经从传统的协同办公&#xff0c;转向信创环境下的运营、管理、服务的全程数字化、智能化。目前&#xff0c;医院信创建设全面展开&#xff0c;信创需求不断增加。 01.医院数字化信创建设政策 共同助力医院的高质量发展 医疗…

【DS Solutions】一个反欺诈产品的进化,Stripe Radar

Stripe Radar 是 Stripe 提供的一项防欺诈服务&#xff0c;它利用机器学习技术来帮助商家检测和阻止信用卡欺诈行为。这篇文章是Stripe公司关于其反欺诈解决方案Stripe Radar的构建过程的介绍。文章从Stripe的防欺诈团队工程师的角度出发&#xff0c;详细讲述了Stripe Radar的工…

精益管理咨询公司在与企业沟通时,应该如何展示自己的专业性?

在竞争激烈的商业环境中&#xff0c;精益管理咨询公司扮演着至关重要的角色。它们不仅为企业提供策略性的指导&#xff0c;还帮助企业实现资源的优化配置&#xff0c;从而达到提高效率、降低成本的目的。那么&#xff0c;精益管理咨询公司在与企业沟通时&#xff0c;应该如何展…

西部证券:1+1>2?

又一起券商收购拉开帷幕&#xff0c;证券业并购浪潮呼之欲出。 这次是——西部证券。 最近&#xff0c;西部证券公告称&#xff0c;因自身发展需要正在筹划收购国融证券控股权事项&#xff0c; 这是继“浙商国都”、“国联民生”、“华创太平洋”之后&#xff0c;今年券商并购…

抓包工具whistle的安装和使用

whistle基于Node实现的跨平台web调试代理工具&#xff0c;类似的工具有Windows平台上的Fiddler&#xff0c;主要用于查看、修改HTTP、HTTPS、Websocket的请求、响应&#xff0c;也可以作为HTTP代理服务器使用。 一、安装 whistle&#xff0c;没有cnpm的可以先安装下或者直接使…

测评四款AI视频热门神器,没想到最好用的竟然是它!

在这个科技飞速发展的时代&#xff0c;AI视频工具已经成为我们创意与想象的最佳拍档。今天&#xff0c;就让我们一起走进2024年最热门的四款AI视频工具&#xff0c;看看它们如何为我们的创作插上翅膀&#xff01;今天&#xff0c;就让我们一起走进2024年最热门的四款AI视频工具…