Spring Cloud - Feign声明式服务
Spring Cloud服务提供方都是以HTTP接口的方式暴露自身服务的,服务消费方可以通过URLConnection、HttpClient、OkHttp等HTTP工具包,以及前文中使用的RestTemplate。
而Feign以一种更为优雅、便捷的方式实现了HTTP接口的调用。我们可以借助Feign在客户端(也就是服务消费方)定义本地接口,此接口指定了调用服务提供方的具体HTTP接口,然后消费方就可以通过Spring注入该接口,以调用本地方法的形式就能消费提供方的服务。
1.Feign整合Eureka
继续使用前文的项目代码,稍作修改来完成Feign的使用。
Step 1:添加spring-cloud-starter-feign依赖。
compile('org.springframework.cloud:spring-cloud-starter-netflix-eureka-client:2.0.0.RELEASE')
compile('org.springframework.cloud:spring-cloud-starter-netflix-ribbon:2.0.0.RELEASE')
compile('org.springframework.cloud:spring-cloud-starter-openfeign:2.0.0.RELEASE')
Step 2:修改Spring Boot启动类,添加@EnableFeignClients注解。
@EnableFeignClients
@SpringBootApplication
class EurekaClientConsumerApplication
fun main(args: Array<String>) {
runApplication<EurekaClientConsumerApplication>(*args)
}
Step 3:定义接口,指定调用的服务和具体的接口
@FeignClient注解的value值需要与服务提供方的spring.application.name配置值一致,@GetMapping注解的name值需要与服务提供方的HTTP接口一致。
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.cloud.openfeign.FeignClient
@FeignClient("eureka-client-provider")
interface TestService {
@GetMapping("/test")
fun test(): String
}
Step 4:修改TestController,注入定义好的接口,调用本地接口方法。
import com.yuanzicheng.eurekaclientconsumer.service.TestService
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RestController
@RestController
class TestController {
@Autowired
private lateinit var testService: TestService
@GetMapping("/test")
fun test(): String? {
return testService.test()
}
}
至此,我们就可以在服务消费方通过Feign以本地接口的方式调用服务提供方的REST服务,而不需要通过HTTP工具包以URL的方式访问。
更为让人欣喜的是,Spring Cloud Feign扩展了对Spring MVC注解的支持,同时还整合了Ribbon来提供自动的均衡负载支持。
2.Feign日志处理
Feign对日志的处理非常灵活,可以为每个Feign客户端指定日志策略,每个Feign客户端都会创建一个logger,默认情况下logger的名称是Feign接口的完整类名。
我们可以为每个Feign客户端配置各自的Logger.Level对象,指定日志输出级别了,Logger.Level的可选值如下:
- NONE:不记录任何日志(默认值)
- BASIC:仅记录请求方法、URL、响应状态码、执行时间
- HEADERS:记录请求方法、URL、响应状态码、执行时间、请求和响应的header
- FULL:记录请求和响应的header、body、元数据
特别需要注意的是,Feign的Logger.Level只会响应DEBUG级别的日志。所以,如果想自定义Feign的日志配置,需要将Feign接口的日志级别设为DEBUG。
2.1 为Feign接口添加日志
Step 1:添加自定义的Configuration类,设置Feign的Logger.Level
import feign.Logger
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
@Configuration
class FeignLogConfiguration {
@Bean
internal fun feignLoggerLevel(): Logger.Level {
return Logger.Level.FULL
}
}
Step 2:修改Feign接口,指定Configuration类
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.cloud.openfeign.FeignClient
import com.yuanzicheng.eurekaclientconsumer.FeignLogConfiguration
@FeignClient(value = "eureka-client-provider", configuration = arrayOf(FeignLogConfiguration::class))
interface TestService {
@GetMapping("/test")
fun test(): String
}
Step 3:修改Feign接口的日志级别
logging:
level:
com.yuanzicheng.eurekaclientconsumer.service.TestService: debug
Step 4:请求,查看日志输出
2018-08-02 19:44:19.689 DEBUG 2083 --- [io-30001-exec-5] c.y.e.service.TestService : [TestService#test] ---> GET http://eureka-client-provider/test HTTP/1.1
2018-08-02 19:44:19.689 DEBUG 2083 --- [io-30001-exec-5] c.y.e.service.TestService : [TestService#test] ---> END HTTP (0-byte body)
2018-08-02 19:44:19.694 DEBUG 2083 --- [io-30001-exec-5] c.y.e.service.TestService : [TestService#test] <--- HTTP/1.1 200 (4ms)
2018-08-02 19:44:19.694 DEBUG 2083 --- [io-30001-exec-5] c.y.e.service.TestService : [TestService#test] content-length: 15
2018-08-02 19:44:19.694 DEBUG 2083 --- [io-30001-exec-5] c.y.e.service.TestService : [TestService#test] content-type: text/plain;charset=UTF-8
2018-08-02 19:44:19.694 DEBUG 2083 --- [io-30001-exec-5] c.y.e.service.TestService : [TestService#test] date: Thu, 02 Aug 2018 11:44:19 GMT
2018-08-02 19:44:19.694 DEBUG 2083 --- [io-30001-exec-5] c.y.e.service.TestService : [TestService#test]
2018-08-02 19:44:19.695 DEBUG 2083 --- [io-30001-exec-5] c.y.e.service.TestService : [TestService#test] 20001 : test...
2018-08-02 19:44:19.695 DEBUG 2083 --- [io-30001-exec-5] c.y.e.service.TestService : [TestService#test] <--- END HTTP (15-byte body)
2018-08-02 19:45:31.846 DEBUG 2083 --- [io-30001-exec-7] c.y.e.service.TestService : [TestService#test] ---> GET http://eureka-client-provider/test HTTP/1.1
2018-08-02 19:45:31.846 DEBUG 2083 --- [io-30001-exec-7] c.y.e.service.TestService : [TestService#test] ---> END HTTP (0-byte body)
2018-08-02 19:45:31.851 DEBUG 2083 --- [io-30001-exec-7] c.y.e.service.TestService : [TestService#test] <--- HTTP/1.1 200 (4ms)
2018-08-02 19:45:31.851 DEBUG 2083 --- [io-30001-exec-7] c.y.e.service.TestService : [TestService#test] content-length: 15
2018-08-02 19:45:31.851 DEBUG 2083 --- [io-30001-exec-7] c.y.e.service.TestService : [TestService#test] content-type: text/plain;charset=UTF-8
2018-08-02 19:45:31.852 DEBUG 2083 --- [io-30001-exec-7] c.y.e.service.TestService : [TestService#test] date: Thu, 02 Aug 2018 11:45:31 GMT
2018-08-02 19:45:31.852 DEBUG 2083 --- [io-30001-exec-7] c.y.e.service.TestService : [TestService#test]
2018-08-02 19:45:31.852 DEBUG 2083 --- [io-30001-exec-7] c.y.e.service.TestService : [TestService#test] 20002 : test...
2018-08-02 19:45:31.852 DEBUG 2083 --- [io-30001-exec-7] c.y.e.service.TestService : [TestService#test] <--- END HTTP (15-byte body)