微服务-OpenFeign-工程案例

Ribbon

前置知识

是NetFlix的开源项目,主要来提供关于客户端的负载均衡能力。从多个服务提供方,选取一个节点发起调用。

Feign:NetFlix,SpringCloud 的第一代LB(负载均衡)客户端工具包。

OpenFeign:SpringCloud自研,SpringCloud的第二代(负载均衡工具包),扩展支持了@RequestMapping,@GetMapping等之类的注解的能力。

Feign 和 OpenFeign都是基于Ribbon。

实践案例

Provider & Consumer 都引入相同的依赖

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

Provider

java 复制代码
@RestController
public class EchoController {
    @GetMapping(value = "/echo/{string}")
    public String echo(@PathVariable String string) {
        return "Hello Nacos Discovery " + string;
    }
}

Consumer

java 复制代码
@SpringBootApplication
@EnableDiscoveryClient
public class OpenFeignConsumerApplication {
    @Bean
    @LoadBalanced // 这个注解就实现了负载均衡,是因为底层已经封装了Ribbon的东西
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
    public static void main(String[] args) {
        SpringApplication.run(OpenFeignConsumerApplication.class);
    }
}

我们可以看到这里有Ribbon相关的依赖:

OpenFeign 搭建

xml 复制代码
<com.alibaba.cloud.version>2.2.8.RELEASE</com.alibaba.cloud.version>
<com.cloud.version>Hoxton.SR12</com.cloud.version>
<com.dubbo.version>2.2.7.RELEASE</com.dubbo.version>
<dependency>
     <groupId>com.alibaba.cloud</groupId>
     <artifactId>spring-cloud-alibaba-dependencies</artifactId>
     <version>${com.alibaba.cloud.version}</version>
     <type>pom</type>
     <scope>import</scope>
   </dependency>
   <dependency>
     <groupId>org.springframework.cloud</groupId>
     <artifactId>spring-cloud-dependencies</artifactId>
     <version>${com.cloud.version}</version>
     <type>pom</type>
     <scope>import</scope>
   </dependency>
   <!-- https://mvnrepository.com/artifact/com.alibaba.cloud/spring-cloud-starter-dubbo -->
   <dependency>
     <groupId>com.alibaba.cloud</groupId>
     <artifactId>spring-cloud-starter-dubbo</artifactId>
     <version>${com.dubbo.version}</version>
   </dependency>

Provider

xml 复制代码
<dependency>
     <groupId>com.alibaba.cloud</groupId>
     <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
 </dependency>
 <dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-web</artifactId>
 </dependency>
java 复制代码
@RestController
public class EchoController {
    @GetMapping(value = "/echo/{string}")
    public String echo(@PathVariable String string) {
        return "Hello Nacos Discovery " + string;
    }
}

Consumer

xml 复制代码
<dependency>
     <groupId>com.alibaba.cloud</groupId>
     <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
 </dependency>
 <dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-web</artifactId>
 </dependency>
 <dependency>
	 <groupId>org.springframework.cloud</groupId>
	 <artifactId>spring-cloud-starter-openfeign</artifactId>
 </dependency>
java 复制代码
@FeignClient("openfigen-provider") // 服务提供方 新建一个接口和服务提供方一致
public interface FeignController {
    @GetMapping(value = "/echo/{string}")
    String echo(@PathVariable String string);
}

@RestController
public class EchoController {
    @Autowired
    FeignController feignController;
    @RequestMapping(value = "/echo/{str}", method = RequestMethod.GET)
    public String echo(@PathVariable String str) {
        return feignController.echo(str); // 可以像调用本地方法一样的调用远程方法
    }
}

@SpringBootApplication
@EnableDiscoveryClient 
@EnableFeignClients // 注意这个注解提供了远程调用的能力
public class OpenFeignConsumerApplication {
    public static void main(String[] args) {
        SpringApplication.run(OpenFeignConsumerApplication.class);
    }
}

负载均衡 + 降级演示

负载均衡

首先我们搭建三个服务提供方,简单的搭建直接使用启动参数-Dserver.port 指定不同的端口进行启动,然后在提供方进行调用。

消费方代码,可以看到打印不同的端口。

java 复制代码
@RestController
public class EchoController {
    @Value("${server.port}")
    private String port;
    @GetMapping(value = "/echo/{string}")
    public String echo(@PathVariable String string) {
        return "Hello Nacos Discovery " + string + " port : " + port;
    }
}
降级
  • 实现接口的方式,我们不知道错误的原因
java 复制代码
@FeignClient(name = "openfeign-provider",
 fallback = DegradeFeignClientFallback.class
)
public interface DegradeFeignClient {

    @RequestMapping(value = "/echo/{id}", method = RequestMethod.GET)
    public String echo(@PathVariable String id) ;
}

@Component
public class DegradeFeignClientFallback implements DegradeFeignClient {

    @Override
    public String echo(String id) {
        return "Fallback recv args: id=" + id
                + ", date=" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSSSS").format(new Date());
    }
}

我们在服务端构造一个错误,如果抛异常会走降级处理:

java 复制代码
@RestController
public class EchoController {
    @Value("${server.port}")
    private String port;
    @GetMapping(value = "/echo/{string}")
    public String echo(@PathVariable String string) {
        int a = 3/ 0; // 服务端构造错误
        return "Hello Nacos Discovery " + string + " port : " + port;
    }
}
  • 实现factory的方式,好处是我们可以知道错误的原因
java 复制代码
@FeignClient(name = "openfeign-provider",
    fallback = DegradeFeignClientFallback.class
)
java 复制代码
@Component
public class DegradeFeignClientFallbackFactory implements FallbackFactory<DegradeFeignClientFallbackFactory.DegradeFeignClientFallbackFactoryInner> {

    @Override
    public DegradeFeignClientFallbackFactoryInner create(Throwable cause) {
        System.out.println("错误原因: " + cause.getMessage());

        return new DegradeFeignClientFallbackFactoryInner();
    }

    static class DegradeFeignClientFallbackFactoryInner implements DegradeFeignClient {

        @Override
        public String echo(String id) {
            return "FallbackFactory recv args: id=" + id
                    + ", date=" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSSSS").format(new Date());
        }
    }
}
相关推荐
Decay__5 小时前
05_MySQL 常用 SQL 大全 —— 诊断、管理、优化辅助 SQL 与三大系统库速查
运维·数据库·sql·mysql·架构
GlobalInfo7 小时前
2026年机器人多指灵巧手市场分析报告——涵盖行业调查、趋势分析与发展前景
大数据·人工智能·microsoft·微服务·机器人
代码山河7 小时前
Python就业方向全解析:后端、爬虫、数据分析、AI你选哪个?
python·学习·架构·教程·面向对象·项目
微订校园外卖平台9 小时前
校园外卖平台选模板还是定制:架构、数据流与验收清单
大数据·架构·外卖系统·本地生活·微订
ZhengEnCi10 小时前
用 AI 写代码为什么拼到最后还是拼人:算力瓶颈与领域专家提示词的本质差异
算法·架构
Decay__11 小时前
04_MySQL DBA 日常运维手册 —— 会话管理、锁与阻塞、事务监控、慢查询与日志巡检
运维·数据库·sql·mysql·架构
阿里云云原生13 小时前
Agent 数据飞轮平台的选型和实践
云原生
华普微HOPERF14 小时前
Matter协议架构详解:数据模型与交互模型深度解析
microsoft·架构·交互
做运维的阿瑞14 小时前
云项目可观测性与成本治理:告警、日志、Dashboard 与预算标签
大数据·云原生·云计算·terraform
4SAPI15 小时前
多国产模型混合调度与企业级治理生产选型指南:4SAPI、硅基流动与 OpenRouter 的架构权衡
大数据·人工智能·架构·php