欧美人与性动交α欧美精品_色综合久久天天综合_亚洲s黄在线_youjizz国产在线观看_男女猛烈拍拍拍无挡视频免费

首頁 > 資訊 > > 正文

服務(wù)調(diào)用/通信-OpenFeign最佳實(shí)踐

2023-04-26 18:12:41        來源:   程序猿阿嘴

我正在參加「掘金·啟航計劃」

Spring Cloud OpenFeign 它是 Spring 官方推出的一種聲明式服務(wù)調(diào)用與負(fù)載均衡組件。它底層基于 Netflix Feign,Netflix Feign 是 Netflix 設(shè)計的開源的聲明式 WebService 客戶端,用于簡化服務(wù)間通信。


(資料圖片僅供參考)

Spring Cloud openfeign 對 Feign 進(jìn)行了增強(qiáng),使其支持 Spring MVC 注解,另外還整合了 Ribbon 和 Nacos,從而使得 Feign 的使用更加方便。

docs.spring.io/spring-clou…

原理

用到了 動態(tài)代理

對比 Dubbo

OpenFeign 好像不能直接調(diào)用 service 層,一般的寫法是服務(wù)提供方必須寫 controller 接口,而 dubbo 是不用寫 controller 接口的。如果不能直接調(diào)用 service 層,必須寫 controller 層,那么這應(yīng)該是一個缺點(diǎn),因?yàn)槊看味碱~外要寫一個 controller 方法。

而且在服務(wù)消費(fèi)者方,還要額外寫個有 @FeignClient 注解的遠(yuǎn)程調(diào)用 service 接口??瓷先?Spring Cloud 的 OpenFeign 比 dubbo 麻煩不少。

引入依賴

使用 OpenFeign 組件需要引入客戶端依賴

org.springframework.cloudspring-cloud-starter-openfeign復(fù)制代碼

使用案例

在啟動類上加上 @EnableFeignClients 注解

/** * 被調(diào)用方 */@RestControllerpublic class WarehouseController {    /**     * 查詢對應(yīng) skuId 的庫存狀況     * @param skuId skuId     * @return Stock 庫存對象     */    @GetMapping(\"/stock\")    public Stock getStock(Long skuId){    // ...省略    }}/** * 調(diào)用方 */@FeignClient(\"warehouse-service\")public interface WarehouseServiceFeignClient {        @GetMapping(\"/stock\")    public Stock getStock(@RequestParam(\"skuId\") Long skuId);}復(fù)制代碼

@FeignClient 注解說明當(dāng)前接口為 OpenFeign 通信客戶端,參數(shù)值 warehouse-service 為服務(wù)提供者 ID(注意,OpenFeign服務(wù)名稱不支持下劃線_,這是一個坑),這一項必須與 Nacos 注冊 ID 保持一致。

在 OpenFeign 發(fā)送請求前會自動在 Nacos 查詢 warehouse-service 所有可用實(shí)例信息,再通過內(nèi)置的 Ribbon 負(fù)載均衡選擇一個實(shí)例發(fā)起 RESTful 請求,進(jìn)而保證通信高可用。

tips: 這里的返回值雖然寫的都是同一個類型,但他們可不一定是同一個類,本質(zhì)上是以 Json 交互的,只要屬性對的上即可。

@FeignClient 注解屬性詳解

contextId: 如果配置了contextId,該值將會作為beanName。

fallback: 定義容錯的處理類,當(dāng)調(diào)用遠(yuǎn)程接口失敗或超時時,會調(diào)用對應(yīng)接口的容錯邏輯,fallback指定的類必須實(shí)現(xiàn)@FeignClient標(biāo)記的接口

fallbackFactory: 工廠類,用于生成fallback類示例,通過這個屬性我們可以實(shí)現(xiàn)每個接口通用的容錯邏輯,減少重復(fù)的代碼

url: url一般用于調(diào)試,可以手動指定@FeignClient調(diào)用的地址

Spring Cloud CircuitBreaker Fallbacks

當(dāng)斷路器打開或出現(xiàn)錯誤時執(zhí)行的默認(rèn)邏輯,可以通過 fallback 來配置

注意:您還需要將其聲明為 Spring bean 。

@FeignClient(name = \"test\", url = \"http://localhost:${server.port}/\", fallback = Fallback.class)protected interface TestClient {    @RequestMapping(method = RequestMethod.GET, value = \"/hello\")    Hello getHello();    @RequestMapping(method = RequestMethod.GET, value = \"/hellonotfound\")    String getException();}@Componentstatic class Fallback implements TestClient {    @Override    public Hello getHello() {        throw new NoFallbackAvailableException(\"Boom!\", new RuntimeException());    }    @Override    public String getException() {        return \"Fixed response\";    }}復(fù)制代碼

如果需要訪問導(dǎo)致回退觸發(fā)的原因,可以使用 fallbackFactory 屬性

@FeignClient(name = \"testClientWithFactory\", url = \"http://localhost:${server.port}/\",        fallbackFactory = TestFallbackFactory.class)protected interface TestClientWithFactory {    @RequestMapping(method = RequestMethod.GET, value = \"/hello\")    Hello getHello();    @RequestMapping(method = RequestMethod.GET, value = \"/hellonotfound\")    String getException();}@Componentstatic class TestFallbackFactory implements FallbackFactory{    @Override    public FallbackWithFactory create(Throwable cause) {        return new FallbackWithFactory();    }}static class FallbackWithFactory implements TestClientWithFactory {    @Override    public Hello getHello() {        throw new NoFallbackAvailableException(\"Boom!\", new RuntimeException());    }    @Override    public String getException() {        return \"Fixed response\";    }}復(fù)制代碼

開啟日志

工作中我們有些生產(chǎn)問題出現(xiàn)在微服務(wù) OpenFeign 的互相調(diào)用中,然而 OpenFeign 的調(diào)用默認(rèn)是不打日志的。

我們可以通過代碼配置或者配置文件配置

//全局配置@Configurationpublic class FeignLoggerConfiguration {    @Bean    Logger.Level feignLoggerLevel() {        return Logger.Level.FULL;    }}//局部配置//不需要加Configuration注解public class FeignConfig {    @Bean    public Logger.Level feignLogLevel(){        //設(shè)置feign客戶端的日志打印級別為FULL        return Logger.Level.FULL;    }}//configuration屬性,值為Class,配置信息對名稱為userprivilege的服務(wù)生效@Resource@FeignClient(name=\"userprivilege\",fallback = FallBack_PrivilegeService.class ,configuration = FeignConfig.class)public interface PrivilegeService {}復(fù)制代碼
feign:  client:    config:      default: # 項目全局        loggerLevel: HEADERS      order-service: #@FeignClient注解中配置的服務(wù)名        loggerLevel: FULL復(fù)制代碼

Level 有四個等級

NONE 不打日志,默認(rèn)值 BASIC 只記錄 method、url、響應(yīng)碼,執(zhí)行時間 HEADERS 只記錄請求和響應(yīng)的 header FULL 全部都記錄

上面修改了 openfeign 的日志級別是 debug,但是 springboot 默認(rèn)日志級別是 info,因?yàn)?debug

logging:    level:    com.base.service: debug # 這里是openfeign client 所在的包路徑復(fù)制代碼

上傳文件

www.baeldung.com/java-feign-…

@PostMapping(value = \"/upload-file\")public String handleFileUpload(@RequestPart(value = \"file\") MultipartFile file) {    // File upload logic}public class FeignSupportConfig {    @Bean    public Encoder multipartFormEncoder() {        return new SpringFormEncoder(new SpringEncoder(new ObjectFactory() {            @Override            public HttpMessageConverters getObject() throws BeansException {                return new HttpMessageConverters(new RestTemplate().getMessageConverters());            }        }));    }}@FeignClient(name = \"file\", url = \"http://localhost:8081\", configuration = FeignSupportConfig.class)public interface UploadClient {    @PostMapping(value = \"/upload-file\", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)    String fileUpload(@RequestPart(value = \"file\") MultipartFile file);}復(fù)制代碼

性能優(yōu)化

替換默認(rèn)通信組件

OpenFeign 默認(rèn)使用 Java 自帶的 URLConnection 對象創(chuàng)建 HTTP 請求,但接入生產(chǎn)時,如果能將底層通信組件更換為 Apache HttpClient、OKHttp 這樣的專用通信組件,基于這些組件自帶的連接池,可以更好地對 HTTP 連接對象進(jìn)行重用與管理。

io.github.openfeignfeign-okhttpio.github.openfeignfeign-httpclient復(fù)制代碼

然后在配置文件中加入如下:

feign:  okhttp:    enabled: true# 或者feign:  httpclient:    enabled: true復(fù)制代碼

經(jīng)過上面設(shè)置已經(jīng)可以使用okhttp了,因?yàn)樵? FeignAutoConfiguration 中已實(shí)現(xiàn)自動裝配

數(shù)據(jù)壓縮

在 OpenFeign 中,默認(rèn)并沒有開啟數(shù)據(jù)壓縮功能。但如果你在服務(wù)間單次傳遞數(shù)據(jù)超過 1K 字節(jié),強(qiáng)烈推薦開啟數(shù)據(jù)壓縮功能。默認(rèn) OpenFeign 使用 Gzip 方式壓縮數(shù)據(jù),對于大文本通常壓縮后尺寸只相當(dāng)于原始數(shù)據(jù)的 10%~30%,這會極大提高帶寬利用率。,在項目配置文件 application.yml 中添加以下配置:

feign:  compression:    request:      enabled: true  # 開啟請求數(shù)據(jù)的壓縮功能      mime-types: text/xml,application/xml, application/json  # 壓縮類型      min-request-size: 1024  # 最小壓縮值標(biāo)準(zhǔn),當(dāng)數(shù)據(jù)大于 1024 才會進(jìn)行壓縮    response:      enabled: true  # 開啟響應(yīng)數(shù)據(jù)壓縮功能復(fù)制代碼

Tip提醒: 如果應(yīng)用屬于計算密集型,CPU 負(fù)載長期超過 70%,因數(shù)據(jù)壓縮、解壓縮都需要 CPU 運(yùn)算,開啟數(shù)據(jù)壓縮功能反而會給 CPU 增加額外負(fù)擔(dān),導(dǎo)致系統(tǒng)性能降低,這是不可取的。 這種情況 建議不要開啟數(shù)據(jù)的壓縮功能

負(fù)載均衡

OpenFeign 使用時默認(rèn)引用 Ribbon 實(shí)現(xiàn)客戶端負(fù)載均衡,它默認(rèn)的負(fù)載均衡策略是輪詢策略。那如何設(shè)置 Ribbon 默認(rèn)的負(fù)載均衡策略呢?

只需在 application.yml 中調(diào)整微服務(wù)通信時使用的負(fù)載均衡類即可。

warehouse-service: #服務(wù)提供者的微服務(wù)ID  ribbon:    #設(shè)置對應(yīng)的負(fù)載均衡類    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule復(fù)制代碼

Tip提醒: 出于性能方面的考慮,我們可以選擇用 權(quán)重策略或區(qū)域敏感策略來替代輪詢策略 ,因?yàn)檫@樣的執(zhí)行效率最高。

一種封裝OpenFegin的實(shí)踐

在了解這種實(shí)踐前,我們需要先知道Feign對接口繼承的寫法支持

Feign 繼承支持

參考:docs.spring.io/spring-clou…

Feign通過單繼承接口支持模板api。這允許將常見操作分組到方便的基本接口中。

Feign 支持繼承和多重繼承,這樣我們可以將API暴露到接口當(dāng)中,服務(wù)提供者實(shí)現(xiàn)該接口來提供服務(wù),服務(wù)消費(fèi)者只需要引入該接口所在的API模塊即可。

但早先時候官方并不倡導(dǎo)這么做,相關(guān)思考可見:

why-is-it-such-a-bad-idea-to-share-an-interface-between-server-and-client should-i-use-a-single-interface-for-feign-and-spring-mvc
public interface UserService {    @RequestMapping(method = RequestMethod.GET, value =\"/users/{id}\")    User getUser(@PathVariable(\"id\") long id);}復(fù)制代碼
@RestControllerpublic class UserResource implements UserService {    @Override    public User getUsers() {        ...    }}復(fù)制代碼
@FeignClient(\"users\")public interface UserClient extends UserService {}復(fù)制代碼

tips: @FeignClient接口不應(yīng)該在服務(wù)器和客戶端之間共享,并且不支持在類級別上用@RequestMapping注釋@FeignClient接口。

實(shí)踐

將 Feign 的 Client 抽取為獨(dú)立模塊,并且把接口有關(guān)的 POJO、默認(rèn)的 Feign 配置都放到這個模塊中,提供給所有消費(fèi)者使用。

例如:將 UserClients、User、Feign 的默認(rèn)配置都抽取到一個 feign-api 包中,所有微服務(wù)引用該依賴包,即可直接使用。

服務(wù)提供方開發(fā)實(shí)踐

RPC 接口和實(shí)現(xiàn)各自放在獨(dú)立的模塊中,方便服務(wù)調(diào)用方重用服務(wù)接口 ,服務(wù)接口模塊只能包含最基本的模塊依賴(過多會導(dǎo)致依賴傳遞)。

服務(wù)的接口及相關(guān)模型必須放在同一模塊中,該模塊僅包含這些內(nèi)容, 服務(wù)提供方的接口中不能指定 FeignClient 注解(在消費(fèi)方指定),在方法中可以使用 @RequestMapping 等注解 。

例如:

account - account-api - account-service復(fù)制代碼

account-api 模塊中放消費(fèi)方需要用到的東西, api接口,vo,入?yún)⒌?..

public interface AccountApi {    @RequestMapping(method = RequestMethod.GET, value =\"/users/{id}\")    User getUser(@PathVariable(\"id\") long id);}復(fù)制代碼

account-service 實(shí)現(xiàn) account-api 提供的接口

@RestController@Api(tags = \"用戶接口\")public class AccountController implements AccountApi {    ...}復(fù)制代碼

服務(wù)消費(fèi)方開發(fā)實(shí)踐

引用 RPC 接口模塊,在消費(fèi)方編寫 feign 客戶端類繼承相關(guān)接口并處理熔斷,在客戶端接口上增加 FeignClient 注解即可。

@Component@FeignClient(name = \"account-service\",fallbackFactory = AccountClientFallbackFactory.class)public interface AccountClient extends AccountApi {    ...}@Componentpublic class AccountClientFallbackFactory implements FallbackFactory {    @Override    public AccountClient create(Throwable throwable) {        AccountClientFallback accountClientFallback = new AccountClientFallback();        accountClientFallback.setCause(throwable);        return accountClientFallback;    }}@Slf4jpublic class AccountClientFallback implements AccountClient {    @Setter    private Throwable cause;    @Override    public ResultData getByCode(String accountCode) {...    }}復(fù)制代碼

擴(kuò)展

Spring Cloud OpenFeign 特性完成公告

由于 Spring 現(xiàn)在提供了自己的 HTTP 接口客戶端解決方案,比如在最新的 Spring Boot 3.0 中實(shí)現(xiàn)接口調(diào)用可以有以下兩種解決方案:

RestTemplate WebClient

所以,從 Spring Cloud 2022.0.0 版本開始,Spring Cloud OpenFeign 模塊已經(jīng)視為功能完成狀態(tài)了,這意味著 Spring Cloud 團(tuán)隊將不再向該模塊添加新功能。

雖然 OpenFeign 不會再添加新功能,但還是會繼續(xù)修復(fù)錯誤和安全問題,并且也還會考慮和審查來自社區(qū)的小規(guī)模的 pull requests 請求。

HTTP Interface

Spring 6 中帶來了一個新的特性——HTTP Interface。這個新特性,可以讓開發(fā)者將 HTTP 服務(wù),定義成一個包含特定注解標(biāo)記的方法的 Java 接口,然后通過對接口方法的調(diào)用,完成 HTTP 請求??雌饋砗芟袷褂? Feign 來完成遠(yuǎn)程服務(wù)調(diào)用。

docs.spring.io/spring-fram…

原文鏈接:https://juejin.cn/post/7201316570315440184

標(biāo)簽:

熱門話題
精彩推薦
今日推薦
花木