微服务面试题

微服务治理包含什么内容

微服务治理(Microservices Governance)是指在微服务架构中,对服务的生命周期、服务间交互、服务的健康状态、监控、日志管理、安全性等多个方面进行管理和优化的过程。微服务治理的目的是确保微服务系统的可靠性、可扩展性、灵活性和可维护性。它涵盖了很多技术和管理手段,具体包括以下几个方面:

1. 服务注册与发现

  • 服务注册:微服务在启动时将自身的信息(如IP地址、端口、元数据等)注册到服务注册中心(如 Nacos、Consul、Eureka等)。
  • 服务发现:服务消费者通过服务注册中心发现并访问其他微服务,避免硬编码服务地址,使得服务可以动态扩展或缩减。

关键技术:Nacos、Eureka、Consul、Zookeeper

2. 负载均衡

  • 客户端负载均衡:服务消费者通过负载均衡算法(如轮询、随机、加权等)选择多个服务实例中的一个来进行请求。
  • 服务器端负载均衡:使用 API 网关或负载均衡器(如 Nginx、HAProxy)在请求到达服务之前进行负载均衡。

关键技术:Ribbon、Nginx、HAProxy

3. 服务间通信

  • 同步通信:大部分微服务间的通信通过 HTTP(REST)、gRPC 或其他协议进行同步调用。
  • 异步通信:为了提高性能,异步消息队列(如 Kafka、RabbitMQ、ActiveMQ)可以用于微服务间的消息传递,减少服务间的耦合。

关键技术:HTTP REST、gRPC、消息队列(Kafka、RabbitMQ)

4. 服务容错与降级

  • 断路器:当某个微服务不可用或超时时,断路器会停止请求该服务,避免造成级联故障。
  • 服务降级:在服务不可用或负载过高时,提供备用方案或返回预设的默认值。
  • 超时与重试:设置请求超时限制并在失败时进行重试,以提高系统的鲁棒性。

关键技术:Hystrix、Resilience4j、Sentinel

5. 服务监控与日志管理

  • 监控:实时监控微服务的健康状况、性能、响应时间等,确保微服务系统的可用性和性能。
  • 日志管理:集中化日志管理,用于收集、存储、查询和分析微服务的运行日志,帮助排查问题。
  • 追踪与链路分析:通过分布式追踪工具跟踪请求在各个服务间的流转路径,帮助诊断性能瓶颈和故障。

关键技术:Prometheus、Grafana、ELK(Elasticsearch、Logstash、Kibana)、Zipkin、Jaeger

6. 服务安全

  • 认证与授权:微服务之间的通信需要验证身份,确保服务间的安全调用。常用的认证方法包括基于 Token(如 JWT)的认证。
  • 加密:为了保护敏感数据,服务间的通信需要使用 HTTPS 等加密协议。
  • 防火墙与限流:通过设置防火墙和限流规则来防止恶意攻击或服务过载。

关键技术:OAuth 2.0、JWT、Spring Security、API Gateway、Rate Limiting

7. 配置管理

  • 集中化配置:将微服务的配置文件集中管理,支持动态刷新和管理。这样可以在不中断服务的情况下,修改和更新配置。
  • 环境隔离:不同环境(开发、测试、生产)之间的配置要进行隔离,保证配置的安全和稳定性。

关键技术:Nacos、Apollo、Consul、Spring Cloud Config

8. 数据管理与事务处理

  • 分布式事务:由于微服务架构的分布式特性,传统的单体事务已无法满足需求,需要通过分布式事务机制来保证数据的一致性。
  • Saga 模式:通过一系列本地事务和补偿操作来确保最终一致性。
  • Event Sourcing 和 CQRS:通过事件驱动的架构和命令查询职责分离模式,确保服务间的数据一致性和高性能。

关键技术:Seata、Atomikos、Saga、Event Sourcing、CQRS

9. API 网关与路由管理

  • API 网关:微服务架构中,所有外部请求都通过 API 网关统一接入,API 网关可以进行请求路由、负载均衡、认证、限流等操作。
  • 路由管理:动态管理请求路由规则,支持服务版本控制和灰度发布。

关键技术:Kong、Zuul、Spring Cloud Gateway

10. 服务治理与调度

  • 服务健康检查:微服务在注册到服务注册中心时,需要定期进行健康检查,确保服务的可用性。
  • 服务版本管理与灰度发布:通过服务的版本控制和灰度发布策略,逐步将新版本推广到生产环境。
  • 自动扩展与缩减:根据服务负载自动调整服务实例的数量,确保资源的高效利用。

关键技术:Kubernetes、Docker Swarm、Spring Cloud Kubernetes、Consul


11. 版本控制与灰度发布

  • 服务版本管理:微服务的不同版本可能同时存在,需要管理和协调服务版本。
  • 灰度发布与蓝绿发布:通过逐步发布新版本,确保服务升级时的平滑过渡,避免对现有系统造成影响。

关键技术:Istio、Argo CD、Spring Cloud Bus


12. 微服务的可观察性

  • 分布式跟踪:微服务架构中,单个请求可能会跨多个服务,分布式跟踪可以帮助追踪请求在服务间的流转路径,定位性能瓶颈和故障。
  • 日志聚合与分析:集中化日志管理,帮助开发和运维人员快速定位问题。

关键技术:Zipkin、Jaeger、ELK Stack


13. 容器化与服务调度

  • 容器化:通过 Docker 等容器技术将微服务进行打包,确保服务的跨平台一致性和灵活性。
  • 服务调度:使用容器编排工具(如 Kubernetes)来自动化部署、扩展和管理微服务。

关键技术:Docker、Kubernetes、Docker Compose


总结

微服务治理是一个综合的体系,涵盖了多个方面的管理与优化。一个健康的微服务治理架构不仅关注服务注册与发现、负载均衡等基础设施,还应确保服务的安全、可靠、可监控、可扩展。通过使用合适的工具和框架来实现微服务治理,可以有效地提升微服务系统的稳定性、灵活性和可维护性。

Dubbo

dubbo怎么定位的,在微服务中扮演什么角色,与Eureka区别

dubbo远程调用原理

动态代理

功能:服务治理(服务注册与发现,远程调用,熔断+重试,负载均衡(轮询/随机/权重/活跃度))

Dobbuo实现服务注册与发现有借助其他组件吗,还是他自己实现的

Dubbo 在实现 服务注册与发现 时,既有自己实现的部分,也可以通过借助外部组件(注册中心)来完成。实际上,Dubbo 主要依赖外部的 注册中心 来进行服务的注册与发现。服务注册与发现的过程是 Dubbo 分布式架构中关键的一部分,帮助实现服务的高可用和负载均衡。

1. Dubbo 自己的实现

Dubbo 的早期版本(特别是在 2.x 之前),曾经内置了一些简单的服务注册与发现机制,但这些机制比较原始、简单,且功能有限。因此,Dubbo 并不依赖自己完整的服务注册与发现实现,而是希望将这部分职责交给更强大的分布式注册中心。

2. 依赖外部组件:服务注册与发现

Dubbo 2.x 开始,Dubbo 默认使用外部的服务注册中心来完成服务的注册与发现。常见的外部组件有:

  • Zookeeper:这是 Dubbo 默认支持的服务注册与发现组件。Dubbo 利用 Zookeeper 提供的分布式协调功能,来进行服务注册、发现和监控。
  • Nacos:在 Dubbo 2.7 版本及以后,Dubbo 也支持 Nacos 作为注册中心。Nacos 提供了更丰富的功能,如动态配置管理、服务治理等。

此外,Dubbo 还支持其他一些注册中心的插件,如 ConsulEtcd 等。

3. 服务注册与发现过程

  • 服务注册

    • 服务提供者启动时,会将自己的服务信息(如服务接口、服务实现类、IP、端口等)注册到注册中心(如 Zookeeper 或 Nacos)。
    • 这些信息通常是 以树形结构存储,注册中心会为每个服务暴露一个唯一的路径,表示该服务的实例信息。
  • 服务发现

    • 服务消费者在调用服务之前,会查询注册中心,获取可用的服务提供者信息(如服务的 IP 地址、端口、负载均衡策略等)。
    • 注册中心根据客户端的请求返回可用的服务实例,消费者可以通过这些信息调用相应的服务。

4. 为什么选择外部注册中心

Dubbo 使用外部注册中心来实现服务注册与发现,主要有以下几个原因:

  • 高可用与容错性:外部注册中心如 Zookeeper、Nacos 提供了高可用和容错机制,能够处理服务实例的动态变化(如上线、下线、网络故障等)。
  • 分布式环境支持:注册中心为 Dubbo 提供了强大的分布式协调能力,尤其是在大规模分布式系统中,注册中心能够管理成千上万的服务实例,并确保服务发现的可靠性。
  • 负载均衡和容错:通过服务注册中心,Dubbo 可以实现更加灵活和智能的负载均衡和故障转移机制,避免直接在服务之间做硬编码。
  • 多种协议支持:注册中心可以同时支持不同类型的服务(如 Dubbo 服务、HTTP 服务等),使得 Dubbo 在多协议场景下的兼容性更强。

5. 服务注册与发现的流程

服务注册流程
  1. 服务提供者启动:服务提供者启动时,Dubbo 会将服务接口、服务实现、IP、端口等信息通过配置文件或注解的方式传递给注册中心。
  2. 注册中心保存信息:注册中心(如 Zookeeper)会在特定的节点路径下存储服务的信息,确保该服务的可用性。
  3. 服务提供者心跳:为了保证服务的健康状态,服务提供者定期向注册中心发送心跳,确保自己在注册中心的信息是有效的。
服务发现流程
  1. 服务消费者查询:服务消费者启动时,会查询注册中心,获取指定服务的地址和信息。
  2. 注册中心返回服务实例信息:注册中心返回可用的服务实例(如服务提供者的 IP、端口等)。
  3. 调用远程服务:服务消费者通过网络请求(如 HTTP、Dubbo 协议等)调用远程服务。

6. Dubbo与Zookeeper/Nacos的集成

  • Zookeeper 集成

    • Zookeeper 作为一个分布式协调框架,提供了类似分布式文件系统的机制,Dubbo 使用 Zookeeper 进行服务注册和发现。
    • 服务提供者将服务信息注册到 Zookeeper 的某个节点,而消费者则从 Zookeeper 查询该节点,获得可用服务的列表。
    • Zookeeper 支持数据一致性和分布式事务,能够高效地管理服务的动态变化。
  • Nacos 集成

    • Nacos 是阿里巴巴开源的动态服务发现与配置管理平台,提供了类似 Zookeeper 的服务注册与发现功能。
    • 与 Zookeeper 相比,Nacos 在用户体验、配置管理、健康检查等方面更加灵活、简便。
    • Nacos 支持服务的 动态注册与发现,并且可以实现更加细粒度的服务管理。

7. 总结

  • Dubbo 本身并没有完全实现服务注册与发现,而是将这一功能交给外部的注册中心(如 ZookeeperNacos 等)来处理。
  • 通过注册中心,Dubbo 实现了服务的动态注册与发现,能够支持分布式架构中的服务高可用、负载均衡和容错等重要功能。
  • 使用外部注册中心的好处包括高可用性、灵活的服务治理、分布式协调能力等。

因此,Dubbo 并不依赖自己实现服务注册与发现,而是借助成熟的注册中心组件来完成这些任务。

限流

网关

安全性 ,如黑名单

Nacos

nacos实现远程调用方案

Nacos 是一个开源的 服务发现配置管理 平台,常用于微服务架构中的服务注册与发现以及配置管理。它本身并不直接提供远程调用(如 Dubbo 或 gRPC 提供的服务调用),但可以与其他远程调用框架结合使用,在微服务架构中实现服务间的远程调用。

下面我将详细介绍如何通过 Nacos + Spring CloudNacos + Dubbo 实现远程调用。


1. Nacos + Spring Cloud 实现远程调用

在 Spring Cloud 微服务架构中,Nacos 通常作为服务注册与发现的中心,服务间的远程调用通过 Spring Cloud FeignSpring Cloud RestTemplate 来实现。

步骤:
  1. 服务注册与发现

    • 各个微服务注册到 Nacos。
    • Nacos 充当服务注册中心,提供服务发现功能。
  2. 服务提供者

    • 在 Spring Boot 服务中使用 @EnableDiscoveryClient 注解开启服务发现。
    • 使用 @RestController@Service 暴露远程调用接口。
  3. 服务消费者

    • 服务消费者同样需要启用 @EnableDiscoveryClient 来从 Nacos 获取服务列表。
    • 可以使用 Feign ClientRestTemplate 来调用其他微服务。
示例:Nacos + Spring Cloud + Feign + 远程调用

服务提供者

java 复制代码
// Application.java
@SpringBootApplication
@EnableDiscoveryClient
public class ServiceProviderApplication {
    public static void main(String[] args) {
        SpringApplication.run(ServiceProviderApplication.class, args);
    }
}

// Controller.java
@RestController
@RequestMapping("/hello")
public class HelloController {

    @GetMapping("/greet")
    public String greet() {
        return "Hello from Service Provider!";
    }
}

服务消费者

java 复制代码
// Application.java
@SpringBootApplication
@EnableDiscoveryClient
public class ServiceConsumerApplication {
    public static void main(String[] args) {
        SpringApplication.run(ServiceConsumerApplication.class, args);
    }
}

// Feign 客户端接口
@FeignClient(name = "service-provider")
public interface HelloClient {

    @GetMapping("/hello/greet")
    String greet();
}

// 服务消费者调用
@RestController
@RequestMapping("/consumer")
public class ConsumerController {

    @Autowired
    private HelloClient helloClient;

    @GetMapping("/call")
    public String callService() {
        return helloClient.greet();
    }
}

application.properties 配置文件:

复制代码

spring.application.name=service-consumer spring.cloud.nacos.discovery.server-addr=localhost:8848 spring.application.name=service-provider spring.cloud.nacos.discovery.server-addr=localhost:8848

解释:
  1. @EnableDiscoveryClient:在服务提供者和消费者中启用服务发现功能,使得它们能够与 Nacos 进行交互。
  2. @FeignClient(name = "service-provider"):Feign 用于通过服务名称调用服务,Feign 会自动处理服务发现与调用。
  3. spring.cloud.nacos.discovery.server-addr=localhost:8848:配置 Nacos 注册中心的地址。
Feign 优势:
  • 简洁:Feign 是声明式的 HTTP 客户端,服务间调用只需要通过接口进行,不需要关心底层的 HTTP 请求细节。
  • 负载均衡:Spring Cloud 提供的 Feign 支持客户端负载均衡,可以自动通过 Ribbon 来实现负载均衡。

2. Nacos + Dubbo 实现远程调用

Dubbo 是一个高性能的 RPC 框架,适用于服务间的远程调用。Nacos 可以与 Dubbo 集成,作为服务注册与发现的中心,Dubbo 用于处理具体的远程调用过程。

步骤:
  1. 服务注册与发现

    • Dubbo 服务在启动时将自身注册到 Nacos。
    • Dubbo 服务消费者通过 Nacos 查找服务提供者。
  2. 服务提供者

    • 在 Dubbo 服务中,通过 Nacos 作为注册中心进行服务注册。
  3. 服务消费者

    • 服务消费者通过 Dubbo 与 Nacos 进行集成,进行服务的发现和远程调用。
示例:Nacos + Dubbo + 远程调用

服务提供者

java 复制代码
// Application.java
@SpringBootApplication
public class ServiceProviderApplication {
    public static void main(String[] args) {
        SpringApplication.run(ServiceProviderApplication.class, args);
    }
}

// 服务接口
public interface HelloService {
    String sayHello();
}

// 服务实现
@Service
public class HelloServiceImpl implements HelloService {
    @Override
    public String sayHello() {
        return "Hello from Dubbo Service Provider!";
    }
}

服务消费者

java 复制代码
// Application.java
@SpringBootApplication
public class ServiceConsumerApplication {
    public static void main(String[] args) {
        SpringApplication.run(ServiceConsumerApplication.class, args);
    }
}

// 服务消费者调用
@DubboReference
private HelloService helloService;

@GetMapping("/call")
public String callService() {
    return helloService.sayHello();
}

application.properties 配置文件:

复制代码

# Nacos 配置 spring.cloud.nacos.discovery.server-addr=localhost:8848 spring.dubbo.registry.address=nacos://localhost:8848 spring.dubbo.application.name=service-consumer spring.dubbo.registry.id=nacos

解释:
  1. spring.dubbo.registry.address=nacos://localhost:8848:配置 Dubbo 的注册中心为 Nacos。
  2. @DubboReference:注解用于注入 Dubbo 服务接口,自动从 Nacos 获取服务提供者并执行远程调用。

3. Nacos 配置管理与远程调用

除了服务注册与发现,Nacos 还可以作为配置中心来管理远程调用中的配置。你可以通过 Nacos 动态加载服务的配置,从而在运行时调整服务间的调用方式、负载均衡策略等。

配置管理:
  1. 动态配置:通过 Nacos 提供的配置管理功能,可以动态调整服务间调用的配置。例如,负载均衡策略、调用超时时间等都可以通过 Nacos 配置中心进行管理。
  2. 环境隔离:Nacos 可以支持多环境配置,如开发、测试、生产环境的隔离,确保不同环境下的远程调用使用不同的配置。

总结

  1. Nacos + Spring Cloud

    • 利用 Nacos 作为服务注册与发现中心,服务消费者通过 Feign 或 RestTemplate 调用服务提供者。
    • Feign 简单易用,支持负载均衡和容错,适合大部分微服务架构中的服务调用。
  2. Nacos + Dubbo

    • 结合 Nacos 和 Dubbo,实现高性能的远程调用。
    • Dubbo 提供了丰富的远程调用功能,支持 RPC 通信、服务治理、负载均衡、容错等特性。
  3. Nacos 配置中心

    • Nacos 可以为远程调用提供配置管理功能,支持动态调整服务的行为(如负载均衡策略、超时设置等)。

通过这些集成方案,你可以利用 Nacos 作为中心来实现服务注册、发现、配置管理,并通过 Feign 或 Dubbo 进行高效的远程服务调用。

Feign与RestTemplate

在 Spring Cloud 微服务架构中,Nacos 通常作为服务注册与发现的中心,服务间的远程调用通过 Spring Cloud Feign 或 Spring Cloud RestTemplate 来实现。 二者区别是什么,代码举例说明

在 Spring Cloud 微服务架构中,Nacos 作为服务注册与发现的中心,Spring Cloud Feign 和 Spring Cloud RestTemplate 都可以用于实现服务间的远程调用,但它们有一些显著的区别。

1. Spring Cloud Feign

Feign 是一个声明式的 HTTP 客户端,可以通过接口方式来定义远程调用,Feign 会自动为你实现 HTTP 请求的细节。它结合了 Spring Cloud 的负载均衡(Ribbon)和服务发现(Eureka/Nacos),使得服务间调用变得非常简洁。

特点:
  • 声明式调用:通过接口方式定义远程调用,代码简洁。
  • 与 Spring Cloud 结合紧密:集成了负载均衡、服务发现、熔断等功能。
  • 自动处理 HTTP 请求:不需要手动编写 HTTP 请求的相关代码。
示例代码:

假设有一个用户服务(user-service)和一个订单服务(order-service)。

1. 添加依赖:pom.xml 中加入 Feign 和 Nacos 的相关依赖:

java 复制代码
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

2. 启用 Feign 客户端: 在 Spring Boot 启动类中启用 Feign 客户端:

java 复制代码
@SpringBootApplication
@EnableFeignClients
public class OrderServiceApplication {
    public static void main(String[] args) {
        SpringApplication.run(OrderServiceApplication.class, args);
    }
}

3. 定义 Feign 接口:

java 复制代码
@FeignClient(name = "user-service")  // user-service 是 Nacos 中注册的服务名称
public interface UserClient {
    @GetMapping("/user/{id}")
    User getUserById(@PathVariable("id") Long id);
}

4. 使用 Feign 调用远程服务:

java 复制代码
@RestController
@RequestMapping("/orders")
public class OrderController {

    @Autowired
    private UserClient userClient;

    @GetMapping("/{orderId}")
    public String getOrderDetails(@PathVariable Long orderId) {
        User user = userClient.getUserById(123L);  // 调用 user-service 服务
        return "Order for user: " + user.getName();
    }
}

2. Spring Cloud RestTemplate

RestTemplate 是 Spring 提供的一个同步 HTTP 客户端,用于发起 HTTP 请求。在 Spring Cloud 中,它通常与 Ribbon 和 Nacos 结合使用,用于实现服务间的调用,但相较于 Feign,RestTemplate 更加低级,需要手动配置 URL 和请求。

特点:
  • 程序员控制更多细节:需要手动编写 URL 和处理请求。
  • 灵活性高:可以更加灵活地控制 HTTP 请求的细节。
  • 不如 Feign 简洁:相对于 Feign 需要更多的样板代码。
示例代码:

假设同样有 user-serviceorder-service

1. 添加依赖:pom.xml 中加入 RestTemplate 和 Nacos 的相关依赖:

java 复制代码
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

2. 定义 RestTemplate Bean:

java 复制代码
@Configuration
public class RestTemplateConfig {
    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

项目实战

Resttemplate配置

java 复制代码
remote.maxTotalConnect=200
remote.maxConnectPerRoute=100
remote.connectTimeout=50000
remote.readTimeout=50000
java 复制代码
package com.smcv.mall.tasks.configure;

import org.apache.http.client.HttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.http.client.BufferingClientHttpRequestFactory;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.web.client.RestTemplate;

import java.nio.charset.StandardCharsets;
import java.util.List;

/**
 * @Author: shenjian
 * @Desription:
 * @Date: Created in 下午3:37 2017/11/24
 * @Modified By:
 */
@Configuration
@EnableCaching
@ConditionalOnClass(value = {RestTemplate.class, HttpClient.class})
@RefreshScope
public class RestTemplateConfiguration {

    @Value("${remote.maxTotalConnect}")
    private int maxTotalConnect; //连接池的最大连接数默认为0
    @Value("${remote.maxConnectPerRoute}")
    private int maxConnectPerRoute; //单个主机的最大连接数
    @Value("${remote.connectTimeout}")
    private int connectTimeout; //连接超时默认2s
    @Value("${remote.readTimeout}")
    private int readTimeout; //读取超时默认30s

    //创建HTTP客户端工厂
    private ClientHttpRequestFactory createFactory() {
        if (this.maxTotalConnect <= 0) {
            SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
            factory.setConnectTimeout(this.connectTimeout);
            factory.setReadTimeout(this.readTimeout);
            return factory;
        }
        HttpClient httpClient = HttpClientBuilder.create().setMaxConnTotal(this.maxTotalConnect).setMaxConnPerRoute(this.maxConnectPerRoute).build();
        HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(httpClient);
        factory.setConnectTimeout(this.connectTimeout);
        factory.setReadTimeout(this.readTimeout);
        return factory;
    }



    @Bean("getByBodyRestTemplate")
    @Primary
    public RestTemplate restTemplate() {
        RestTemplate restTemplate = new RestTemplate(new BufferingClientHttpRequestFactory(this.createFactory()));
        restTemplate.setRequestFactory(new HttpComponentsClientRestfulHttpRequestFactory());
        List<HttpMessageConverter<?>> converterList =  restTemplate.getMessageConverters();

        // 重新设置StringHttpMessageConverter字符集为UTF-8,解决中文乱码问题
        HttpMessageConverter<?> converterTarget = null;
        int index = 0;
        for (HttpMessageConverter<?> item : converterList) {
            if (StringHttpMessageConverter.class == item.getClass()) {
                converterTarget = item;
                break;
            }
            ++index;
        }
        if (null != converterTarget) {
            converterList.remove(converterTarget);
        }
        converterList.add(index, new StringHttpMessageConverter(StandardCharsets.UTF_8));

        // 加入日志打印
//        restTemplate.setInterceptors(Collections.singletonList((ClientHttpRequestInterceptor)restTemplateInterceptor));
        return restTemplate;
    }

}

3. 使用 RestTemplate 调用远程服务:

java 复制代码
@RestController
@RequestMapping("/orders")
public class OrderController {

    @Autowired
    private RestTemplate restTemplate;

    @Value("${user.service.url}")
    private String userServiceUrl;

    @GetMapping("/{orderId}")
    public String getOrderDetails(@PathVariable Long orderId) {
        String userUrl = userServiceUrl + "/user/123";  // 构造 user-service 的 URL
        ResponseEntity<User> response = restTemplate.exchange(userUrl, HttpMethod.GET, null, User.class);
        User user = response.getBody();
        return "Order for user: " + user.getName();
    }
}

application.properties 中配置 user-service 的 URL:

复制代码

user.service.url=http://user-service

3. 两者的主要区别

特性 Spring Cloud Feign Spring Cloud RestTemplate
使用方式 基于接口定义,声明式调用 基于手动 URL 和 HTTP 请求,编程式调用
简洁性 更简洁,无需关心请求细节 需要手动编写请求细节
集成 自动集成负载均衡(Ribbon)、服务发现(Nacos)等 手动配置 Ribbon 和服务发现
灵活性 较低,主要针对常规的 RESTful 调用 高,可以自由处理更多的 HTTP 细节
可维护性 高,代码简洁易读 低,需要编写更多的样板代码

总结:

  • Feign 适合在微服务架构中需要频繁进行服务间通信时使用,它提供了声明式的 HTTP 调用方式,能够简化代码并与 Spring Cloud 的其他组件(如 Ribbon、Nacos)紧密集成。
  • RestTemplate 提供了更多的灵活性和控制,适合需要精细控制 HTTP 请求的场景,但相对来说代码较为繁琐,且需要手动处理更多的细节。

通常情况下,推荐使用 Feign,因为它更符合微服务的设计理念,简洁且易于维护。

Spring Cloud RestTemplate 手动配置 Ribbon 和服务发现 具体如何实现的

项目中没有看到这个注解 @LoadBalanced // 启用 Ribbon 负载均衡

相关推荐
Vol火山8 小时前
云原生架构中的中间件容器化:优劣势与实践探索
云原生·中间件·架构·数字化
程序员JerrySUN8 小时前
BitBake 执行流程深度解析:从理论到实践
linux·开发语言·嵌入式硬件·算法·架构
dbcat官方9 小时前
2.微服务灰度发布落地实践(agent实现)
微服务·云原生·架构
峰子201217 小时前
Go语言实现守护进程的挑战
开发语言·后端·面试·架构·golang·go
绝无仅有18 小时前
gozero项目日志Prometheus的配置与实战
后端·面试·架构
绝无仅有19 小时前
gozero项目日志收集与配置实战
后端·面试·架构
uhakadotcom19 小时前
2025年,最新的AI发展趋势是什么?
后端·面试·架构
Elcker20 小时前
KOI技术-事件驱动编程(Sping后端)
java·spring·架构
陌夏微秋20 小时前
STM32单片机芯片与内部47 STM32 CAN内部架构 介绍
数据库·stm32·单片机·嵌入式硬件·架构·信息与通信