前几章讲到了通过Spring Cloud Ribbon和resttemplate实现客户端消费者调用,生产者提供的服务,而Spring Cloud openFeign还提供了一种比Ribbon更简单的服务调用方式 ——— 声明式服务调用
创建openfeign消费者服务cloud-feign-order80
第一步创建pom文件
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <artifactId>springcloud</artifactId> <groupId>org.example</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>cloud-feign-order80</artifactId> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!--swagger 整合swagger需要的依赖--> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> </dependency> <!--swagger ui--> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> </dependency> <dependency> <groupId>org.example</groupId> <artifactId>cloud-api-conmmon</artifactId> <version>1.0-SNAPSHOT</version> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <!--feign声明式服务的调用--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <executions> <execution> <goals> <goal>repackage</goal> </goals> </execution> </executions> <configuration> <fork>true</fork> <!-- fork: 如果没有配置该项配置,devtools不会起作用的,即应用不会restear --> </configuration> </plugin> </plugins> </build> </project>
创建application.yml文件
server: port: 80 spring: application: name: cloud-order-service eureka: client: register-with-eureka: true fetch-registry: true serviceUrl: defaultZone: http://eureka7001.com:7001/eureka/ #集群版
编写启动类开启feign功能
package com.shiwen; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; import org.springframework.cloud.openfeign.EnableFeignClients; /** * @author wangjie * @Title: OpenFeignApplication * @Description: openfeign声明式服务的调用 * @company: 西安石文软件有限公司 * @date 2020/10/1411:11 */ @SpringBootApplication @EnableFeignClients @EnableEurekaClient public class OpenFeignApplication { public static void main(String[] args) { SpringApplication.run(OpenFeignApplication.class,args); } }
编写controller消费,服务提供者的接口
package com.shiwen.controller; import com.shiwen.entity.CommonResult; import com.shiwen.service.FeignService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; /** * @author wangjie * @Title: FeignController * @Description: openfeign服务的调用 * @company: 西安石文软件有限公司 * @date 2020/10/1411:13 */ @RestController @RequestMapping("/order") public class FeignController { @Autowired private FeignService feignService; @GetMapping("/selete/{id}") public CommonResult getUserById(@PathVariable Long id){ return feignService.selectOne(id); } }
使用fegin调用服务提供者的服务就是需要编写对应的service
package com.shiwen.service; import com.shiwen.entity.CommonResult; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; /** * @author wangjie * @Title: FeignService * @Description: feign接口 * @company: 西安石文软件有限公司 * @date 2020/10/1411:19 */ @FeignClient("CLOUD-PAYMENT-SERVICE") public interface FeignService { @GetMapping("payment/select-one/{id}") CommonResult selectOne(@PathVariable("id") Long id); }
service中的 CLOUD-PAYMENT-SERVICE 服务提供者注册到eureka的服务名,@GetMapping("payment/select-one/{id}") 服务提供者的controller接口地址
启动单机版的eureka注册中心
启动cloud-provider-payment8001 和打包启动cloud-provider-payment8001 使用application-8002.yml配置文件启动 给注册中心注册两个服务8001,8002
访问http://localhost:80/order/selete/1
再次访问http://localhost:80/order/selete/1
也能实现两个服务的负载均衡调用,因为feign底层使用的还是ribbon的默认的轮巡算法实现负载调用的
openFeign的超时控制,openFeign默认消费者调用是1秒,超过1不在等待,直接报错连接超时
第一步再服务提供方写一个超时的接口
/** * 编写超时程序 */ @GetMapping("timeout") public CommonResult timeOutMethods(){ try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace(); } return new CommonResult(200,"超时服务",serverPort); }
第二不 openFeign调用服务
@RestController @RequestMapping("/order") public class FeignController { @Autowired private FeignService feignService; @GetMapping("/selete/{id}") public CommonResult getUserById(@PathVariable Long id){ return feignService.selectOne(id); } @GetMapping("/timeout") public CommonResult getTimeOut(){ return feignService.timeOutMethods(); } }
@FeignClient("CLOUD-PAYMENT-SERVICE") public interface FeignService { @GetMapping("payment/select-one/{id}") CommonResult selectOne(@PathVariable("id") Long id); @GetMapping("payment/timeout") CommonResult timeOutMethods(); }
配置ribbon的超时时间
ribbon:
ConnectTimeout: 5000
ReadTimeout: 5000
如果没有配置就会报连接超时的错误,配置了消费者调用还会等待
openFeign日志打印功能
日志的级别
配置日志bean
package com.shiwen.config; import feign.Logger; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * @author wangjie * @Title: OpenFeignConfig * @Description: feign的日志配置bean * @company: 西安石文软件有限公司 * @date 2020/10/1511:52 */ @Configuration public class OpenFeignConfig { /** * 日志的级别 * @return */ @Bean Logger.Level feignLevel(){ return Logger.Level.FULL; } }
application.yml开启日志
logging:
level:
com.shiwen.config.OpenFeignConfig: debug