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

OpenFeign相关面试题及答案

1、什么是OpenFeign,它如何简化远程服务调用?

OpenFeign是一个声明式的Web服务客户端,它使得编写HTTP客户端变得更加容易。它属于Spring Cloud Netflix项目的一部分,可以与Spring Boot应用轻松集成。通过使用OpenFeign,开发者可以通过简单的接口和注解来定义服务绑定,从而简化了与远程HTTP服务的交互过程。

OpenFeign的工作方式是:

  1. 声明式接口编程: 开发者可以定义一个接口,并对其进行注解,以标识需要调用的远程服务的HTTP端点。借助Spring MVC的注解,如@RequestMapping@PathVariable等,这个接口直观地映射了远程服务的API。

  2. 自动化请求与响应处理: OpenFeign自动处理请求的发送和响应的接收。它封装了编码请求和解码响应的过程,开发者不必手动构建HTTP请求或解析响应,这极大地减少了样板代码。

  3. 集成Ribbon和Hystrix: OpenFeign与Ribbon和Hystrix的集成提供了负载均衡和断路器功能。这意味着在调用远程服务时,Feign会自动进行负载均衡,并且可以提供容错能力,例如当远程服务不可用时提供回退方法。

  4. 易于维护: 因为远程调用逻辑被抽象为普通的Java接口调用,所以在服务消费者一端维护和测试服务调用变得更加容易。接口方法名称即服务调用意图,这种方式比编写复杂的HTTP客户端代码更加直观。

下面是一个OpenFeign的简单例子,展示了如何创建一个服务客户端来消费远程服务:

@FeignClient(name = "userservice", url = "http://localhost:8000/")
public interface UserServiceClient {@GetMapping("/users/{id}")User getUserById(@PathVariable("id") Long id);}

在这个例子中,UserServiceClient是一个接口,使用@FeignClient注解指定了远程服务的名称和URL。接口中的方法getUserById通过@GetMapping注解映射到远程服务的相应路径上。当你调用getUserById方法时,OpenFeign会自动构建HTTP GET请求到指定的URL,并解码响应到User对象。

总之,OpenFeign是微服务架构下进行服务间调用的优雅工具,它简化了服务消费者端与服务生产者通信的复杂性,通过声明式客户端接口降低了耦合,并提升了开发效率。

2、在OpenFeign中如何定义和使用客户端?

在Spring Cloud项目中使用OpenFeign时,首先需要将OpenFeign的依赖添加到项目的构建配置中,例如在Maven的pom.xml文件中添加以下依赖:

<dependencies><!-- Spring Cloud OpenFeign dependency --><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId></dependency><!-- 其他依赖项 -->
</dependencies>

接下来,您需要在Spring Boot的主应用程序类上使用@EnableFeignClients注解来启用Feign客户端:

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

然后,定义一个Feign客户端接口,使用@FeignClient注解指定远程服务的名称,接口中的方法将映射到远程服务的具体操作。

例如,假设您想要调用远程用户服务来获取用户信息:

@FeignClient(name = "user-service")
public interface UserServiceClient {@GetMapping("/users/{id}")User getUserById(@PathVariable("id") Long id);}

在这个例子中,@FeignClient注解的name属性表示远程服务的名称,对于Eureka等服务发现组件来说,这通常是服务的应用名称。您也可以使用url属性直接指定服务的URL。UserServiceClient是一个接口,定义了一个方法getUserById,它通过@GetMapping注解映射到远程服务的/users/{id}端点。

要使用这个Feign客户端,您可以在Spring组件中自动注入它,然后就像调用本地方法一样使用它:

@RestController
public class UserController {private final UserServiceClient userServiceClient;public UserController(UserServiceClient userServiceClient) {this.userServiceClient = userServiceClient;}@GetMapping("/user/{id}")public User getUser(@PathVariable Long id) {return userServiceClient.getUserById(id);}}

在这个UserController中,UserServiceClient被注入到控制器中,并被用来代理调用远程服务的getUserById方法。当调用getUser控制器方法时,它将通过UserServiceClient代理调用远程用户服务获取用户信息。

这样,OpenFeign为服务之间的远程调用提供了一种简单、声明式的方法,使得开发者可以专注于业务逻辑,而不用处理底层的HTTP通信细节。

3、@FeignClient注解中的fallback和fallbackFactory有什么区别?

在使用OpenFeign时,@FeignClient注解提供了fallbackfallbackFactory两个属性,它们都用于定义服务降级处理逻辑,但是它们的用法和提供的功能有所不同。

fallback

fallback属性允许您指定一个实现了Feign客户端接口的类,该类将作为远程调用失败时的备用实现。当远程服务调用由于某种原因失败或不可用时,Feign 会自动切换到这个备用实现。

例如:

@FeignClient(name = "user-service", fallback = UserServiceFallback.class)
public interface UserServiceClient {// ...
}@Component
public class UserServiceFallback implements UserServiceClient {@Overridepublic User getUserById(Long id) {// 实现服务降级逻辑return new User("defaultUser", "This is a fallback user");}
}

在这个例子中,如果getUserById的调用失败,Feign会自动调用UserServiceFallback中的同名方法。

fallbackFactory

fallbackFactory属性提供了更多的灵活性。它允许您为Feign客户端提供一个FallbackFactory的实现,这样您不仅可以提供服务降级逻辑,还能访问导致降级的原因(例如抛出的异常)。

例如:

@FeignClient(name = "user-service", fallbackFactory = UserServiceFallbackFactory.class)
public interface UserServiceClient {// ...
}@Component
public class UserServiceFallbackFactory implements FallbackFactory<UserServiceClient> {@Overridepublic UserServiceClient create(Throwable cause) {return new UserServiceClient() {@Overridepublic User getUserById(Long id) {// 使用导致降级的异常信息System.out.println("Fallback cause: " + cause);return new User("defaultUser", "This is a fallback user with factory");}};}
}

在这个例子中,如果getUserById的调用失败,Feign会自动使用UserServiceFallbackFactory创建一个备用实现,并且您可以访问和记录失败的原因。

总结来说:

  • fallback只提供了一个简单的服务降级实现,当远程服务调用失败时,将直接使用该实现。
  • fallbackFactory提供了一个创建服务降级实现的工厂,您可以访问到调用失败的具体异常,允许你执行更复杂的降级逻辑,比如根据不同的异常类型返回不同的响应。

根据您的具体需求,可以选择使用fallbackfallbackFactory,如果需要对异常进行细粒度的处理,通常推荐使用fallbackFactory

4、如何在OpenFeign中配置和自定义请求拦截器?

在OpenFeign中,您可以自定义请求拦截器来修改发往服务提供者的HTTP请求。这在添加自定义的HTTP头,如认证信息,或者是日志记录等方面特别有用。

要在Spring Cloud项目中配置和自定义Feign请求拦截器,您需要完成以下步骤:

  1. 创建一个自定义拦截器类:您需要创建一个实现了RequestInterceptor接口的类。在该类中,您可以覆写apply方法来自定义请求处理逻辑。
public class CustomFeignInterceptor implements RequestInterceptor {@Overridepublic void apply(RequestTemplate template) {// 添加自定义的HTTP头,比如认证tokentemplate.header("Authorization", "Bearer " + "your-token-value");// 记录请求信息,或添加其他自定义逻辑// ...}}
  1. 注册拦截器到Feign配置中:接下来,需要在Spring上下文中将您的拦截器注册为一个Bean。这样Spring Cloud Feign就会自动将其加入到请求处理流程中。
@Configuration
public class FeignConfig {@Beanpublic RequestInterceptor customFeignInterceptor() {return new CustomFeignInterceptor();}}
  1. 将Feign配置应用于特定的Feign客户端或全局客户端:您可以将自定义的拦截器应用于特定的Feign客户端或所有客户端。
  • 特定客户端配置:使用configuration属性指定配置类。
@FeignClient(name = "user-service", configuration = FeignConfig.class)
public interface UserServiceClient {// ...
}
  • 全局客户端配置:如果您希望所有的Feign客户端都使用这个拦截器,则需要在您的应用配置中使用@EnableFeignClientsdefaultConfiguration属性。
@EnableFeignClients(defaultConfiguration = FeignConfig.class)
@SpringBootApplication
public class MyApplication {// ...
}

这样配置后,每次Feign客户端发起请求时,都会经过CustomFeignInterceptor,从而允许您对请求进行自定义处理。

5、OpenFeign中的负载均衡是如何工作的?

在Spring Cloud生态系统中,OpenFeign是一个声明式的Web服务客户端,它简化了与HTTP API的通信。与此同时,Spring Cloud为服务之间的通信提供了负载均衡的功能,通常与Netflix Ribbon库或Spring Cloud LoadBalancer一起使用来实现客户端负载均衡。

负载均衡在OpenFeign中的工作流程如下:

  1. 服务发现:首先,服务消费者通过集成的服务发现机制(如Netflix Eureka、Consul或Zookeeper)来获取服务提供者的实例列表。这些实例信息包含了运行服务的主机名和端口号。

  2. 负载均衡器集成:在引入了OpenFeign依赖的Spring Cloud项目中,默认集成了一个负载均衡器,这可能是Netflix Ribbon或Spring Cloud LoadBalancer。这个负载均衡器会自动配置,并且可以根据需要进行自定义。

  3. 请求拦截与处理:当你使用Feign客户端发起一个请求时,请求会被拦截。Feign客户端实际上是一个代理,它将请求转发给负载均衡器。

  4. 选择服务实例:负载均衡器根据预定的策略(如轮询、随机、权重等)从服务发现获取的服务实例列表中选择一个实例。这个过程是透明的,服务消费者不需要关心具体的选择逻辑。

  5. 发起请求:一旦选择了服务实例,请求就会被发送到选定的实例。如果该实例不可用,负载均衡器可能会尝试选择另一个实例(这取决于配置的重试机制)。

  6. 处理响应:响应返回给服务消费者,就如同访问一个普通的单实例服务一样。

例子:

@FeignClient(name = "user-service")
public interface UserServiceClient {@GetMapping("/users/{id}")User getUserById(@PathVariable("id") Long id);
}

在这个例子中,user-service是服务提供者的名称,Feign客户端将请求发送到user-service。在后台,负载均衡器会根据服务发现机制获取user-service的可用实例,并决定将请求发往哪一个实例。

随着Spring Cloud的发展,Netflix Ribbon逐渐被Spring Cloud自己的负载均衡器——Spring Cloud LoadBalancer所取代,这个改变发生在Spring Cloud的Greenwich版本之后。Spring Cloud LoadBalancer是一个轻量级的客户端负载均衡器,它提供了一个简单的、可插拔的、基于Spring的方式来配置负载均衡策略。

6、如何在OpenFeign中启用GZIP压缩?

在OpenFeign中启用GZIP压缩可以减少传输数据的大小,从而提高性能。要启用GZIP压缩,你需要做两部分的工作:确保服务端支持GZIP压缩,以及在客户端(Feign客户端)配置请求和响应的压缩。

以下是在Spring Cloud环境下使用Feign客户端启用GZIP压缩的步骤:

  1. 服务端配置:确保你的服务端应用已经配置了对GZIP压缩的支持。如果你的服务是通过Spring Boot搭建的,可以在application.propertiesapplication.yml中添加如下配置:
server:compression:enabled: truemime-types: text/html,text/xml,text/plain,application/json,application/xmlmin-response-size: 1024 # 设置压缩的最小响应大小阈值
  1. 客户端配置:在Feign客户端,你需要设置请求头来告诉服务端你希望接受压缩的响应,同时配置Feign以发送压缩的请求。
feign:compression:request:enabled: truemime-types: text/html, text/xml, application/jsonmin-request-size: 2048 # 设置压缩的最小请求大小阈值response:enabled: true
  1. 自定义Feign配置:在某些情况下,你可能需要自定义Feign配置。你可以通过创建一个配置类并将其应用到@FeignClient中来实现:
@Configuration
public class FeignCompressionConfig {@Beanpublic Encoder feignEncoder() {return new SpringEncoder(new GzipEncoder(new SpringDecoder()));}@Beanpublic Decoder feignDecoder() {return new ResponseEntityDecoder(new SpringDecoder());}@Beanpublic Logger.Level feignLoggerLevel() {return Logger.Level.FULL;}
}@FeignClient(name = "compressed-service", configuration = FeignCompressionConfig.class)
public interface CompressedServiceClient {// ...
}

在这个配置类中,使用GzipEncoderSpringDecoder对请求和响应进行编码和解码。

  1. 请求拦截器:你也可以通过创建一个自定义的Feign请求拦截器来添加Accept-Encoding头:
public class GzipRequestInterceptor implements RequestInterceptor {@Overridepublic void apply(RequestTemplate template) {template.header("Accept-Encoding", "gzip");}
}

然后在你的配置中注册这个拦截器:

@Configuration
public class FeignConfig {@Beanpublic RequestInterceptor gzipRequestInterceptor() {return new GzipRequestInterceptor();}}

记得将这个配置应用到你的@FeignClient上。

通过上述步骤,你可以在使用OpenFeign的环境中启用GZIP压缩,这有助于提升网络传输效率,特别是在处理大量数据时。确保测试压缩功能在你的整个服务链中都能正确工作,包括服务端、代理、负载均衡器等。

7、在OpenFeign中如何处理错误和异常?

在OpenFeign中处理错误和异常通常涉及以下几个步骤:

  1. 使用@FeignClientfallback属性
    你可以为Feign客户端定义一个fallback类,这样当远程服务调用失败时,就会调用这个类中相应的方法。这适用于断路器模式,如Hystrix断路器。但请注意,从Spring Cloud Hoxton版本开始,Hystrix已被Spring Cloud CircuitBreaker框架取代。
@FeignClient(name = "remote-service", fallback = RemoteServiceFallback.class)
public interface RemoteServiceClient {@GetMapping("/data")Data getData();
}@Component
public class RemoteServiceFallback implements RemoteServiceClient {@Overridepublic Data getData() {// 提供备用逻辑return new Data("Default Data");}
}
  1. 使用@FeignClientfallbackFactory属性
    如果你需要访问导致回退的具体异常,你可以使用fallbackFactory属性。FallbackFactory允许你访问引起回退的异常,以便可以执行更复杂的逻辑。
@FeignClient(name = "remote-service", fallbackFactory = RemoteServiceFallbackFactory.class)
public interface RemoteServiceClient {// ...
}@Component
public class RemoteServiceFallbackFactory implements FallbackFactory<RemoteServiceClient> {@Overridepublic RemoteServiceClient create(Throwable cause) {return new RemoteServiceClient() {// 提供备用逻辑,并处理异常};}
}
  1. 自定义错误解码器(Error Decoder)
    Feign提供了ErrorDecoder接口,通过实现该接口你可以自定义服务调用的错误处理。你可以根据HTTP响应状态码或其他条件定义不同的异常类型。
public class CustomErrorDecoder implements ErrorDecoder {@Overridepublic Exception decode(String methodKey, Response response) {switch (response.status()) {case 400:// 处理400系列错误return new BadRequestException();case 404:// 处理404错误return new NotFoundException();default:// 其他错误return new GenericException("Generic error");}}
}@Configuration
public class FeignClientConfig {@Beanpublic ErrorDecoder errorDecoder() {return new CustomErrorDecoder();}
}

并将其应用到@FeignClient上:

@FeignClient(name = "remote-service", configuration = FeignClientConfig.class)
  1. 处理FeignException
    如果远程服务调用失败,并且没有回退逻辑,Feign会抛出FeignException。你可以在服务消费者端捕获这个异常,并根据需要进行处理。
try {remoteServiceClient.getData();
} catch (FeignException e) {// 处理Feign异常
}

确保你的错误处理策略与业务需求和用户体验相匹配,并且在任何重试或回退逻辑中避免无限循环或过多的性能开销。

8、OpenFeign和RestTemplate有什么区别?

OpenFeign和RestTemplate都是用于在Java应用中发起HTTP请求的工具,但它们之间存在一些主要区别:

  1. 声明式 vs. 模板式

    • OpenFeign 是一个声明式的Web服务客户端,它允许你通过简单地创建接口并用注解声明方法和参数来定义服务绑定。这种方式简化了远程HTTP服务的调用。
    • RestTemplate 是一种模板式的客户端,它提供了一系列用于同步调用的方法,你需要手动构建URL、设置请求体和头信息,然后处理响应。
  2. 集成和配置

    • OpenFeign 与Spring Cloud紧密集成,并提供自动服务发现、负载均衡和断路器集成等功能,这使得在微服务架构中调用其他服务变得非常简单。
    • RestTemplate 不自动提供这些集成,但是你可以通过使用@LoadBalanced注解来启用客户端负载均衡,同时需要你手动集成断路器等功能。
  3. 易用性

    • OpenFeign 通过接口和注解实现了对HTTP请求的抽象,使用它通常只需要定义一个接口并添加适当的注解即可完成服务绑定。
    • RestTemplate 需要你编写更多的模板代码来执行HTTP请求和处理响应。
  4. 错误处理

    • OpenFeign 默认会将所有的HTTP状态码异常抛出为FeignException,这可以通过自定义ErrorDecoder来处理。
    • RestTemplate 在默认情况下对于4xx和5xx响应会抛出HttpClientErrorExceptionHttpServerErrorException,同时提供ResponseErrorHandler来自定义错误处理。
  5. 维护状态

    • OpenFeign 是目前Spring Cloud推荐的方法,得到了更好的社区支持和更新。
    • RestTemplate 虽然目前仍然广泛使用,但Spring团队在Spring 5中引入了非阻塞的WebClient作为RestTemplate的替代,推荐在新的代码中使用WebClient
  6. 异步支持

    • OpenFeign 在较新的版本中支持异步请求,但这并不是它的主要目的。
    • RestTemplate 是同步的,与之相对的异步非阻塞客户端是WebClient

总的来说,如果你正在构建一个Spring Cloud微服务架构,经常需要调用其他服务,并且希望尽可能简化服务间的通信,那么OpenFeign可能是一个更好的选择。如果你需要更细粒度的控制,或者在一个不使用Spring Cloud的环境中,RestTemplate(或者WebClient)可能更适合你的需求。

9、如何定制OpenFeign的配置?

在Spring Cloud中,你可以通过为FeignClient创建一个Java配置类来定制OpenFeign的配置。这个配置类可以定义EncoderDecoderLoggerErrorDecoderRequestInterceptor等组件,以改变Feign的默认行为。

以下是一些步骤和示例,展示了如何定制Feign的配置:

  1. 创建Feign配置类
    创建一个包含你需要自定义的组件的配置类。你可以定义编码器(Encoder)、解码器(Decoder)、日志级别(Logger.Level)、错误解码器(ErrorDecoder)等组件。
import feign.codec.Encoder;
import feign.codec.Decoder;
import feign.Logger;
import feign.codec.ErrorDecoder;
import org.springframework.context.annotation.Bean;public class FeignCustomConfig {@Beanpublic Encoder feignEncoder() {return new YourCustomEncoder();}@Beanpublic Decoder feignDecoder() {return new YourCustomDecoder();}@Beanpublic Logger.Level feignLoggerLevel() {return Logger.Level.FULL; // 详细日志}@Beanpublic ErrorDecoder feignErrorDecoder() {return new YourCustomErrorDecoder();}
}
  1. 使用@FeignClient注解的configuration属性
    @FeignClient注解中引用你的配置类。这样,任何使用该Feign客户端的接口都会应用这些自定义配置。
@FeignClient(name = "customized-feign-client", configuration = FeignCustomConfig.class)
public interface CustomizedFeignClient {// 方法定义
}
  1. 自定义请求拦截器
    如果你需要对所有请求添加特定的头信息,或者执行一些请求前的逻辑,可以创建自定义的RequestInterceptor
import feign.RequestInterceptor;
import feign.RequestTemplate;public class CustomRequestInterceptor implements RequestInterceptor {@Overridepublic void apply(RequestTemplate template) {template.header("Authorization", "Bearer " + "your-token");// 其他自定义逻辑}
}// 在配置类中添加这个拦截器
public class FeignCustomConfig {@Beanpublic RequestInterceptor customRequestInterceptor() {return new CustomRequestInterceptor();}// 其他配置...
}
  1. 自定义日志配置
    你还可以自定义Feign的日志行为,通过实现Logger接口。
import feign.Logger;public class CustomLogger extends Logger {// 自定义日志行为
}// 注册自定义日志
public class FeignCustomConfig {@BeanLogger logger() {return new CustomLogger();}// 其他配置...
}
  1. 自定义错误处理
    通过实现ErrorDecoder接口,你可以自定义远程调用过程中的错误处理逻辑。
import feign.codec.ErrorDecoder;public class CustomErrorDecoder implements ErrorDecoder {@Overridepublic Exception decode(String methodKey, Response response) {// 自定义错误处理return new Exception("Custom error message");}
}// 注册自定义错误解码器
public class FeignCustomConfig {@Beanpublic ErrorDecoder errorDecoder() {return new CustomErrorDecoder();}// 其他配置...
}

使用这种方式,你可以为每个Feign客户端细粒度地定制配置,或者定义全局配置应用于所有Feign客户端。所有这些自定义组件的创建都依赖于Spring的自动装配特性,Feign会在启动时自动检测和应用这些配置。

10、如何在OpenFeign中使用断路器?

在OpenFeign中使用断路器可以防止系统在一部分服务失败时,这种影响蔓延导致更多的服务失败,这种模式被称为断路器模式。在Spring Cloud中,最初使用Netflix的Hystrix实现断路器,但是自从Spring Cloud Hystrix进入维护模式后,Spring Cloud引入了resilience4j作为替代,也支持使用Spring Retry进行简单的重试逻辑。

以下是如何在OpenFeign中使用断路器的一些步骤:

使用Spring Cloud CircuitBreaker(推荐)

Spring Cloud 2020.0.0版本及以上推荐使用Spring Cloud CircuitBreaker来实现断路器功能,其中包含对Resilience4j的集成。

  1. 添加依赖
    要使用Resilience4j作为断路器,需要在项目中添加以下依赖(以Maven为例):
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-circuitbreaker-resilience4j</artifactId>
</dependency>
  1. 配置Feign客户端
    @FeignClient注解中使用fallbackfallbackFactory属性指定回退逻辑:
@FeignClient(name = "remote-service", fallback = RemoteServiceFallback.class)
public interface RemoteServiceClient {// ...
}@Component
public class RemoteServiceFallback implements RemoteServiceClient {// 实现接口方法,并提供回退逻辑
}
  1. 配置断路器
    application.ymlapplication.properties中,你可以为断路器配置参数,例如失败率、慢调用阈值、断路器开启或关闭时间等:
resilience4j.circuitbreaker:instances:remote-service:registerHealthIndicator: trueslidingWindowSize: 100minimumNumberOfCalls: 20permittedNumberOfCallsInHalfOpenState: 10waitDurationInOpenState: 10000failureRateThreshold: 50slowCallDurationThreshold: 2000slowCallRateThreshold: 50automaticTransitionFromOpenToHalfOpenEnabled: true

使用Hystrix(旧版本Spring Cloud)

如果你使用的是Spring Cloud的老版本,那么你可能会使用Netflix Hystrix来实现断路器。

  1. 添加依赖
    你需要在项目中添加Netflix Hystrix的依赖(以Maven为例):
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
  1. 启用Hystrix
    在你的应用主类上使用@EnableHystrix注解来启用Hystrix。
@SpringBootApplication
@EnableHystrix
public class Application {public static void main(String[] args) {SpringApplication.run(Application.class, args);}
}
  1. 配置Feign客户端
    使用@FeignClientfallback属性定义回退逻辑:
@FeignClient(name = "remote-service", fallback = RemoteServiceFallback.class)
public interface RemoteServiceClient {// ...
}@Component
public class RemoteServiceFallback implements RemoteServiceClient {// 实现方法并提供回退逻辑
}
  1. 配置Hystrix参数
    application.ymlapplication.properties中配置Hystrix的参数:
hystrix:command:default:execution:isolation:thread:timeoutInMilliseconds: 2000

使用Spring Retry

如果你只需简单的重试机制而不需要完整的断路器功能,可以使用Spring Retry。

  1. 添加依赖
<dependency><groupId>org.springframework.retry</groupId><artifactId>spring-retry</artifactId>
</dependency>
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
  1. 在配置类中启用重试
@Configuration
@EnableFeignClients
@EnableRetry
public class FeignConfig {// ...
}
  1. 在Feign客户端上使用重试
@FeignClient(name = "remote-service")
public interface RemoteServiceClient {// ...
}
  1. 配置重试参数
spring:cloud:loadbalancer:retry:enabled: true

确保选择与你的Spring Cloud版本相匹配的断路器实现,并根据具体需求配置相关参数。在使用断路器时,考虑如何响应失败的调用,并提供适当的回退逻辑以保持用户体验和系统的稳定性。

11、OpenFeign中如何使用OAuth2进行服务调用?

在OpenFeign中使用OAuth2进行服务调用,你需要确保Feign客户端能够在发出请求时携带有效的OAuth2令牌。以下是配置OpenFeign客户端以使用OAuth2令牌的基本步骤:

  1. 添加OAuth2依赖
    首先,确保你的项目中包含了OAuth2客户端依赖。以下是使用Spring Cloud的项目中添加Spring Security OAuth2客户端的示例:
<dependency><groupId>org.springframework.security</groupId><artifactId>spring-security-oauth2-client</artifactId>
</dependency>
<dependency><groupId>org.springframework.security</groupId><artifactId>spring-security-oauth2-jose</artifactId>
</dependency>
  1. 配置资源服务器和客户端细节
    application.ymlapplication.properties中配置资源服务和OAuth2客户端详细信息,包括客户端ID、客户端秘钥、授权服务器的URL等。
spring:security:oauth2:client:registration:myclient:client-id: client-idclient-secret: client-secretauthorization-grant-type: client_credentialsprovider:myclient:token-uri: https://auth-server/oauth/token
  1. 创建Feign配置类
    创建一个Feign配置类,其中包含一个RequestInterceptor,该拦截器会从OAuth2AuthorizedClientService获取OAuth2令牌,并将其添加到Feign请求头中。
import feign.RequestInterceptor;
import feign.RequestTemplate;
import org.springframework.context.annotation.Bean;
import org.springframework.security.oauth2.client.OAuth2AuthorizeRequest;
import org.springframework.security.oauth2.client.OAuth2AuthorizedClientManager;public class OAuth2FeignConfig {private final OAuth2AuthorizedClientManager authorizedClientManager;public OAuth2FeignConfig(OAuth2AuthorizedClientManager authorizedClientManager) {this.authorizedClientManager = authorizedClientManager;}@Beanpublic RequestInterceptor oauth2FeignRequestInterceptor() {return requestTemplate -> {OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest.withClientRegistrationId("myclient").principal("principal").build();String tokenValue = authorizedClientManager.authorize(authorizeRequest).getAccessToken().getTokenValue();requestTemplate.header("Authorization", "Bearer " + tokenValue);};}
}
  1. 在Feign客户端中应用配置
    在Feign客户端接口上使用@FeignClient注解,并指定上面创建的配置类来使用该配置。
@FeignClient(name = "client-name", configuration = OAuth2FeignConfig.class)
public interface SomeClient {// 你的方法定义
}
  1. 配置OAuth2AuthorizedClientManager
    确保你的应用中配置了OAuth2AuthorizedClientManager,它用于获取和管理OAuth2令牌。
import org.springframework.context.annotation.Bean;
import org.springframework.security.oauth2.client.OAuth2AuthorizedClientManager;
import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository;
import org.springframework.security.oauth2.client.web.AuthenticatedPrincipalOAuth2AuthorizedClientRepository;@Configuration
public class OAuth2ClientConfig {@Beanpublic OAuth2AuthorizedClientManager authorizedClientManager(ClientRegistrationRepository clientRegistrationRepository,AuthenticatedPrincipalOAuth2AuthorizedClientRepository authorizedClientRepository) {return new DefaultOAuth2AuthorizedClientManager(clientRegistrationRepository,authorizedClientRepository);}
}

确保你的安全配置允许服务账户或者客户端凭据流程。这些步骤需要你已经对Spring Security和OAuth2有一定的了解。实际应用中,可能还需要根据授权服务器的具体实现和要求来进行细节调整。

12、在OpenFeign使用中需要注意什么?

在使用OpenFeign时,以下是一些需要注意的最佳实践和常见问题:

  1. 接口设计

    • Feign客户端接口应该精确映射到远程服务的端点。
    • 方法签名应清晰地表明预期的HTTP动作、路径、请求参数和返回类型。
  2. 错误处理

    • 实现和使用ErrorDecoder以定制如何处理远程调用中的错误响应。
    • 使用fallbackfallbackFactory来提供服务降级处理逻辑。
  3. 日志记录

    • Feign的日志级别可以提供关键的调试信息。合理设置日志级别,并在生产环境中注意不要泄露敏感信息。
    • 可以创建自定义Logger以适应特定的日志记录需求。
  4. 请求和响应处理

    • 如果需要,自定义EncoderDecoder以处理特殊的请求体或响应体。
    • 使用RequestInterceptor添加通用请求头,例如认证令牌。
  5. 性能和超时

    • 设置连接和读取超时,以避免服务调用在网络延迟时产生长时间的等待。
    • 通过配置feign.client.config.default.connectTimeoutfeign.client.config.default.readTimeout来设置超时时间。
  6. 断路器和重试机制

    • Integrate circuit breakers like Resilience4j to handle fallback logic and prevent cascading failures.
    • 配置重试机制以应对临时的网络问题或服务不稳定。
  7. 序列化和反序列化

    • 确保Feign客户端使用的序列化和反序列化库与服务提供者一致,以防止数据格式问题。
  8. HTTP版本和TLS

    • 如果远程服务要求使用HTTP/2或特定的TLS版本,请确保Feign客户端正确配置和支持它。
  9. 负载均衡

    • 如果使用Eureka或Ribbon等服务发现和负载均衡工具,确保其与Feign集成正确。
  10. 参数编码

    • 在使用@RequestParam@PathVariable时,注意URL的编码问题,特别是对于查询参数。
  11. 版本控制

    • 如果API具有多个版本,确保Feign客户端调用正确的API版本。
  12. 契约测试

    • 考虑使用契约测试来保证Feign客户端与服务提供者之间的契约兼容性。
  13. 异常处理

    • 使用@ExceptionHandler@ControllerAdvice来集中处理Feign客户端抛出的异常。

在实际应用中,需要根据具体场景调整配置和处理方式。始终关注上游服务的变化,并定期更新Feign客户端以同步这些变化。此外,保持代码的清晰和可维护性也是非常重要的。

相关文章:

OpenFeign相关面试题及答案

1、什么是OpenFeign&#xff0c;它如何简化远程服务调用&#xff1f; OpenFeign是一个声明式的Web服务客户端&#xff0c;它使得编写HTTP客户端变得更加容易。它属于Spring Cloud Netflix项目的一部分&#xff0c;可以与Spring Boot应用轻松集成。通过使用OpenFeign&#xff0…...

c盘扩容时,d盘无法删除卷问题

C盘扩容时&#xff0c;磁盘管理中D盘右键无法删除卷的原因 首先&#xff0c;D盘下文件夹为空&#xff0c;但是显示可用空间不是100%&#xff0c;经过排查&#xff0c;发现是虚拟内存设置在了D盘导致无法删除卷&#xff0c;这里只需要将虚拟内存放到其他盘&#xff0c;如E盘即可…...

NumPy 中级教程——广播(Broadcasting)

Python NumPy 中级教程&#xff1a;广播&#xff08;Broadcasting&#xff09; 在 NumPy 中&#xff0c;广播是一种强大的机制&#xff0c;它允许不同形状的数组在进行操作时&#xff0c;自动进行形状的调整&#xff0c;使得它们能够完成一致的运算。广播使得对数组的操作更加…...

python-39-flask+nginx+Gunicorn的组合应用

flask nginx Gunicorn 王炸 1 flasknginxgunicornsupervisor 1.1 myapp.py from flask import Flask app Flask(__name__)app.route("/") def test_link():return "the link is very good"if __name__"__main__":app.run()默认是5000端口…...

C#-CSC编译环境搭建

一.Microsoft .NET Framework 确保系统中安装Microsoft .NET Framework相关版本下载 .NET Framework 4.7 | 免费官方下载 (microsoft.com)https://dotnet.microsoft.com/zh-cn/download/dotnet-framework/net47 二.编译环境搭建 已经集成编译工具csc.exe,归档至gitcode,实现us…...

【JVM】一文掌握JVM垃圾回收机制

作为Java程序员,除了业务逻辑以外,随着更深入的了解,都无法避免的会接触到JVM以及垃圾回收相关知识。JVM调优是一个听起来很可怕,实际上很简单的事。 感到可怕,是因为垃圾回收相关机制都在JVM的C++层实现,我们在Java开发中看不见摸不着;而实际很简单,是因为它说到底,也…...

【AIGC风格prompt】风格类绘画风格的提示词技巧

风格类绘画风格的提示词展示 主题&#xff1a;首先需要确定绘画的主题&#xff0c;例如动物、自然景观、人物等。 描述&#xff1a;根据主题提供详细的描述&#xff0c;包括颜色、情感、场景等。 绘画细节&#xff1a;描述绘画中的细节&#xff0c;例如表情、纹理、光影等。 场…...

vue exceljs json数据转excel

json数据转excel 有时候我们会遇到这样一个需求&#xff0c;就是将数据转成excel下载&#xff0c;这一般都是由后端来处理&#xff0c;使用插件poi轻松搞定。如果只有少量数据&#xff0c;那么能不能避免调用后端接口&#xff0c;前端直接处理呢&#xff1f; 答案是&#xff…...

Navicat for MySQL 创建函数——报错1418

解决方法 1查看是否开启了创建函数的功能 输入下面语句查看是否开启了创建函数的功能 show variables like %func%; 下面为创建函数功能为开启的查询结果 如果不是上面的结果可以用下面的语句修改为开启 set GLOBAL log_bin_trust_function_creatorstrue; //或 set GLOBAL …...

java球队信息管理系统Myeclipse开发mysql数据库web结构java编程计算机网页项目

一、源码特点 java Web球队信息管理系统是一套完善的java web信息管理系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为TOMCAT7.0,Myeclipse8.5开发&#xff0c;数据库为Mysql5…...

设计模式(4)--对象行为(7)--观察者

1. 意图 定义对象间的一种一对多的依赖关系&#xff0c; 当一个对象的状态改变时&#xff0c;所有依赖于它的对象都得到通知并被自动更新。 2. 四种角色 抽象目标(Subject)、具体目标(Concrete Subject)、抽象观察者(Observer)、 具体观察者(Concrete Observer) 3. 优点 3.1 …...

MySQL所有常见问题

一、事务 定义:一组操作要么全部成功,要么全部失败,目的是为了保证数据最终的一致性 在MySQL中,提供了一系列事务相关的命令: start transaction | begin | begin work:开启一个事务commit:提交一个事务rollback:回滚一个事务事务的ACID 原子性(Atomicity):当前事…...

锐捷交换机配置 SNMP

配置步骤 ( SNMP v2 ) 步骤一 -- 创建共同体(Community) ruijie(config)#snmp-server community test rw # rw 为读和写口令ruijie(config)#snmp-server community public ro # ro 为只读和写口令这里的共同体为“test”,通常只读口令和读写口令单独配置,提升安…...

Windows 10 安装和开启VNCServer 服务

Windows 10 安装和开启VNCServer 服务 登录云服务器 使用本地RDP登录到配置VNCServer服务的Windows10系统的云服务器。 下载VNC Server安装包 打开官网下载VNCServer安装包 URL&#xff1a;https://www.realvnc.com/en/connect/download/vnc/windows/ 安装VNC Server 双击…...

js遍历后端返回的集合将条件相同的放入同一个数组内

项目场景&#xff1a; echarts折线图需要根据条件动态展示多条不同曲线 解决方案&#xff1a; 后端直接将使用sql将数据查询出来返回即可,因为我这里不是Java使用的C#不是很熟练后台不好写逻辑,所以在前端js完成的 代码如下: function createline(villagename, buildingname…...

GcExcel:DsExcel 7.0 for Java Crack

GcExcel:DsExcel 7.0-高速 Java Excel 电子表格 API 库 Document Solutions for Excel&#xff08;DsExcel&#xff0c;以前称为 GcExcel&#xff09;Java 版允许您在 Java 应用程序中以编程方式创建、编辑、导入和导出 Excel 电子表格。几乎可以部署在任何地方。 创建、加载、…...

基于SpringBoot的职业生涯规划系统

文章目录 项目介绍主要功能截图:部分代码展示设计总结项目获取方式🍅 作者主页:超级无敌暴龙战士塔塔开 🍅 简介:Java领域优质创作者🏆、 简历模板、学习资料、面试题库【关注我,都给你】 🍅文末获取源码联系🍅 项目介绍 基于SpringBoot的职业生涯规划系统,java…...

基于Java+SpringBoot+vue+elementui的校园文具商城系统详细设计和实现

基于JavaSpringBootvueelementui的校园文具商城系统详细设计和实现 欢迎点赞 收藏 ⭐留言 文末获取源码联系方式 文章目录 基于JavaSpringBootvueelementui的校园文具商城系统详细设计和实现前言介绍&#xff1a;系统设计&#xff1a;系统开发流程用户登录流程系统操作流程 功能…...

PyTorch中常用的工具(5)使用GPU加速:CUDA

文章目录 前言4 使用GPU加速&#xff1a;CUDA5 小结 前言 在训练神经网络的过程中需要用到很多的工具&#xff0c;最重要的是数据处理、可视化和GPU加速。本章主要介绍PyTorch在这些方面常用的工具模块&#xff0c;合理使用这些工具可以极大地提高编程效率。 由于内容较多&am…...

Qt+opencv 视频分解为图片

最近遇到一些售前提供的BUG&#xff0c;但是他们提供的是录像视频&#xff0c;因为处理显示速度比较快&#xff0c;因此很难找到出现问题的位置。需要反复播放&#xff0c;自己编写了一个视频分解成图片这样就可以一张图一张图的对比&#xff0c;方便查看。 开发环境 qtopenv…...

一篇文章认识微服务的优缺点和微服务技术栈

目录 1、微服务 2、微服务架构 3、微服务优缺点 3.1 优点 3.2 缺点 4、微服务技术栈 1、微服务 微服务化的核心就是将传统的一站式应用&#xff0c;根据业务拆分成一个一个的服务&#xff0c;彻底地去耦合&#xff0c;每一个微服务提供单个业务功能的服务&#xff0c;一…...

[spark] dataframe的数据导入Mysql5.6

在 Spark 项目中使用 Scala 连接 MySQL 5.6 并将 DataFrame 中的数据保存到 MySQL 中的步骤如下&#xff1a; 添加 MySQL 连接驱动依赖&#xff1a; 在 Spark 项目中&#xff0c;你需要在项目的构建工具中添加 MySQL 连接驱动的依赖。 如果使用 Maven&#xff0c;可以在 pom.xm…...

2023年度业务风险报告:四个新风险趋势

目录 倒票的黄牛愈加疯狂 暴增的恶意网络爬虫 愈加猖獗的羊毛党 层出不穷的新风险 业务风险呈现四个趋势 防御云业务安全情报中心“2023年业务风险数据”统计显示&#xff0c;恶意爬虫风险最多&#xff0c;占总数的37.8%&#xff1b;其次是虚假账号注册&#xff0c;占18.79%&am…...

python编程从入门到实践(1)

文章目录 2.2.1命名的说明2.3字符串2.3.1使用方法修改字符串的大小写2.3.2 在字符串中使用变量2.3.3 制表符 和 换行符2.5.4删除空白2.5.5 删除前缀&#xff0b;后缀 2.2.1命名的说明 只能包含&#xff1a;字母&#xff0c;下划线&#xff0c;数字 必须&#xff1a;字母&#…...

ElasticSearch 文档操作

创建文档 指定id // 无则插入&#xff0c;有则覆盖&#xff08;覆盖的逻辑是先删除&#xff0c;再插入&#xff09; PUT /<target>/_doc/<_id> // 无则插入&#xff0c;有则覆盖 POST /<target>/_doc/<_id> // 无则插入&#xff0c;有则报错 PUT /&l…...

NXOpenC++布尔求和命令

一、概述 在进行批量布尔求和时&#xff0c;采用NXOpenC的方式要比UFun的方式美观的多&#xff0c;个人认为&#xff0c;ufun中UF_MODL_unite_bodies函数采用的是两两进行合并&#xff0c;显示多个步骤&#xff0c;而NXOpenC采用的是一个工具体和多个目标体进行合并&#xff0c…...

ubuntu python播放MP3,wav音频和录音

目录 一.利用pygame&#xff08;略显麻烦&#xff0c;有时候播放不太正常&#xff09;1.安装依赖库2.代码 二.利用mpg123&#xff08;简洁方便&#xff0c;但仅争对mp3&#xff09;1.安装依赖库2.代码 三.利用sox&#xff08;简单方便&#xff0c;支持的文件格式多&#xff09;…...

Rust学习笔记000 安装

安装命令 curl --proto https --tlsv1.2 -sSf https://sh.rustup.rs | sh $ curl --proto https --tlsv1.2 -sSf https://sh.rustup.rs | sh info: downloading installerWelcome to Rust!This will download and install the official compiler for the Rust programming la…...

python AI五子棋对战

我写过一篇c++五子棋 c++五子棋代码-CSDN博客 现在又写了python import copy import time from enum import IntEnum import pygame from pygame.locals import *time = time.strftime("%Y-%m-%d %H:%M:%S") version = str(time)# 基础参数设置 square_size = 40 …...

图文证明 费马,罗尔,拉格朗日,柯西

图文证明 罗尔,拉格朗日,柯西 费马引理和罗尔都比较好证,不过多阐述,看图即可: 费马引理: 罗尔定理: 重点来证明拉格朗日和柯西 拉格朗日: 我认为不需要去看l(x)的那一行更好推: 详细的推理过程: 构造 h ( x ) f ( x ) − l ( x ) , 因为 a , b 两点为交点 , f ( a ) l ( …...

CEC2017(Python):粒子群优化算法PSO求解CEC2017(提供Python代码)

一、CEC2017简介 参考文献&#xff1a; [1]Awad, N. H., Ali, M. Z., Liang, J. J., Qu, B. Y., & Suganthan, P. N. (2016). “Problem definitions and evaluation criteria for the CEC2017 special session and competition on single objective real-parameter numer…...

AUTOSAR从入门到精通- 虚拟功能总线(RTE)(一)

目录 前言 几个高频面试题目 RTE S/R接口implicit与Explicit的实现与区别 接口的代码 implicit...

B/S架构云端SaaS服务的医院云HIS系统源码,自主研发,支持电子病历4级

医院云HIS系统源码&#xff0c;自主研发&#xff0c;自主版权&#xff0c;电子病历病历4级 系统概述&#xff1a; 一款满足基层医院各类业务需要的云HIS系统。该系统能帮助基层医院完成日常各类业务&#xff0c;提供病患挂号支持、病患问诊、电子病历、开药发药、会员管理、统…...

看懂基本的电路原理图(入门)

文章目录 前言一、二极管二、电容三、接地一般符号四、晶体振荡器五、各种符号的含义六、查看原理图的顺序总结 前言 电子入门&#xff0c;怎么看原理图&#xff0c;各个图标都代表什么含义&#xff0c;今天好好来汇总一下。 就比如这个电路原理图来说&#xff0c;各个符号都…...

赫夫曼树基本数据结构

自编头文件&#xff1a; #ifndef HUFFMAN_H_INCLUDED #define HUFFMAN_H_INCLUDED#include<limits.h> #include<string.h> typedef struct {unsigned int weight;unsigned int parent,lchild,rchild; }HTNode,*HuffmanTree; typedef char** HuffmanCode;void Sele…...

10TB海量JSON数据从OSS迁移至MaxCompute

前提条件 开通MaxCompute。 在DataWorks上完成创建业务流程&#xff0c;本例使用DataWorks简单模式。详情请参见创建业务流程。 将JSON文件重命名为后缀为.txt的文件&#xff0c;并上传至OSS。本文中OSS Bucket地域为华东2&#xff08;上海&#xff09;。示例文件如下。 {&qu…...

LLM之RAG实战(九)| 高级RAG 03:多文档RAG体系结构

在RAG&#xff08;检索和生成&#xff09;这样的框架内管理和处理多个文档有很大的挑战。关键不仅在于提取相关内容&#xff0c;还在于选择包含用户查询所寻求的信息的适当文档。基于用户查询对齐的多粒度特性&#xff0c;需要动态选择文档&#xff0c;本文将介绍结构化层次检索…...

Windows电脑引导损坏?按照这个教程能修复

前言 Windows系统的引导一般情况下是不会坏的&#xff0c;小伙伴们可以不用担心。发布这个帖子是因为要给接下来的文章做点铺垫。 关注小白很久的小伙伴应该都知道&#xff0c;小白的文章都讲得比较细。而且文章与文章之间的关联度其实还是蛮高的。在文章中&#xff0c;你会遇…...

记Android字符串资源支持的参数类型

参数以%开头&#xff0c;后拼接对应的参数类型名称&#xff0c;如下所示&#xff1a; <string name"tips">Hello, %s! You have some new messages.</string> 类型名称如下所示&#xff1a; s字符串格式用于插入字符串值。例如&#xff0c;"Hel…...

Java实现树结构(为前端实现级联菜单或者是下拉菜单接口)

Java实现树结构&#xff08;为前端实现级联菜单或者是下拉菜单接口&#xff09; 我们常常会遇到这样一个问题&#xff0c;就是前端要实现的样式是一个级联菜单或者是下拉树&#xff0c;如图 这样的数据接口是怎么实现的呢&#xff0c;是什么样子的呢&#xff1f; 我们可以看看 …...

MySQL中常用的数据类型

整型 int 有符号范围: -2147483648 ~ 2147483647 int unsigned 无符号范围: 0 ~ 4294967295 int(5) zerofill 仅用于显示&#xff0c;当不满足5位时&#xff0c;按照左边补0&#xff0c;例如: 00002满足时&#xff0c;正常显示 tinyint[(m)] [unsigned] [zerofill] 有符号&a…...

HTML+CSS+JS制作三款雪花酷炫特效

🎀效果展示 🎀代码展示 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html...

[C#]使用ONNXRuntime部署一种用于边缘检测的轻量级密集卷积神经网络LDC

源码地址&#xff1a; github.com/xavysp/LDC LDC: Lightweight Dense CNN for Edge Detection算法介绍&#xff1a; 由于深度学习方法的快速发展&#xff0c;近年来&#xff0c;用于执行图像边缘检测的卷积神经网络&#xff08;CNN&#xff09;模型爆炸性地传播。但边缘检测…...

ZigBee案例笔记 - 无线点灯

文章目录 无线点灯实验概述工程关键字工程文件夹介绍Basic RF软件设计框图简单说明工程操作Basic RF启动流程Basic RF发送流程Basic RF接收流程 无线点灯案例无线点灯现象 无线点灯实验概述 ZigBee无线点灯实验&#xff08;即Basic RF工程&#xff09;&#xff0c;由TI公司提供…...

Debezium日常分享系列之:向 Debezium 连接器发送信号

Debezium日常分享系列之&#xff1a;向 Debezium 连接器发送信号 一、概述二、激活源信号通道三、信令数据集合的结构四、创建信令数据集合五、激活kafka信号通道六、数据格式七、激活JMX信号通道八、自定义信令通道九、Debezium 核心模块依赖项十、部署自定义信令通道十一、信…...

《C#程序设计教程》总复习

一、单项选择题 1.short 类型的变量在内存中占据的位数是 ( )。 A. 8 B. 16 C. 32 D. 64 2.对千 int[ 4,5]型的数组 a, 数组元素 a[2,3] 存在数组第 ( )个位置上。 A. 11 B. 12 C. 14 D. 15 3.设 int 类型变量 x,y,z 的值分别是2、3、6 , 那么…...

为什么ChatGPT选择了SSE,而不是WebSocket?

我在探索ChatGPT的使用过程中&#xff0c;发现了一个有趣的现象&#xff1a;ChatGPT在实现流式返回的时候&#xff0c;选择了SSE&#xff08;Server-Sent Events&#xff09;&#xff0c;而非WebSocket。 那么问题来了&#xff1a;为什么ChatGPT选择了SSE&#xff0c;而不是We…...

appium入门基础

介绍 appium支持在不同平台的UI自动化&#xff0c;如web,移动端,桌面端等。还支持使用java&#xff0c;python&#xff0c;js等语言编写自动化代码。主要用于自动化测试脚本&#xff0c;省去重复的手动操作。 Appium官网 安装 首先必须环境有Node.js用于安装Appium。 总体来…...

jsp介绍

JSP 一种编写动态网页的语言&#xff0c;可以嵌入java代码和html代码&#xff0c;其底层本质上为servlet,html部分为输出流&#xff0c;编译为java文件 例如 源jsp文件 <% page contentType"text/html; charsetutf-8" language"java" pageEncoding&…...

Debian安装k8s记录

Debian安装k8s记录 在master和node上安装kube安装master安装node遇到的问题汇总1、kubelet.service报错 failed to pull image "registry.k8s.io/pause:3.6"2、node重启后报错&#xff0c;failed: open /run/flannel/subnet.env: no such file or directory 在master…...