Spring Cloud-hystrix Feign(九)

前面使用ribbon拦截RestTemplate 实现服务的负载均衡 使用Hystrix进行熔断降级请求缓存  用原生的方式 将会有大量的模板代码,feigin就是rabbon和Histrix的整合 同

使用feign只需要通过接口对服务方的绑定 实现多处调用  

使用例子

1.引入Pom依赖

     <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>
        <!--开启端点 用于dashboard监控-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

2.定义一个接口描述服务信息

@FeignClient("PROVIDER")
@RequestMapping("/user")
public interface UserService {

    @RequestMapping(value = "/findById",method = RequestMethod.GET)
    public User findById(@RequestParam("id") Integer id);
    @RequestMapping(value = "/findAll",method = RequestMethod.GET)
    public List<User> findAll();

    @RequestMapping(value = "/deleteById",method = RequestMethod.GET)
    public Boolean deleteById(@RequestParam("id")Integer id);

    @RequestMapping(value = "/update",method = RequestMethod.POST)
    public Boolean update(@RequestBody User user);
}

@FeignClient 是用于服务发现  发现指定服务

@RequestMapping 为请求指定服务 指定方式

@RequestBody 表示参数是封装在报文体出传输  服务端 接收也需要打RequestBody

3.入口类开启Fegin以及服务发现

@SpringBootApplication
@EnableFeignClients //开启feigin
@EnableDiscoveryClient //开启服务发现
public class SpringCloudFeignConsumerApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringCloudFeignConsumerApplication.class, args);
    }

}

4.通过注入实现调用

@RestController
public class UserContorller {
    @Autowired
    UserService  userService;
    @RequestMapping("/findById")
    @ResponseBody
    public User findById(Integer id) {
        return userService.findById(id);
    }

    @RequestMapping("/findAll")
    @ResponseBody
    public List<User> findAll() {
        return userService.findAll();
    }

    @RequestMapping("/deleteById")
    @ResponseBody
    public Boolean deleteById(Integer id) {
        return userService.deleteById(1);
    }

    @RequestMapping("/update")
    @ResponseBody
    public Boolean update() {
        User user=new User();
        user.setId(1);
        user.setName("测试修改");
        User filterUser = userService.findById(user.getId());
        filterUser.setName(user.getName());
        userService.update(filterUser);
        return true;
    }
}

 

继承特性

将接口定义在服务端 服务消费者通过继承方式实现服务订阅。避免 每个服务消费者 都要重复定义接口描述

1.新增一个API项目并被服务端和客户端依赖 同时依赖web 因为需要使用springMVC注解对接口描述

3.pom依赖

 <!--定义接口约束 需要用到springMVC的注解-->
    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
        </dependency>
    </dependencies>
    <!--用普通jar打包的方式-->
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-source-plugin</artifactId>
                <executions>
                    <execution>
                        <id>attach-sources</id>
                        <goals>
                            <goal>jar</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

jar包打包方式 都改为传统的打包方式 否则 其他依赖会报错 找不到 符号  因为存在2个入口类

3.api项目添加一个接口描述

@RequestMapping("/user")
public interface UserService {

    @RequestMapping(value = "/findById",method = RequestMethod.GET)
    public User findById(@RequestParam("id") Integer id);
    @RequestMapping(value = "/findAll",method = RequestMethod.GET)
    public List<User> findAll();

    @RequestMapping(value = "/deleteById",method = RequestMethod.GET)
    public Boolean deleteById(@RequestParam("id")Integer id);

    @RequestMapping(value = "/update",method = RequestMethod.POST)
    public Boolean update(@RequestBody User user);
}

4.更改provider

@Controller
@RequestMapping("/user")
public class UserContorller implements UserService {
    List<User> users;

    public UserContorller() {
        users = new ArrayList<>();
        users.add(new User(1, "小明", 1));
        users.add(new User(2, "小香", 0));
        users.add(new User(3, "小方", 0));
        users.add(new User(4, "小张", 0));
        users.add(new User(6, "小李", 0));

    }

    @RequestMapping("/findById")
    @ResponseBody
    public User findById(Integer id) {
        return users.stream().filter(c -> c.getId().intValue() == id.intValue()).findAny().get();
    }

    @RequestMapping("/findAll")
    @ResponseBody
    public List<User> findAll() {
        return users;
    }

    @RequestMapping("/deleteById")
    @ResponseBody
    public Boolean deleteById(Integer id) {
        return users.removeIf(c -> c.getId().intValue() == id.intValue());
    }

    @RequestMapping("/update")
    @ResponseBody
    public Boolean update(@RequestBody User user) {
        User filterUser = findById(user.getId());
        filterUser.setName(user.getName());
        return true;
    }
}

5.更改consumer Service继承api的Service

@FeignClient("PROVIDER")
public interface UserService extends com.liqiang.api.UserService {
}

6.consumer调用注入Service

@RestController
public class UserContorller {
    @Autowired
    UserService  userService;
    @RequestMapping("/findById")
    @ResponseBody
    public User findById(Integer id) {
        return userService.findById(id);
    }

    @RequestMapping("/findAll")
    @ResponseBody
    public List<User> findAll() {
        return userService.findAll();
    }

    @RequestMapping("/deleteById")
    @ResponseBody
    public Boolean deleteById(Integer id) {
        return userService.deleteById(1);
    }

    @RequestMapping("/update")
    @ResponseBody
    public Boolean update() {
        User user=new User();
        user.setId(1);
        user.setName("测试修改");
        User filterUser = userService.findById(user.getId());
        filterUser.setName(user.getName());
        userService.update(filterUser);
        return true;
    }
}

继承的缺点   接口修改 会导致调用端的构建失败 不同通过版本控制可以避免 

Ribbon配置

全局配置

通过ribbon.<属性>=..

ribbon:
  ConnectTimeout: 500
  ReadTimeout=5000

指定服务配置及重试

<服务名>.ribbon.<属性>=...  服务名为@FeginClient配置

#对指定服务设置rabbion全局参数 Fegin接口@FeignClient("PROVIDER")
PROVIDER:
  ribbon:
    #配置首台服务器重试1次
    MaxAutoRetries: 1
    #配置其他服务器重试两次
    MaxAutoRetriesNextServer: 2
    #链接超时时间
    ConnectTimeout: 500
    #请求处理时间
    ReadTimeout: 2000
    #每个操作都开启重试机制
    OkToRetryOnAllOperations: true

hystrix配置

全局配置

与hystrix配置一样

#配置断路器超时时间,默认是1000(1秒)
hystrix:
  command:
    default:
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 12000

通过指令配置 

hystrix.command.<commandKey> commandKey默认以方法名作为标识

禁用hystrix

全部禁用

feign:
  hystrix:
    enabled: true #启用hystrix false为禁用 

指定服务禁用

@Configuration
public class DisableHystrixConfiguration {
    @Bean
    @Scope("prototype")
    public Feign.Builder feignBuilder() {
        return Feign.builder();

    }
}

 

@FeignClient(value = "PROVIDER",configuration = DisableHystrixConfiguration.class)
public interface UserService extends com.liqiang.api.UserService {
}

服务降级

1.增加一个Service的接口类

public class UserServiceFaillBack implements UserService {
    @Override
    public User findById(Integer id) {
        return null;
    }

    @Override
    public List<User> findAll() {
        return null;
    }

    @Override
    public Boolean deleteById(Integer id) {
        return false;
    }

    @Override
    public Boolean update(User user) {
        return false;
    }
}
@FeignClient(value = "PROVIDER",configuration = DisableHystrixConfiguration.class,fallback = UserServiceFaillBack.class)
public interface UserService extends com.liqiang.api.UserService {
}

请求压缩

feign:
  compression:
    request:
      enabled: true  #feign请求gizp压缩 减少网络损耗
    response:
      enabled: true  #feign响应gizp压缩 减少网络损耗
      #启用压缩 压缩指定格式  超过对应大小的才开始压缩
      #feign.compression.request.enabled=true
      #feign.compression.request.mime-types=text/xml,application/xml,application/json #指定格式
      #feign.compression.request.min-request-size=2048 #指定大小

日志配置

对服务开启日志输出

#还需要在application配置Logger.Level  详情区主类去看
logging:
  level:
    com:
      liqiang:
        feginService:
          HelloExtendService: DEBUG

还要在主类设置日志界别

class SpringcloudFeiginConsumerApplication {

    /***
     * 日志可选级别
     * • NONE: 不记录任何信息。
     * • BASIC: 仅记录请求方法、URL以及响应状态码和执行时间。
     * • HEADERS: 除了记录BASIC级别的信息之外, 还会记录请求和响应的头信息。
//     * • FULL: 记录所有请求与响应的明细, 包括头信息、 请求体、 元数据等。
//     * @return
     */
    @Bean
    public Logger.Level feignLoggerLevel() {
        return Logger.Level.FULL;
    }
    public static void main(String[] args) {
        SpringApplication.run(SpringcloudFeiginConsumerApplication.class, args);
    }


}

 

可能遇到的问题 

如果遇到feign注解无效,同时配置了scan 包扫描。   可以在@EnableFeignClients("你的feign包")或者application.properties 配置feign.client.package=com.crb.ocms.stock

posted @ 2018-12-20 16:13  意犹未尽  阅读(909)  评论(0编辑  收藏  举报