<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          SpringCloud下基于OpenFeign的服務(wù)調(diào)用實(shí)踐

          共 6484字,需瀏覽 13分鐘

           ·

          2021-11-09 06:47

          Feign是一個(gè)聲明式的Web Service客戶端,而OpenFeign則是Spring Cloud在Feign的基礎(chǔ)上增強(qiáng)了對Spring MVC注解的支持。其提供了比RestTemplate更加優(yōu)雅、便捷的服務(wù)調(diào)用方式

          abstract.png

          服務(wù)提供者

          服務(wù)提供者payment的部分實(shí)現(xiàn)如下,可以看到其暴露了兩個(gè)接口 pay/hello1、pay/hello2 用于給消費(fèi)者調(diào)用

          @RestController
          @RequestMapping("pay")
          @Slf4j
          public?class?PaymentController?{

          ????@Value("${server.port}")
          ????private?String?serverPort;

          ????@GetMapping("/hello1")
          ????public?String?hello1(@RequestParam?String?name)?{
          ????????String?msg?=?"[Payment?Service-"+?serverPort?+"]:?"?+?name;
          ????????return?msg;
          ????}

          ????@PostMapping("/hello2")
          ????public?Person?hello2(@RequestBody?Person?person)?{
          ????????person.setServicePort(?serverPort?);
          ????????String?uuid?=?UUID.randomUUID().toString();
          ????????person.setId(?uuid?);
          ????????return?person;
          ????}

          }

          服務(wù)消費(fèi)者

          對于服務(wù)消費(fèi)者order而言,首先需要引入OpenFeign依賴

          <dependencyManagement>
          ??<dependencies>

          ????
          ????<dependency>
          ??????<groupId>org.springframework.bootgroupId>
          ??????<artifactId>spring-boot-dependenciesartifactId>
          ??????<version>2.2.2.RELEASEversion>
          ??????<type>pomtype>
          ??????<scope>importscope>
          ????dependency>

          ????
          ????<dependency>
          ??????<groupId>org.springframework.cloudgroupId>
          ??????<artifactId>spring-cloud-dependenciesartifactId>
          ??????<version>Hoxton.SR1version>
          ??????<type>pomtype>
          ??????<scope>importscope>
          ????dependency>

          ??dependencies>
          dependencyManagement>

          <dependencies>
          ??
          ??
          ??<dependency>
          ????<groupId>org.springframework.cloudgroupId>
          ????<artifactId>spring-cloud-starter-openfeignartifactId>
          ??dependency>

          dependencies>

          為了調(diào)用payment服務(wù),我們直接定義接口即可。特別地,該接口需要添加@Component注解。具體地,用@FeignClient注解的name、path屬性分別定義所調(diào)用服務(wù)的服務(wù)名、url路徑。對于接口中方法,可以通過@RequestMapping等注解定義所調(diào)用服務(wù)具體的url路徑。對于傳參,類似于Controller層參數(shù)綁定一樣,通過@RequestParam、@PathVariable、@RequestBody等注解綁定參數(shù)。不同的是,對于@RequestParam、@PathVariable而言,需要通過value屬性顯式設(shè)置參數(shù)名。示例如下

          @Component
          @FeignClient(name?=?"payment",?path?=?"pay"?)
          public?interface?PaymentService?{

          ????@GetMapping("/hello1")
          ????//?需要通過@RequestParam注解的value屬性顯式指定參數(shù)名
          ????String?method1(@RequestParam(value?=?"name")?String?name);

          ????@PostMapping("/hello2")
          ????Person?method2(@RequestBody?Person?person);

          }

          然后,我們就可以直接注入該接口paymentService來進(jìn)行服務(wù)調(diào)用,示例如下

          @RestController
          @RequestMapping("order2")
          public?class?OrderController2?{

          ????@Autowired
          ????private?PaymentService?paymentService;

          ????@GetMapping("/test1")
          ????public?String?test1(@RequestParam?String?name)?{
          ????????String?msg?=?paymentService.method1(name)?;
          ????????String?result?=?"[Order?Service?test1]:?"?+?msg;
          ????????return?result;
          ????}

          ????@GetMapping("/test2")
          ????public?String?test2(@RequestParam?String?name,?@RequestParam?Integer?age)?{
          ????????Person?person?=?Person.builder()
          ????????????.name(?name?)
          ????????????.age(?age?)
          ????????????.build();

          ????????person?=?paymentService.method2(person);
          ????????String?result?=?"[Order?Service?test2]:?"?+?person;
          ????????return?result;
          ????}

          }

          最后,需要在啟動類上添加 @EnableFeignClients 注解,如下所示

          @SpringBootApplication
          //?使用Consul作為注冊中心
          @EnableDiscoveryClient
          //?啟用Feign客戶端
          @EnableFeignClients
          public?class?OrderApplication?{
          ????public?static?void?main(String[]?args)?{
          ????????SpringApplication.run(OrderApplication.class,?args);
          ????}
          }

          測試

          至此,我們對于服務(wù)提供者payment分別在8004、8005、8006創(chuàng)建三個(gè)實(shí)例,對于服務(wù)消費(fèi)者order創(chuàng)建一個(gè)運(yùn)行在82端口的實(shí)例。并通過Consul作為注冊中心。測試結(jié)果如下,符合預(yù)期。且進(jìn)一步說明OpenFeign默認(rèn)支持Ribbon,實(shí)現(xiàn)了負(fù)載均衡

          figure 1.jpeg

          超時(shí)配置

          OpenFeign調(diào)用服務(wù)時(shí),默認(rèn)超時(shí)配置為1秒。故可通過 feign.client.config..connectTimeoutfeign.client.config..readTimeout 配置項(xiàng)針對各OpenFeign客戶端進(jìn)行配置。其中feignName即為@FeignClient注解所定義的OpenFeign客戶端名。特別地,如果feignName為default表示其是對所有客戶端的配置

          #?配置名為payment的OpenFegin客戶端超時(shí)參數(shù)
          feign:
          ??client:
          ????config:
          ??????payment:
          ????????#?建立連接超時(shí)閾值,?Unit:?ms
          ????????connectTimeout:?10000
          ????????#?讀取資源超時(shí)閾值,?Unit:?ms
          ????????readTimeout:?10000

          日志配置

          OpenFeign特別提供了日志功能,實(shí)現(xiàn)了對服務(wù)接口調(diào)用的監(jiān)控。具體有下述四種日志級別

          • NONE:默認(rèn)的,不顯示任何日志
          • BASIC:顯示請求方法、URL、狀態(tài)碼及執(zhí)行時(shí)間
          • HEADERS:除了BASIC中定義的信息之外,還會顯示請求頭、響應(yīng)頭
          • FULL:除了HEADERS中定義的信息之外,還會顯示請求體、響應(yīng)體及元數(shù)據(jù)

          這里,我們利用Java配置類定義OpenFeign的日志級別

          package?com.aaron.SpringCloud1.order.config;

          import?feign.Logger;
          import?org.springframework.context.annotation.Bean;
          import?org.springframework.context.annotation.Configuration;

          @Configuration
          public?class?OpenFeignLogConfig?{

          ????/**
          ?????*?配置OpenFeign日志級別
          ?????*?@return
          ?????*/

          ????@Bean
          ????public?Logger.Level?openFeignLogLevel()?{
          ????????return?Logger.Level.FULL;
          ????}

          }

          然后,將我們期望監(jiān)控的OpenFeign接口的日志級別設(shè)為DEBUG即可,如下所示

          logging:
          ??level:
          ????#?將PaymentService接口的日志級別設(shè)為DEBUG
          ????com.aaron.SpringCloud1.order.service.PaymentService:?DEBUG

          測試效果,如下所示,符合預(yù)期

          figure 2.jpeg

          服務(wù)降級

          OpenFeign不僅支持Ribbon實(shí)現(xiàn)負(fù)載均衡,與此同時(shí)其還依賴了Hystrix以支持服務(wù)降級。故在服務(wù)消費(fèi)者order中實(shí)現(xiàn)PaymentService接口,以提供該接口的降級類。實(shí)現(xiàn)相應(yīng)方法的降級邏輯

          @Service
          public?class?PaymentFallBackService?implements?PaymentService?{

          ????@Override
          ????public?String?method1(String?name)?{
          ????????return?"invalid";
          ????}

          ????@Override
          ????public?Person?method2(Person?person)?{
          ????????person.setId(?null?);
          ????????person.setServicePort("-1");
          ????????return?person;
          ????}

          }

          然后在PaymentService接口上,通過@FeignClient注解的fallback屬性指定其相應(yīng)的降級類

          @Component
          @FeignClient(name?=?"payment",?path?=?"pay",?fallback?=?PaymentFallBackService.class)
          public?interface?PaymentService?
          {

          ????@GetMapping("/hello1")
          ????String?method1(@RequestParam(value?=?"name")?String?name);

          ????@PostMapping("/hello2")
          ????Person?method2(@RequestBody?Person?person);

          }

          對于order服務(wù)的配置文件,做相應(yīng)調(diào)整。首先調(diào)整OpenFeign中payment服務(wù)的超時(shí)配置(connectTimeout、readTimeout)為10s,然后將 feign.hystrix.enabled 設(shè)為true,使能OpenFeign的Hystrix功能。最后設(shè)置Hystrix的相關(guān)配置。具體地,我們配置全局默認(rèn)的超時(shí)時(shí)間為3s。當(dāng)然我們也可以針對某個(gè)方法設(shè)置單獨(dú)的超時(shí)配置以覆蓋全局默認(rèn),其中配置項(xiàng)的名稱規(guī)則為 接口名#方法名(參數(shù)類型) 。例如這里設(shè)置PaymentService接口method2方法的超時(shí)時(shí)間為5s,使用的配置項(xiàng)名稱為PaymentService#method2(Person)

          feign:
          ??client:
          ????config:
          ??????payment:
          ????????#?建立連接超時(shí)閾值,?Unit:?ms
          ????????connectTimeout:?10000
          ????????#?讀取資源超時(shí)閾值,?Unit:?ms
          ????????readTimeout:?10000
          ??#?啟用OpenFeign的Hystrix功能
          ??hystrix:
          ??????enabled:?true

          hystrix:
          ??command:
          ????#?配置全局默認(rèn)的超時(shí)時(shí)間??
          ????default:
          ??????execution:
          ????????isolation:
          ??????????thread:
          ????????????timeoutInMilliseconds:?3000
          ????#?配置PaymentService接口method2方法的超時(shí)時(shí)間
          ????PaymentService#method2(Person):
          ??????execution:
          ????????isolation:
          ??????????thread:
          ????????????timeoutInMilliseconds:?6000

          現(xiàn)在我們通過調(diào)用order服務(wù)接口來進(jìn)行驗(yàn)證,可以看到正常情況下,通過OpenFeign調(diào)用的服務(wù)均未發(fā)生降級

          figure 3.png

          現(xiàn)在我們對payment服務(wù)進(jìn)行改造,通過Thread.sleep來模擬業(yè)務(wù)耗時(shí),如下所示

          @RestController
          @RequestMapping("pay")
          public?class?PaymentController?{

          ????@Value("${server.port}")
          ????private?String?serverPort;

          ????@GetMapping("/hello1")
          ????public?String?hello1(@RequestParam?String?name)?{
          ????????String?msg?=?"[Payment?Service-"+?serverPort?+"]:?"?+?name;

          ????????//?模擬業(yè)務(wù)耗時(shí)
          ????????try{?Thread.sleep(4000);?}?catch?(Exception?e)?{}
          ????????
          ????????return?msg;
          ????}

          ????@PostMapping("/hello2")
          ????public?Person?hello2(@RequestBody?Person?person)?{
          ????????person.setServicePort(?serverPort?);
          ????????String?uuid?=?UUID.randomUUID().toString();
          ????????person.setId(?uuid?);

          ????????//?模擬業(yè)務(wù)耗時(shí)
          ????????try{?Thread.sleep(8000);?}?catch?(Exception?e)?{}
          ????????
          ????????return?person;
          ????}

          }

          可以看到兩個(gè)方法均進(jìn)行降級,測試結(jié)果符合預(yù)期,如下所示

          figure 4.jpeg

          參考文獻(xiàn)

          1. Spring微服務(wù)實(shí)戰(zhàn) John Carnell著
          瀏覽 37
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  人妻巨大乳HD无码 | www.骚 | 日本午夜精品 | 国产特级毛片AAAAAA | 正在播放国产AV |