OpenFeign是什么
隨着業務的增多,我們的單體應用越來越復雜,單機已經難以滿足性能的需求,這時候出現了分布式。分布式通訊除了RPC, REST HTTP請求是最簡單的一種方式。OpenFeign是Netflix開源的參照Retrofit, JAXRS-2.0, and WebSocket的一個http client客戶端,致力於減少http client客戶端構建的復雜性。
官方用法
github提供了一個簡單的demo,很容易理解。
interface GitHub {
@RequestLine("GET /repos/{owner}/{repo}/contributors")
List<Contributor> contributors(@Param("owner") String owner, @Param("repo") String repo);
}
static class Contributor {
String login;
int contributions;
}
public static void main(String... args) {
GitHub github = Feign.builder()
.decoder(new GsonDecoder())
.target(GitHub.class, "https://api.github.com");
// Fetch and print a list of the contributors to this library.
List<Contributor> contributors = github.contributors("OpenFeign", "feign");
for (Contributor contributor : contributors) {
System.out.println(contributor.login + " (" + contributor.contributions + ")");
}
}
簡單的說,這么用沒問題。但如果想要集成到系統中,關於Hystrix的配置還需要自己指定。為此,我單獨把配置方案提煉了一下。
項目地址: https://github.com/Ryan-Miao/springboot-starter-feign
本項目提供了一個開箱即用的spring boot feign starter, 基於默認的約定配置
來簡化和優化OpenFeign的使用流程.
How to use
引入repo
<repositories>
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</repository>
</repositories>
引入依賴
<dependency>
<groupId>com.github.Ryan-Miao</groupId>
<artifactId>springboot-starter-feign</artifactId>
<version>1.1</version>
</dependency>
在springboot 項目中添加Configuration
@Autowired
private Environment environment;
@Bean
public FeignFactory feignFactory() {
return new FeignFactory(environment, hystrixConfigurationProperties());
}
@Bean
public HystrixConfigurationProperties hystrixConfigurationProperties() {
return new HystrixConfigurationProperties();
}
然后就可以使用了。
使用和配置
約定了一些配置,大概如下
feign:
hystrixConfig:
"hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds": 8000
"hystrix.command.GithubConnector#getRepos.execution.isolation.thread.timeoutInMilliseconds": 15000
endpointConfig:
GithubConnector:
default:
url: https://api.github.com
readTimeoutMillis: 8000
connectTimeoutMillis: 5000
getRepos:
url: https://api.github.com
readTimeoutMillis: 15000
connectTimeoutMillis: 10000
- feign是配置的第一個索引
- hystrixConfig是hystrix的配置,更多配置見Hystrix
- endpointConfig是我們遠程請求的host和超時配置,其中,第一個節點為Connector class
的名稱,下一個是具體到某個請求的key,整個Connector class的默認配置是default
節點,如果該Connector里的某個請求的超時比較長,需要單獨設置,則會覆蓋默認節點。
另外,hystrix的超時配置commankey為[connectorClassName][#][methodName]
定義一個GithubConnector,繼承com.miao.connect.Connector
public interface GithubConnector extends Connector {
@RequestLine("GET /users/{username}")
@Headers({"Content-Type: application/json"})
GithubUser getGithubUser(@Param("username") String username);
@RequestLine("GET /users/{username}/repos")
@Headers({"Content-Type: application/json"})
Observable<String> getRepos(@Param("username") String username);
}
調用
@Autowired
private FeignFactory feignFactory;
@GetMapping("/profile/{username}")
public GithubUser getProfile(@PathVariable String username) {
//采用Jackson作為編碼和解碼類庫,url和超時配置按照default,即讀取feign.endpointConfig.GithubConnector.default
final GithubConnector connector = feignFactory.builder().getConnector(GithubConnector.class);
return connector.getGithubUser(username);
}
@GetMapping("/repos/{username}")
public String getUserRepos(@PathVariable String username) {
//用String來接收返回值, url和超時單獨指定配置,因為請求時間較長
//采用connector的method來當做獲取配置的key,即讀取feign.endpointConfig.GithubConnector.getRepos
final GithubConnector connector = feignFactory.builder()
.connectorMethod("getRepos")
.stringDecoder() //默認使用jackson作為序列化工具,這里接收string,使用StringDecoder
.getConnector(GithubConnector.class);
return connector.getRepos(username)
.onErrorReturn(e -> {
LOGGER.error("請求出錯", e);
Throwable cause = e.getCause();
if (cause instanceof FeignErrorException) {
throw (FeignErrorException) cause;
}
throw new RuntimeException("請求失敗", e);
}).toBlocking().first();
}
具體見使用示例example
相比原生有什么區別?
最大的區別是hystrix配置的內容,原生並沒有提供hystrix相關配置,需要自己額外
准備。這里集成hystrix的約定,只要按照hystrix官方參數配置即可。
然后是緩存,在使用原生OpenFeign的過程中發現每次請求都要創建一個Connector,
而且Connector的創建又依賴一大堆別的class。對於我們遠程調用比較頻繁的應用來說,
增大了垃圾收集器的開銷,我們其實不想回收。所以對Connector做了緩存。
其他用法同OpenFeign。