OpenFeign:讓微服務間調用像本地方法一樣簡單

    • 引言:微服務通信的演進之路
    • 什么是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應用程序有如下主要的目錄結構…