SpringCloud微服务负载均衡_Feign技术

一、介绍

声明性REST客户端:Feign
Feign是一个声明式的伪Http客户端,它使得写Http客户端变得更简单。使用Feign,只需要创建一个接口并注解。它具有可插拔的注解特性,可使用Feign 注解和JAX-RS注解。Feign支持可插拔的编码器和解码器。
Feign默认集成了Ribbon,并和Eureka结合,默认实现了负载均衡的效果。

  1. Feign 采用的是基于接口的注解
  2. Feign 整合了ribbon,具有负载均衡的能力
  3. Feign整合了Hystrix,具有熔断的能力

编程式实现
需要以具体代码表达在哪里(where)做什么(what),如何实现(how)
声明式实现
只需要声明在哪里(where )做什么(what),而无需关心如何实现(how)

注意,使用Feign就不再使用Ribbon,所以把Ribbon的依赖和@LoadBalance注解删除

二、使用Feign

1.引入pom依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

2.@EnableFeignClients

User服务启动类加注解,开启Feign

在这里插入图片描述

3.@FeignClient

使用Feign,不再使用Rest调用,就是正常的Controller调用Service.
具体的Feign的功能在Service中实现

Controller

    @Autowired
    UserService userService;

    @GetMapping("/callDept")
    public String callDept(){
        String msg = "访问Dept服务";
        return userService.callDept();
    }

Service
注意:DEPT是我们在application.yml配置文件中配置的项目名。而且Dept服务的两个节点的项目名都叫dept,只是端口号不同。

spring:
  application:
    name: dept
@FeignClient("DEPT")
public interface UserService {

    @GetMapping("/dept/called")
     String callDept() ;
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

服务被调用到,并且负载均衡轮询访问。

Bug 参数为[text/plain] 无法转化为json

方式零:
直接将返回类型修改为String。



方式一:

@GetMapping(value = "/dept/called",produces = "application/json;charset=UTF-8")

在这里插入图片描述


方式二:创建自定义解析类
public class MyMessageConverter extends MappingJackson2HttpMessageConverter {

    public MyMessageConverter(){
        List<MediaType> mediaTypes = new ArrayList<>();
        mediaTypes.add(MediaType.TEXT_PLAIN);
        setSupportedMediaTypes(mediaTypes);
    }
}

方式三:配置类中注入自定义解析类
@Configuration  // 有了该注解,该类就相当于是applicationContext.xml
public class ConfigBean {

    // 解决返回参数为[text/plain] 无法转化为json
    @Bean
    public Decoder feignDecoder(){
        MyMessageConverter myMessageConverter = new MyMessageConverter();
        // Java8的lambda表达式。 ->
        ObjectFactory<HttpMessageConverters> objectFactory = () -> new HttpMessageConverters(myMessageConverter);
        return new SpringDecoder(objectFactory);
    }
}


使用Feign带参调用服务-GET

UserController
在这里插入图片描述

UserService

在这里插入图片描述

使用Feign带参调用服务-POST

UserController

在这里插入图片描述
UserService

在这里插入图片描述

完整代码

YML配置文件

server:
  port: 8001 #服务端口
eureka:
  instance:
    hostname: user8001
    instance-id: user8001
    prefer-ip-address: true
  client:
    service-url:
       defaultZone: http://localhost:7000/eureka
spring:
  application:
    name: user8001

server:
  port: 8002 #服务端口
eureka:
  instance:
    hostname: dept8002
    instance-id: dept8002
    prefer-ip-address: true
  client:
    service-url:
       defaultZone: http://localhost:7000/eureka
spring:
  application:
    name: dept

server:
  port: 8003 #服务端口
eureka:
  instance:
    hostname: dept8003
    instance-id: dept8003
    prefer-ip-address: true
  client:
    service-url:
       defaultZone: http://localhost:7000/eureka
spring:
  application:
    name: dept

UserController

@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    RestTemplate restTemplate;
    @Autowired
    UserService userService;

    @GetMapping("/callDept")
    public String callDept(){
        String msg = "访问Dept服务";
        System.out.println(msg);
        return userService.callDept();
    }
    @GetMapping("/callDeptById1")
    public String callDeptById1(@RequestParam String id){
        String msg = "GET请求   表单形式";
        System.out.println(msg);
        return userService.callDeptAndParam(id);
    }
    @GetMapping("/callDeptById2/{id}")
    public String callDeptById2(@PathVariable("id") String id){
        String msg = "Get  路径带参";
        System.out.println(msg);
        return userService.callDeptAndParam2(id);
    }

    @PostMapping
    public String callDeptPost(@RequestBody Map<String,String> map){
        String msg = "POST  JSON";
        System.out.println(msg);
        return userService.callDeptPost(map);
    }
}

UserService

@FeignClient("DEPT")
public interface UserService {

    @GetMapping(value = "/dept/called",produces = "application/json;charset=UTF-8")
     String callDept() ;

    /**
     * 使用Fegin 访问 带参 GET请求   表单形式
     * @param id
     * @return
     */
    @GetMapping(value = "/dept/called2")
    String callDeptAndParam(@RequestParam("id") String id);

    /**
     * 以路径请求方式吓携带参数  Get  路径带参
     * @param id
     * @return
     */
    @GetMapping(value = "/dept/called/{id}")
    String callDeptAndParam2(@PathVariable("id") String id);

    @PostMapping(value ="/dept/beCalledPost")
    String callDeptPost(@RequestBody Map<String, String> map);
}

DeptController1

@RestController
@RequestMapping("/dept")
public class DeptController {

   @GetMapping("/called")
   public Object beCall() {
        System.out.println("dept GET  无参 : 被访问了");
        return "{\"code\":\"8002\"}";
    }
   @GetMapping("/called/{id}")
    public Object beCallById(@PathVariable("id") String id) {
        System.out.println("dept  GET 带参 表单形式    : 被访问了");
        return "{\"code\":\"8002\",\"id\":\""+id+"\"}";
    }

    @GetMapping("/called2")
    public Object beCallById2(@RequestParam("id") String id) {
        System.out.println("dept  GET 带参 路径形式: 被访问了");
        return "{\"code\":\"8002\",\"id\":\""+id+"\"}";
    }
    @PostMapping("/beCalledPost")
    public Object beCalledPost(@RequestBody Map<String,String> map){
        System.out.println("dept  POST 带参 : 被访问了");
        return "{\"code\":\"8002\",\"id\":\""+map.get("id")+"\",\"name\":\""+map.get("name")+"\"}";
    }
}

DeptController2

@RestController
@RequestMapping("/dept")
public class DeptController {

    @GetMapping("/called")
    public Object beCall() {
        System.out.println("dept GET  无参 : 被访问了");
        return "{\"code\":\"8003\"}";
    }
    @GetMapping("/called/{id}")
    public Object beCallById(@PathVariable("id") String id) {
        System.out.println("dept  GET 带参 表单形式    : 被访问了");
        return "{\"code\":\"8003\",\"id\":\""+id+"\"}";
    }

    @GetMapping("/called2")
    public Object beCallById2(@RequestParam("id") String id) {
        System.out.println("dept  GET 带参 路径形式: 被访问了");
        return "{\"code\":\"8003\",\"id\":\""+id+"\"}";
    }
    @PostMapping("/beCalledPost")
    public Object beCalledPost(@RequestBody Map<String,String> map){
        System.out.println("dept  POST 带参 : 被访问了");
        return "{\"code\":\"8003\",\"id\":\""+map.get("id")+"\",\"name\":\""+map.get("name")+"\"}";
    }
}

[Gitee仓库代码](https://gitee.com/L1692312138/spring-cloud_-ribbon_-fegin)
![在这里插入图片描述](https://img-blog.csdnimg.cn/20201106153739792.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0RyZWFtc0FyY2hpdGVjdHM=,size_16,color_FFFFFF,t_70#pic_center)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Liu_Shihao

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值