• 引言:微服务通信的演进之路
    • 什么是OpenFeign?
      • 核心特性概览
    • 快速开始:搭建OpenFeign环境
      • 环境准备与依赖配置
      • 启用OpenFeign功能
    • 基础用法:从简单示例开始
      • 定义第一个Feign客户端
      • 在服务中调用Feign客户端
    • 进阶配置:深度定制OpenFeign
      • 自定义配置类
      • 应用配置示例
    • 高级特性:提升系统可靠性
      • 熔断降级机制
      • 请求拦截器
    • 性能优化:提升通信效率
      • 连接池配置
      • GZIP压缩配置
    • 实战案例:电商系统中的应用
      • 服务间调用示例
    • 常见问题与解决方案
      • 1. 序列化问题
      • 2. 复杂参数传递
      • 3. 文件上传支持
    • 监控与诊断
      • 日志配置
      • 分布式追踪集成
    • 核心原理
      • 核心组件
      • 工作流程
      • 工作流程总结

引言:微服务通信的演进之路

在微服务架构中,服务间的通信是系统设计的核心挑战之一。从最初的HttpClient到RestTemplate,再到如今的声明式HTTP客户端,微服务通信方式经历了显著的演进。Spring Cloud OpenFeign作为声明式REST客户端的优秀实现,正在重新定义微服务间的通信方式。

传统的HTTP客户端使用方式存在诸多痛点:需要手动构建URL、处理序列化/反序列化、处理异常、管理连接池等。这些重复性工作不仅降低了开发效率,还容易引入错误。OpenFeign的出现彻底改变了这一现状,让开发者能够专注于业务逻辑,而不是通信细节。

什么是OpenFeign?

OpenFeign是一个基于Java的声明式HTTP客户端,最初由Netflix开发并开源,后来成为Spring Cloud生态系统的重要组成部分。它通过简单的接口和注解,将HTTP请求转化为Java方法调用,极大地简化了微服务间的通信。

核心特性概览

  • 声明式API:通过接口和注解定义HTTP请求
  • 服务发现集成:无缝集成Eureka、Consul、Nacos等服务注册中心
  • 负载均衡:内置客户端负载均衡功能
  • 熔断降级:支持Hystrix和Resilience4j熔断机制
  • 灵活配置:支持全局和客户端级别的细粒度配置

快速开始:搭建OpenFeign环境

环境准备与依赖配置

首先在Spring Boot项目中添加OpenFeign依赖:

<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId><version>3.0.3</version>
</dependency><!-- 可选:增强的HTTP客户端 -->
<dependency><groupId>io.github.openfeign</groupId><artifactId>feign-okhttp</artifactId><version>11.0</version>
</dependency>

启用OpenFeign功能

在主应用类上添加@EnableFeignClients注解:

@SpringBootApplication
@EnableFeignClients
public class Application {public static void main(String[] args) {SpringApplication.run(Application.class, args);}
}

基础用法:从简单示例开始

定义第一个Feign客户端

@FeignClient(name = "user-service", url = "http://localhost:8080")
public interface UserFeignClient {@GetMapping("/users/{id}")ResponseEntity<User> getUserById(@PathVariable Long id);@PostMapping("/users")ResponseEntity<User> createUser(@RequestBody User user);@GetMapping("/users")ResponseEntity<List<User>> getAllUsers();
}

在服务中调用Feign客户端

@Service
@RequiredArgsConstructor
public class OrderService {private final UserFeignClient userFeignClient;public Order createOrder(Long userId, OrderRequest request) {// 调用用户服务验证用户信息ResponseEntity<User> response = userFeignClient.getUserById(userId);User user = response.getBody();if (user != null && user.isActive()) {Order order = new Order();order.setUserId(userId);order.setAmount(request.getAmount());return orderRepository.save(order);}throw new BusinessException("用户不存在或未激活");}
}

进阶配置:深度定制OpenFeign

自定义配置类

@Configuration
public class FeignConfig {/*** 配置日志级别* NONE: 不记录任何日志* BASIC: 仅记录请求方法、URL、响应状态码和执行时间* HEADERS: 记录BASIC级别信息+请求和响应头信息* FULL: 记录所有请求和响应明细*/@BeanLogger.Level feignLoggerLevel() {return Logger.Level.FULL;}/*** 配置连接超时和读取超时*/@Beanpublic Request.Options options() {return new Request.Options(5, TimeUnit.SECONDS, 10, TimeUnit.SECONDS, true);}/*** 配置重试机制*/@Beanpublic Retryer retryer() {return new Retryer.Default(100, 1000, 3);}
}

应用配置示例

feign:client:config:default:  # 全局默认配置connectTimeout: 5000readTimeout: 10000loggerLevel: basicuser-service:  # 特定服务配置connectTimeout: 3000readTimeout: 5000loggerLevel: fulllogging:level:com.example.clients.UserFeignClient: DEBUG

高级特性:提升系统可靠性

熔断降级机制

// 1. 定义Fallback类
@Component
@Slf4j
public class UserFeignFallback implements UserFeignClient {@Overridepublic ResponseEntity<User> getUserById(Long id) {log.warn("用户服务不可用,返回默认用户信息");return ResponseEntity.ok(User.createDefaultUser(id));}@Overridepublic ResponseEntity<User> createUser(User user) {throw new ServiceUnavailableException("用户服务暂时不可用");}
}// 2. 配置Fallback
@FeignClient(name = "user-service",url = "${feign.client.user-service.url}",fallback = UserFeignFallback.class
)
public interface UserFeignClient {// 接口方法
}

请求拦截器

@Component
public class AuthRequestInterceptor implements RequestInterceptor {@Overridepublic void apply(RequestTemplate template) {// 添加认证令牌String token = getAuthToken();template.header("Authorization", "Bearer " + token);// 添加追踪IDtemplate.header("X-Request-ID", UUID.randomUUID().toString());}private String getAuthToken() {// 从安全上下文中获取令牌Authentication authentication = SecurityContextHolder.getContext().getAuthentication();if (authentication != null && authentication.getCredentials() instanceof String) {return (String) authentication.getCredentials();}return "";}
}

性能优化:提升通信效率

连接池配置

# 使用OKHttp连接池
feign:okhttp:enabled: truehttpclient:enabled: false# 连接池配置
okhttp:max-idle-connections: 200keep-alive-duration: 300connect-timeout: 3000read-timeout: 10000

GZIP压缩配置

feign:compression:request:enabled: truemime-types: text/xml,application/xml,application/jsonmin-request-size: 2048response:enabled: true

实战案例:电商系统中的应用

服务间调用示例

// 商品服务客户端
@FeignClient(name = "product-service", configuration = FeignConfig.class)
public interface ProductFeignClient {@GetMapping("/products/{id}")Product getProductById(@PathVariable Long id);@PostMapping("/products/{id}/stock/decrease")ResponseEntity<Void> decreaseStock(@PathVariable Long id, @RequestParam Integer quantity);
}// 订单服务客户端
@FeignClient(name = "order-service", configuration = FeignConfig.class)
public interface OrderFeignClient {@PostMapping("/orders")Order createOrder(@RequestBody OrderCreateRequest request);@GetMapping("/orders/users/{userId}")List<Order> getUserOrders(@PathVariable Long userId);
}// 在购物车服务中协调多个服务
@Service
@RequiredArgsConstructor
public class CartService {private final ProductFeignClient productFeignClient;private final OrderFeignClient orderFeignClient;@Transactionalpublic Order checkout(Long userId, List<CartItem> cartItems) {// 验证商品信息并减少库存for (CartItem item : cartItems) {productFeignClient.decreaseStock(item.getProductId(), item.getQuantity());}// 创建订单OrderCreateRequest request = new OrderCreateRequest(userId, cartItems);return orderFeignClient.createOrder(request);}
}

常见问题与解决方案

1. 序列化问题

问题描述:Date类型序列化格式不一致

解决方案:统一配置Jackson日期格式

spring:jackson:date-format: yyyy-MM-dd HH:mm:sstime-zone: GMT+8serialization:write-dates-as-timestamps: false

2. 复杂参数传递

问题描述:GET请求传递对象参数

解决方案:使用@SpringQueryMap注解

@FeignClient(name = "search-service")
public interface SearchFeignClient {@GetMapping("/search")SearchResult search(@SpringQueryMap SearchCriteria criteria);
}

3. 文件上传支持

解决方案:配置form encoder

@Configuration
public class FeignFormConfig {@Beanpublic Encoder feignFormEncoder() {return new SpringFormEncoder(new JacksonEncoder());}
}// 文件上传客户端
@FeignClient(name = "file-service", configuration = FeignFormConfig.class)
public interface FileUploadFeignClient {@PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)UploadResult uploadFile(@RequestPart("file") MultipartFile file);
}

监控与诊断

日志配置

logging:level:com.example.clients: DEBUGfeign:client:config:default:loggerLevel: FULL

分布式追踪集成

@Configuration
public class TraceFeignConfig {@Beanpublic RequestInterceptor tracingRequestInterceptor() {return template -> {// 传递追踪头信息template.header("X-B3-TraceId", MDC.get("X-B3-TraceId"));template.header("X-B3-SpanId", MDC.get("X-B3-SpanId"));template.header("X-B3-ParentSpanId", MDC.get("X-B3-ParentSpanId"));};}
}

核心原理

Spring Cloud OpenFeign 的核心实现是 声明式 REST 客户端 和 动态代理机制 。

核心组件

  • @EnableFeignClients:这个注解用于启动 Feign 客户端的支持。在 Spring Boot 应用中,当你添加了这个注解后,Spring 会扫描指定包下的所有带有 @FeignClient 注解的接口,并为它们创建代理对象。
  • @FeignClient:通过该注解定义一个 Feign 客户端,可以指定服务名(用于服务发现)、URL、编码器、解码器等属性。每个被标记的接口都会被增强生成 JDK 动态代理对象,实际请求会通过这些动态代理对象发送出去。
  • Feign.Builder:Feign 的核心构建者类,它负责根据配置创建具体的 Feign 客户端实例。Spring Cloud 对默认的 Builder 进行了扩展,加入了负载均衡( Ribbon / LoadBalancer )、熔断器( Hystrix )等功能。
  • LoadBalancerFeignClient:当与 Spring Cloud LoadBalancer 集成时,OpenFeign 使用的是一种特殊的服务请求客户端 —— LoadBalancerClient,它能够利用 Ribbon / Spring Cloud LoadBalancer 提供的负载均衡策略来选择服务实例进行调用。
  • Decoder, Encoder, Logger, ErrorDecoder 等:这些是Feign的内部组件,分别用于处理响应的反序列化、请求的序列化、日志记录以及错误处理等功能。Spring Cloud 允许开发者自定义这些组件的行为。

工作流程

1、初始化: 在 Spring 容器启动期间,Spring Cloud 会扫描所有标注有@FeignClient的接口,为它们生成 JDK 动态代理对象,然后注入到 Spring 容器中。
2、创建Feign客户端: 利用 Feign.builder() 方法结合各种配置(如编码器、解码器、拦截器、接口注解配置等),构造出 Feign 动态代理客户端。如果整合了负载均衡器,则会使用 LoadBalancerClient 作为最终的客户端实现。
以 spring-cloud-starter-openfeign 包的 4.2.1 版本源码为例:

public class FeignClientFactoryBeanimplements FactoryBean<Object>, InitializingBean, ApplicationContextAware, BeanFactoryAware {/*** FeignClientFactoryBean 的 getObject() 方法是 Spring 容器用来获取由该工厂 Bean 创建的 Feign 客户端实例的方法。* getObject() 方法最终返回的是一个动态代理对象,这个对象实现了 @FeignClient 定义的接口,并能够将接口方法调用转换为 HTTP 请求*/@Overridepublic Object getObject() {return getTarget();}/*** 创建并返回一个 Feign 客户端实例*/@SuppressWarnings("unchecked")<T> T getTarget() {// 获取 FeignClientFactory 实例FeignClientFactory feignClientFactory = beanFactory != null ? beanFactory.getBean(FeignClientFactory.class): applicationContext.getBean(FeignClientFactory.class);// 使用 FeignClientFactory 构建 Feign.Builder 实例 (代码见后)Feign.Builder builder = feign(feignClientFactory);// 如果 URL 未提供且不在配置中可用,则尝试通过负载均衡选择实例if (!StringUtils.hasText(url) && !isUrlAvailableInConfig(contextId)) {if (LOG.isInfoEnabled()) {LOG.info("For '" + name + "' URL not provided. Will try picking an instance via load-balancing.");}if (!name.startsWith("http://") && !name.startsWith("https://")) {url = "http://" + name;} else {url = name;}url += cleanPath();// 通过负载均衡创建客户端动态代理实例 (代码见后)return (T) loadBalance(builder, feignClientFactory, new HardCodedTarget<>(type, name, url));}// 否则使用固定 URL 创建客户端if (StringUtils.hasText(url) && !url.startsWith("http://") && !url.startsWith("https://")) {url = "http://" + url;}// 获取服务请求客户端:// 1、如果没有额外引入任何 HTTP 客户端库(如 Apache HttpClient 或 OkHttp),// 并且也没有启用负载均衡组件(Ribbon 或 Spring Cloud LoadBalancer),// 那么默认使用的 Client 是 Feign 自带的基于 HttpURLConnection 的实现。// 2、如果启用了负载均衡组件,则使用的 Client 默认是 FeignBlockingLoadBalancerClient(未开启失败重试时)Client client = getOptional(feignClientFactory, Client.class);if (client != null) {// 如果启用负载均衡组件(Spring Cloud LoadBalancer),但由于这里不需要负载均衡,// 所以通过 getDelegate() 获取到具体的 HTTP 请求客户端(比如 HttpURLConnection)即可if (client instanceof FeignBlockingLoadBalancerClient) {// not load balancing because we have a url,// but Spring Cloud LoadBalancer is on the classpath, so unwrapclient = ((FeignBlockingLoadBalancerClient) client).getDelegate();}if (client instanceof RetryableFeignBlockingLoadBalancerClient) {// not load balancing because we have a url,// but Spring Cloud LoadBalancer is on the classpath, so unwrapclient = ((RetryableFeignBlockingLoadBalancerClient) client).getDelegate();}builder.client(client);}// 应用自定义构建器定制化applyBuildCustomizers(feignClientFactory, builder);// 获取 Targeter 实例,并使用它来创建目标客户端动态代理实例Targeter targeter = get(feignClientFactory, Targeter.class);return targeter.target(this, builder, feignClientFactory, resolveTarget(feignClientFactory, contextId, url));}/*** 创建并返回一个已配置好的 Feign.Builder 实例*/protected Feign.Builder feign(FeignClientFactory context) {FeignLoggerFactory loggerFactory = get(context, FeignLoggerFactory.class);Logger logger = loggerFactory.create(type);// @formatter:offFeign.Builder builder = get(context, Feign.Builder.class)// required values// 设置日志记录器,用于输出请求/响应详情.logger(logger)// 将 Java 对象编码为 HTTP 请求体(如 JSON、XML)。默认实现是 SpringEncoder,使用 Spring MVC 的 HttpMessageConverter。.encoder(get(context, Encoder.class))// Decoder:将 HTTP 响应体解码为 Java 对象。默认实现是 SpringDecoder,同样基于 HttpMessageConverter。.decoder(get(context, Decoder.class))// Contract:负责解析接口上的注解(如 @RequestMapping, @GetMapping 等)。默认是 SpringMvcContract,支持 Spring MVC 注解风格。.contract(get(context, Contract.class));// @formatter:on// 设置重试策略(Retryer)、错误处理器(ErrorDecoder)、请求拦截器(RequestInterceptor)、连接超时等配置项// 所有这些配置都支持用户自定义覆盖,默认值来自 Spring Boot 自动配置configureFeign(context, builder);return builder;}/*** 通过负载均衡创建客户端动态代理实例* @param builder 已配置好的 Feign.Builder 实例* @param context FeignClientFactory,用于从 Spring 容器中获取 Bean* @param target 一个封装了目标服务名称和 URL 的对象(通常是服务名,例如 http://service-name)*/protected <T> T loadBalance(Feign.Builder builder, FeignClientFactory context, HardCodedTarget<T> target) {// 获取服务请求客户端:// 如果启用了负载均衡组件,则使用的 Client 默认是 FeignBlockingLoadBalancerClient(未开启失败重试时)// FeignBlockingLoadBalancerClient 内会通过负载均衡获取一个服务实例,把服务名替换为真实IP和端口号,再发起 HTTP 请求。Client client = getOptional(context, Client.class);if (client != null) {// 设置 HTTP 请求客户端builder.client(client);// 应用额外定制化配置applyBuildCustomizers(context, builder);// 获取 TargeterTargeter targeter = get(context, Targeter.class);// 创建动态代理实例return targeter.target(this, builder, context, target);}throw new IllegalStateException("No Feign Client for loadBalancing defined. Did you forget to include spring-cloud-starter-loadbalancer?");}}public class ReflectiveFeign<C> extends Feign {// FeignClientFactoryBean 中的 targeter.target(...) 最终都会调用到 ReflectiveFeign.newInstance(...) 方法创建动态代理对象@SuppressWarnings("unchecked")public <T> T newInstance(Target<T> target, C requestContext) {TargetSpecificationVerifier.verify(target);Map<Method, MethodHandler> methodToHandler =targetToHandlersByName.apply(target, requestContext);InvocationHandler handler = factory.create(target, methodToHandler);// 最终返回的是一个 JDK 动态代理对象T proxy =(T)Proxy.newProxyInstance(target.type().getClassLoader(), new Class<?>[] {target.type()}, handler);for (MethodHandler methodHandler : methodToHandler.values()) {if (methodHandler instanceof DefaultMethodHandler) {((DefaultMethodHandler) methodHandler).bindTo(proxy);}}return proxy;}}
public class FeignBlockingLoadBalancerClient implements Client {/*** 真正执行 HTTP 请求的底层客户端(如 Apache HttpClient、OkHttp、JDK HttpURLConnection 等)* FeignBlockingLoadBalancerClient 是一个装饰器模式的应用,它将实际请求委托给这个 delegate 执行*/private final Client delegate;/*** 用于服务发现和实例选择的负载均衡客户端* Spring Cloud 2020 之前的旧版本是 RibbonLoadBalancerClient* Spring Cloud 2020 之后的新版本是 BlockingLoadBalancerClient*/private final LoadBalancerClient loadBalancerClient;// (省略其他)...// 执行 HTTP 请求public Response execute(Request request, Request.Options options) throws IOException {// 将请求的 URL 解析为 URIfinal URI originalUri = URI.create(request.url());// 提取主机名作为 serviceId(即服务名称),比如 "order-service"String serviceId = originalUri.getHost();Assert.state(serviceId != null, "Request URI does not contain a valid hostname: " + originalUri);// 获取负载均衡策略使用的“hint”,通常是从请求头中提取的路由提示信息,比如可以基于请求头指定调用某个区域的服务实例String hint = getHint(serviceId);// 构建负载均衡请求上下文,request 里会包含请求体、头、方法等信息。DefaultRequest<RequestDataContext> lbRequest = new DefaultRequest<>(new RequestDataContext(buildRequestData(request), hint));// 生命周期方法回调Set<LoadBalancerLifecycle> supportedLifecycleProcessors = LoadBalancerLifecycleValidator.getSupportedLifecycleProcessors(loadBalancerClientFactory.getInstances(serviceId, LoadBalancerLifecycle.class),RequestDataContext.class, ResponseData.class, ServiceInstance.class);supportedLifecycleProcessors.forEach(lifecycle -> lifecycle.onStart(lbRequest));// 根据服务名称,选取服务实例// choose() 方法背后调用了 Ribbon 或 Spring Cloud LoadBalancer 的负载均衡策略算法(如轮询、随机、权重等)ServiceInstance instance = loadBalancerClient.choose(serviceId, lbRequest);org.springframework.cloud.client.loadbalancer.Response<ServiceInstance> lbResponse = new DefaultResponse(instance);// 如果没有找到可用服务实例,构造一个 503 响应返回,同时通知生命周期处理器请求失败if (instance == null) {String message = "Load balancer does not contain an instance for the service " + serviceId;supportedLifecycleProcessors.forEach(lifecycle -> lifecycle.onComplete(new CompletionContext<ResponseData, ServiceInstance, RequestDataContext>(CompletionContext.Status.DISCARD, lbRequest, lbResponse)));return Response.builder().request(request).status(HttpStatus.SERVICE_UNAVAILABLE.value()).body(message, StandardCharsets.UTF_8).build();}// 重构 URL:使用选中的 ServiceInstance 替换原始 URL 中的 host 部分。// 例如把 http://order-service/api/order/1 变成 http://192.168.1.10:8080/api/order/1String reconstructedUrl = loadBalancerClient.reconstructURI(instance, originalUri).toString();Request newRequest = buildRequest(request, reconstructedUrl, instance);// 通过底层的 HTTP 客户端(delegate)发送请求,并通知生命周期处理器执行回调方法 return executeWithLoadBalancerLifecycleProcessing(delegate, options, newRequest, lbRequest, lbResponse,supportedLifecycleProcessors);}
}

3、发起HTTP请求: 应用代码从 Spring 容器中获取到的 Feign 客户端,实际上是上面步骤 2 构造出来的 JDK 动态代理。当程序中调用 Feign 客户端的方法时,实际上是在调用由 JDK 动态生成的代理对象的方法,这个代理对象会将方法调用转换为 HTTP 请求,然后通过 HTTP 客户端发送出去。
4、响应处理: 收到响应后,相应的解码器会被用来解析响应内容,并将其转换为目标方法的返回值类型。

工作流程总结

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

openharmony之一多开发:产品形态配置讲解

OpenHarmony 的“一多开发”指的是 一次开发&#xff0c;多端部署&#xff08;简称“一多”&#xff09;&#xff0c;即使用 一套代码工程&#xff0c;一次开发上架&#xff0c;按需部署到不同终端设备上 &#x1f3af; 核心概念速览 产品形态定义 写在前面&#xff1a;1.不同的…

被迫在linux上用R(真的很难用啊)之如何在linux上正常使用R

总有一些情况&#xff0c;让你不得不在linux上使用R。。。 在我不断试错&#xff0c;不断尝试过程中&#xff08;恩&#xff0c;新手疯狂踩坑&#xff09; 发现最简单的办法是&#xff1a; 1 mamba创建一个新环境&#xff0c;在新环境中使用R 2 转变思维&#xff0c;都在linux上…

【STM32】G030单片机的独立看门狗

目录 一、简单介绍 二、特性 三、窗口选项 四、cubeMX配置 不使用窗口功能 使用窗口功能 五、工程链接 一、简单介绍 独立看门狗&#xff0c;顾名思义&#xff0c;是不依靠系统而独立存在的看门狗 可以脱离应用运行&#xff0c;但缺陷在于时序精度比窗口看门狗低 主要…

VR党建工作站-红色教育基地

近几年在市场爆火的VR党建工作站提升了传统的党建方式&#xff0c;利用VR/AR技术&#xff0c;为广大党员提供沉浸式、多维度的党建学习。佩京利用VR技术搭建的教育场景&#xff0c;可以更加直观地了解党的发展历程&#xff0c;提高学习效果&#xff0c;激发奋斗精神。VR党建工作…

配置 Gitlab 和 Elasticsearch/Zoekt 并使用 Docker Metadata 数据库、Camo 代理服务

配置 Gitlab 和 Elasticsearch/Zoekt 并使用 Docker Metadata 数据库、Camo 代理服务 本文章首发于&#xff1a;连接 Gitlab 和 Elasticsearch/Zoekt 并使用 Docker Metadata 数据库、Camo 代理服务 - Ayaka 的小站 为确保更好阅读格式和阅读体验&#xff0c;更建议前往个人博客…

2025年渗透测试面试题总结-36(题目+回答)

安全领域各种资源&#xff0c;学习文档&#xff0c;以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具&#xff0c;欢迎关注。 目录 一、计算机网络基础 1. HTTP 状态码&#xff08;502/503/501&#xff09; 2. HTTP 请求方式及作用 3. 计…

QT5.15.2 - 安装时如果下载不了停了,需要加速

文章目录QT5.15.2 - 安装时如果下载不了停了&#xff0c;需要加速概述笔记安装的选项可用的国内镜像站点也有很多ENDQT5.15.2 - 安装时如果下载不了停了&#xff0c;需要加速 概述 在 https://download.qt.io/archive/online_installers 中找在线安装包。 用qt-online-instal…

着色器语言

以下是主流的几种着色器语言&#xff1a;1. HLSL (High-Level Shading Language)这是你在Unity中最主要、最应该学习的语言。开发方&#xff1a;微软 (Microsoft)主要应用平台&#xff1a;Unity、DirectX (Windows, Xbox)特点&#xff1a;语法与C语言非常相似&#xff0c;易于学…

VILA运行全程踩坑笔记

VILA运行全程踩坑笔记1. docker的尝试2. 本地部署服务端仓库地址&#xff1a;https://github.com/NVlabs/VILA 全文按照一路踩坑的时间顺序记录&#xff0c;不建议按照步骤一步一步来重复每一个踩坑的悲伤故事&#xff0c;不如先全部看完&#xff0c;再实际上手操作。 省流&am…

Python爬虫: 分布式爬虫架构讲解及实现

了解Python分布式爬虫框架及其实现,能让你在处理大规模数据采集时事半功倍。本文我会结合自己的知识,从核心原理、主流框架、关键技术到实践建议,为你提供一个详细的解读。 🧠 一、分布式爬虫核心原理 分布式爬虫的核心思想是将爬取任务分解,由多个爬虫节点(Worker)协…

君正T31学习(四)- MT7682+VLC出图

一、简介 前几篇文章介绍了如何通过SD卡来播放sensor录制的视频&#xff0c;但是效率很低&#xff0c;所以需要一种效率更高的方法&#xff0c;就是本篇的主角MT7682VLC。 Mt7682在系统中注册为一个以太网卡驱动&#xff0c;接口名为eth0&#xff0c;可以使用Linux通用的socket…

【办公自动化】如何使用Python库高效自动化处理图像?

在日常办公中&#xff0c;我们经常需要处理大量图像&#xff0c;如产品照片、营销素材、文档扫描件等。手动处理这些图像不仅耗时&#xff0c;还容易出错。通过Python自动化图像处理&#xff0c;我们可以高效地完成批量缩放、裁剪、加水印、格式转换等任务&#xff0c;大大提高…

Beats与Elasticsearch高效数据采集指南

Beats 是 Elastic Stack 中的数据采集器&#xff0c;用于从各种来源&#xff08;日志、指标、网络数据等&#xff09;轻量级收集数据&#xff0c;而 Elasticsearch 是搜索和分析引擎&#xff0c;负责存储、索引和快速检索数据。二者结合可搭建强大的数据分析管道&#xff08;如…

前端异常监控,性能监控,埋点,怎么做的

你想做的是一个 前端监控系统&#xff08;Frontend Monitoring / RUM, Real User Monitoring&#xff09;&#xff0c;主要包括&#xff1a;异常监控&#xff08;JS 报错、资源加载错误、Promise 未捕获异常&#xff09;性能监控&#xff08;白屏时间、首屏时间、页面加载时间、…

Kubernetes一EFK日志架构

前言&#xff1a;​ 在云原生时代&#xff0c;Kubernetes已成为容器编排的事实标准&#xff0c;它赋予了应用极高的弹性、可移植性和密度。然而&#xff0c;这种动态、瞬时的特性也带来了可观测性的新难题&#xff1a;当数以百计的Pod在节点间频繁创建和销毁时&#xff0c;传统…

Linux下的软件编程——网络编程(tcp)

重点&#xff1a;1.UDP和TCP区别2.TCP三次握手和四次挥手3.TCP粘包问题及解决办法4.TCP客户端和服务端的编程流程 TCP&#xff1a;传输层传输控制协议&#xff08;流式套接字&#xff09;1&#xff09;TCP的特点1.面向数据流2.有连接&#xff08;通信之前必须建立连接…

印度尼西亚数据源 PHP 对接文档

一、环境要求与配置 1. 系统要求 PHP ≥ 7.4扩展&#xff1a;cURL、JSON、OpenSSLComposer&#xff08;推荐&#xff09; 2. 安装依赖 composer require guzzlehttp/guzzle3. 基础配置类 <?php // config/StockTVConfig.php class StockTVConfig {const BASE_URL https://…

Maven核心用法

1.什么是Maven2.Maven的作用&#xff08;依赖管理、项目构建、统一的项目结构&#xff09;2.1 依赖管理2.2 项目构建2.3 统一的项目结构3.Maven的介绍IDEA中对应信息4.Maven的安装注意&#xff1a;需要解压到 没有中文 不带空格 的目录下5.IDEA中的Maven配置然后需要配置JD…

TypeScript:never类型

never类型是TypeScript中最特殊的类型之一&#xff0c;它表示永远不会发生的值。作为专业前端工程师&#xff0c;理解never类型对于编写类型安全的代码至关重要。1. never类型的核心概念定义&#xff1a;never类型表示永远不会出现的值&#xff0c;常见于&#xff1a;抛出错误的…

图数据库neo4j的安装

安装JDK Neo4j是基于Java的图形数据库&#xff0c;运行Neo4j需要启动JVM进程&#xff0c;因此必须安装JAVA SE的JDK。从Oracle官方网站下载 Java SE JDK&#xff0c;我的的版本是JDK8。 安装Neo4j 官网下载最新版本Neo4j 我下的是社区版的 Neo4j应用程序有如下主要的目录结构…