一马绝、fegin簡介
fegin 是 Netflix 開發(fā)的聲明式匿辩、模板化的HTTP客戶端,其令該來自Retrofit氛堕、JAXRS-2.0以及WebSocket。feign可幫助我們更加便捷野蝇,優(yōu)雅的調(diào)用HTTP API讼稚。
在spring cloud中,使用feign非常簡單绕沈,創(chuàng)建一個接口锐想,并在接口上添加一些注解,代碼就完成了乍狐。feign支持多種注解赠摇,例如feign自帶的注解或者JAX-RS注解等 。
spring cloud對feign進行了增強浅蚪,使feign支持了Spring MVC注解藕帜,并整合了Ribbon和Eureka
,從而讓Feign的使用更加便捷。
二惜傲、使用
添加依賴
<!-- 包含了Ribbon 和 hystrix -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
編寫 接口
path 是請求控制器的路徑
name 是訪問服務的 application.name
// name=eureka里注冊的服務
@FeignClient(path = "test", name = "client-hyq-life-server")
public interface TestApi {
@RequestMapping(value = "/idnex", method = RequestMethod.GET)
String idnex();
}
編寫實現(xiàn)
@RestController
@RequestMapping("test")
public class TestController implements TestApi {
@Autowired
private TestServer testServer;
@Override
public String idnex(){
return testServer.idnex();
}
}
編寫調(diào)用
@RestController
@RequestMapping("/test")
public class TestController {
@Autowired
private TestApi testApi;
@GetMapping("/index")
public String index(){
return testApi.idnex();
}
}
如果兩個服務是分離的都需要給啟動類加
@EnableFeignClients
@SpringBootApplication
public class BffAppServerApplication {
public static void main(String[] args) {
SpringApplication.run(BffAppServerApplication.class, args);
}
}
三洽故、Feign對壓縮的支持
feign:
# 不使用 openfeign 自帶的熔斷
hystrix:
enabled: false
compression:
#配置請求 GZIP 壓縮
request:
enabled: true
#配置壓縮支持的 MIME TYPE
mime-types: text/xml,application/xml,application/json
#配置壓縮數(shù)據(jù)大小的最小閥值,只有超過了這個大小的請求才會對其進行壓縮。,默認 2048
min-request-size: 300
#配置響應 GZIP 壓縮
response:
enabled: true
四盗誊、feign 對OkHttp的支持
依賴
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-okhttp</artifactId>
</dependency>
攔截日志时甚,這里建議做的有意義一些。
/**
* @author big uncle
* @date 2020/6/17 9:02
* ok http 攔截日志
**/
@Slf4j
public class OkHttpLogInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
log.debug("OkHttpUrl : " + chain.request().url());
return chain.proceed(chain.request());
}
}
配置
/**
* @author big uncle
* @date 2020/6/17 8:58
**/
@Configuration
@ConditionalOnClass(Feign.class)
@AutoConfigureBefore(FeignAutoConfiguration.class)
public class FeignOkHttpConfig {
@Bean
public okhttp3.OkHttpClient okHttpClient(){
return new okhttp3.OkHttpClient.Builder()
// 讀取超時設(shè)置
.readTimeout(60, TimeUnit.SECONDS)
// 連接超時設(shè)置
.connectTimeout(60, TimeUnit.SECONDS)
//
.writeTimeout(120, TimeUnit.SECONDS)
.connectionPool(new ConnectionPool())
.addInterceptor(okHttpLogInterceptor())
// .addInterceptor();
.build();
}
@Bean
public OkHttpLogInterceptor okHttpLogInterceptor(){
return new OkHttpLogInterceptor();
}
}
配置出現(xiàn)問題哈踱,發(fā)現(xiàn)配置的時間一直不生效荒适,我讀取時間設(shè)置30秒,在攔截里面看只有1秒开镣,所以很多時候提示超時吻贿。
最后有個大神跟我說了,fegin 一直都是用的是 default 配置哑子,讓我在yml配置 connectTimeout舅列,readTimeout
feign:
compression:
# 請求壓縮
request:
enabled: true
mime-types: "text/xml,application/xml,application/json"
# 用于設(shè)置請求的最小閾值
min-request-size: 1024
# 響應壓縮
response:
enabled: true
hystrix:
enabled: false
okhttp:
enabled: true
client:
config:
default:
connectTimeout: 30000
readTimeout: 40000
經(jīng)過發(fā)現(xiàn)的確可以做到肌割,在代碼里的配置優(yōu)先級居然沒有配置文件高,我個人覺得是有問題的帐要,忽然又想到那配置的池是否也是無用的把敞,待觀察。
五榨惠、日志
這里為了看每個請求的路徑奋早,參數(shù),耗時我們可以進行如下操作赠橙,loggerLevel:
feign:
compression:
# 請求壓縮
request:
enabled: true
mime-types: "text/xml,application/xml,application/json"
# 用于設(shè)置請求的最小閾值
min-request-size: 1024
# 響應壓縮
response:
enabled: true
hystrix:
enabled: false
okhttp:
enabled: true
client:
config:
default:
connectTimeout: 30000
readTimeout: 40000
# BASIC FULL HEADERS NONE
loggerLevel: BASIC
BASIC 打印如下
2020-06-18 09:45:51.670 DEBUG 26772 --- [nio-8888-exec-1] com.giant.cloud.api.MenuApi : [MenuApi#getSonDataMenuList] ---> POST http://server-data-platform/menu/getSonDataMenuList HTTP/1.1
2020-06-18 09:45:52.637 DEBUG 26772 --- [nio-8888-exec-1] com.giant.cloud.api.MenuApi : [MenuApi#getSonDataMenuList] <--- HTTP/1.1 200 (966ms)
2020-06-18 09:45:52.767 DEBUG 26772 --- [nio-8888-exec-2] c.giant.cloud.api.ElectricityStationApi : [ElectricityStationApi#getElectricityStationList] ---> POST http://server-data-platform/electricityStation/getElectricityStationList HTTP/1.1
2020-06-18 09:45:52.805 DEBUG 26772 --- [nio-8888-exec-2] c.giant.cloud.api.ElectricityStationApi : [ElectricityStationApi#getElectricityStationList] <--- HTTP/1.1 200 (38ms)
FULL 打印如下
2020-06-18 09:54:05.190 DEBUG 29140 --- [nio-8888-exec-1] com.giant.cloud.api.MenuApi : [MenuApi#getSonDataMenuList] ---> POST http://server-data-platform/menu/getSonDataMenuList HTTP/1.1
2020-06-18 09:54:05.191 DEBUG 29140 --- [nio-8888-exec-1] com.giant.cloud.api.MenuApi : [MenuApi#getSonDataMenuList] Content-Length: 1733
2020-06-18 09:54:05.191 DEBUG 29140 --- [nio-8888-exec-1] com.giant.cloud.api.MenuApi : [MenuApi#getSonDataMenuList] Content-Type: application/json
2020-06-18 09:54:05.191 DEBUG 29140 --- [nio-8888-exec-1] com.giant.cloud.api.MenuApi : [MenuApi#getSonDataMenuList]
2020-06-18 09:54:05.191 DEBUG 29140 --- [nio-8888-exec-1] com.giant.cloud.api.MenuApi : [MenuApi#getSonDataMenuList] {"data":{"id":null,"parentId":null,"menuName":null,"menuPath":"/electricityStation/list","menuOrder":null,"icon":null,"remarks":null,"menuData":null,"menuButton":null},"token":"5a717dca1142d685c8aa54b45d0388c8","user":{"id":1,"account":"15771720565","name":"馮謙潤","phone":"15771720565","onlineState":null,"remarks":"fdsafdsa","rolesId":1,"avatar":null,"token":"5a717dca1142d685c8aa54b45d0388c8","roles":{"id":1,"roleName":"超級管理員","remarks":"2222","menus":null},"menus":[{"id":1,"parentId":0,"menuName":"大屏展示","menuPath":"/dashboard","menuOrder":1000,"icon":"el-icon-monitor","remarks":null,"menuData":false,"menuButton":false,"child":[]},{"id":2,"parentId":0,"menuName":"數(shù)據(jù)分析","menuPath":"/dataAnalysis","menuOrder":2000,"icon":"el-icon-data-line","remarks":null,"menuData":false,"menuButton":false,"child":[]},{"id":3,"parentId":0,"menuName":"系統(tǒng)管理","menuPath":"/setting","menuOrder":3000,"icon":"el-icon-setting","remarks":null,"menuData":false,"menuButton":false,"child":[{"id":5,"parentId":3,"menuName":"角色管理","menuPath":"/setting/roles","menuOrder":3200,"icon":null,"remarks":null,"menuData":false,"menuButton":false,"child":[]},{"id":6,"parentId":3,"menuName":"菜單管理","menuPath":"/setting/menus","menuOrder":3300,"icon":null,"remarks":null,"menuData":false,"menuButton":false,"child":[]}]},{"id":16,"parentId":0,"menuName":"電站管理","menuPath":"/electricityStation","menuOrder":4000,"icon":"el-icon-lightning","remarks":null,"menuData":false,"menuButton":false,"child":[{"id":17,"parentId":16,"menuName":"電站信息","menuPath":"/electricityStation/list","menuOrder":4100,"icon":null,"remarks":"列出所有電站","menuData":false,"menuButton":false,"child":[]}]}]}}
2020-06-18 09:54:05.191 DEBUG 29140 --- [nio-8888-exec-1] com.giant.cloud.api.MenuApi : [MenuApi#getSonDataMenuList] ---> END HTTP (1733-byte body)
2020-06-18 09:54:06.014 DEBUG 29140 --- [nio-8888-exec-1] com.giant.cloud.api.MenuApi : [MenuApi#getSonDataMenuList] <--- HTTP/1.1 200 (822ms)
2020-06-18 09:54:06.015 DEBUG 29140 --- [nio-8888-exec-1] com.giant.cloud.api.MenuApi : [MenuApi#getSonDataMenuList] connection: keep-alive
2020-06-18 09:54:06.015 DEBUG 29140 --- [nio-8888-exec-1] com.giant.cloud.api.MenuApi : [MenuApi#getSonDataMenuList] content-type: application/json
2020-06-18 09:54:06.015 DEBUG 29140 --- [nio-8888-exec-1] com.giant.cloud.api.MenuApi : [MenuApi#getSonDataMenuList] date: Thu, 18 Jun 2020 01:54:05 GMT
2020-06-18 09:54:06.015 DEBUG 29140 --- [nio-8888-exec-1] com.giant.cloud.api.MenuApi : [MenuApi#getSonDataMenuList] keep-alive: timeout=60
2020-06-18 09:54:06.015 DEBUG 29140 --- [nio-8888-exec-1] com.giant.cloud.api.MenuApi : [MenuApi#getSonDataMenuList] transfer-encoding: chunked
2020-06-18 09:54:06.015 DEBUG 29140 --- [nio-8888-exec-1] com.giant.cloud.api.MenuApi : [MenuApi#getSonDataMenuList]
2020-06-18 09:54:06.017 DEBUG 29140 --- [nio-8888-exec-1] com.giant.cloud.api.MenuApi : [MenuApi#getSonDataMenuList] {"code":200,"msg":null,"data":[{"id":24,"parentId":17,"menuName":"電站數(shù)據(jù)","menuPath":"/electricityStation/data","menuOrder":4110,"icon":null,"remarks":null,"menuData":true,"menuButton":false,"child":[{"id":25,"parentId":24,"menuName":"平頂山","menuPath":"/electricityStation/data/pds","menuOrder":4111,"icon":null,"remarks":null,"menuData":true,"menuButton":false,"child":[]}]}]}
2020-06-18 09:54:06.017 DEBUG 29140 --- [nio-8888-exec-1] com.giant.cloud.api.MenuApi : [MenuApi#getSonDataMenuList] <--- END HTTP (388-byte body)
2020-06-18 09:54:06.453 DEBUG 29140 --- [nio-8888-exec-3] c.giant.cloud.api.ElectricityStationApi : [ElectricityStationApi#getElectricityStationList] ---> POST http://server-data-platform/electricityStation/getElectricityStationList HTTP/1.1
2020-06-18 09:54:06.453 DEBUG 29140 --- [nio-8888-exec-3] c.giant.cloud.api.ElectricityStationApi : [ElectricityStationApi#getElectricityStationList] Content-Length: 1756
2020-06-18 09:54:06.453 DEBUG 29140 --- [nio-8888-exec-3] c.giant.cloud.api.ElectricityStationApi : [ElectricityStationApi#getElectricityStationList] Content-Type: application/json
2020-06-18 09:54:06.453 DEBUG 29140 --- [nio-8888-exec-3] c.giant.cloud.api.ElectricityStationApi : [ElectricityStationApi#getElectricityStationList]
2020-06-18 09:54:06.453 DEBUG 29140 --- [nio-8888-exec-3] c.giant.cloud.api.ElectricityStationApi : [ElectricityStationApi#getElectricityStationList] {"data":{"data":{"id":null,"parentId":null,"menuName":null,"menuPath":null,"menuOrder":null,"icon":null,"remarks":null,"menuData":null,"menuButton":null,"menuId":"25"},"current":1,"size":20},"token":"5a717dca1142d685c8aa54b45d0388c8","user":{"id":1,"account":"15771720565","name":"馮謙潤","phone":"15771720565","onlineState":null,"remarks":"fdsafdsa","rolesId":1,"avatar":null,"token":"5a717dca1142d685c8aa54b45d0388c8","roles":{"id":1,"roleName":"超級管理員","remarks":"2222","menus":null},"menus":[{"id":1,"parentId":0,"menuName":"大屏展示","menuPath":"/dashboard","menuOrder":1000,"icon":"el-icon-monitor","remarks":null,"menuData":false,"menuButton":false,"child":[]},{"id":2,"parentId":0,"menuName":"數(shù)據(jù)分析","menuPath":"/dataAnalysis","menuOrder":2000,"icon":"el-icon-data-line","remarks":null,"menuData":false,"menuButton":false,"child":[]},{"id":3,"parentId":0,"menuName":"系統(tǒng)管理","menuPath":"/setting","menuOrder":3000,"icon":"el-icon-setting","remarks":null,"menuData":false,"menuButton":false,"child":[{"id":5,"parentId":3,"menuName":"角色管理","menuPath":"/setting/roles","menuOrder":3200,"icon":null,"remarks":null,"menuData":false,"menuButton":false,"child":[]},{"id":6,"parentId":3,"menuName":"菜單管理","menuPath":"/setting/menus","menuOrder":3300,"icon":null,"remarks":null,"menuData":false,"menuButton":false,"child":[]}]},{"id":16,"parentId":0,"menuName":"電站管理","menuPath":"/electricityStation","menuOrder":4000,"icon":"el-icon-lightning","remarks":null,"menuData":false,"menuButton":false,"child":[{"id":17,"parentId":16,"menuName":"電站信息","menuPath":"/electricityStation/list","menuOrder":4100,"icon":null,"remarks":"列出所有電站","menuData":false,"menuButton":false,"child":[]}]}]}}
2020-06-18 09:54:06.454 DEBUG 29140 --- [nio-8888-exec-3] c.giant.cloud.api.ElectricityStationApi : [ElectricityStationApi#getElectricityStationList] ---> END HTTP (1756-byte body)
2020-06-18 09:54:06.483 DEBUG 29140 --- [nio-8888-exec-3] c.giant.cloud.api.ElectricityStationApi : [ElectricityStationApi#getElectricityStationList] <--- HTTP/1.1 200 (29ms)
2020-06-18 09:54:06.484 DEBUG 29140 --- [nio-8888-exec-3] c.giant.cloud.api.ElectricityStationApi : [ElectricityStationApi#getElectricityStationList] connection: keep-alive
2020-06-18 09:54:06.484 DEBUG 29140 --- [nio-8888-exec-3] c.giant.cloud.api.ElectricityStationApi : [ElectricityStationApi#getElectricityStationList] content-type: application/json
2020-06-18 09:54:06.484 DEBUG 29140 --- [nio-8888-exec-3] c.giant.cloud.api.ElectricityStationApi : [ElectricityStationApi#getElectricityStationList] date: Thu, 18 Jun 2020 01:54:05 GMT
2020-06-18 09:54:06.484 DEBUG 29140 --- [nio-8888-exec-3] c.giant.cloud.api.ElectricityStationApi : [ElectricityStationApi#getElectricityStationList] keep-alive: timeout=60
2020-06-18 09:54:06.484 DEBUG 29140 --- [nio-8888-exec-3] c.giant.cloud.api.ElectricityStationApi : [ElectricityStationApi#getElectricityStationList] transfer-encoding: chunked
2020-06-18 09:54:06.484 DEBUG 29140 --- [nio-8888-exec-3] c.giant.cloud.api.ElectricityStationApi : [ElectricityStationApi#getElectricityStationList]
2020-06-18 09:54:06.484 DEBUG 29140 --- [nio-8888-exec-3] c.giant.cloud.api.ElectricityStationApi : [ElectricityStationApi#getElectricityStationList] {"code":200,"msg":null,"data":{"current":1,"size":20,"total":1,"records":[{"createTime":"2020-06-15T03:46:17.000+00:00","updateTime":"2020-06-15T03:46:17.000+00:00","deleteFlag":false,"id":1,"menuId":25,"name":"平頂山新能源項目1期","buildingDegree":30,"cityName":"平頂山","cityId":"410400","lng":"113.308","lat":"33.7352","remarks":"測試數(shù)據(jù)"}]}}
2020-06-18 09:54:06.484 DEBUG 29140 --- [nio-8888-exec-3] c.giant.cloud.api.ElectricityStationApi : [ElectricityStationApi#getElectricityStationList] <--- END HTTP (362-byte body)
我就試到這里了耽装,正常來說 FULL 已經(jīng)足夠了。
六期揪、Feign的全局異常處理
@Configuration
public class FeignClientErrorDecoder implements ErrorDecoder {
private static final Log log = LogFactory.getLog(FeignClientErrorDecoder.class);
@Override
public Exception decode(String methodKey, Response response) {
try {
String body = IoUtil.read(response.body().asInputStream(), "utf-8");
Map<String,String> errMap = JSONObject.parseObject(body, HashMap.class);
return new InternalException(errMap.get("message"));
}catch(Exception e){
return new InternalException(e.getMessage());
}
}
}