Spring Cloud微服務系列文,服務調用框架Feign 架構師入門:搭建基本的Eureka架構(從項目裏抽取)

    以前博文的案例中,咱們是經過RestTemplate來調用服務,而Feign框架則在此基礎上作了一層封裝,好比,能夠經過註解等方式來綁定參數,或者以聲明的方式來指定請求返回類型是JSON。    這種「再次封裝」能給咱們帶來的便利有兩點,第一,開發者無需像使用RestTemplate那樣過多地關注HTTP調用細節,第二,在大多數場景裏,某種類型的調用請求會被在多個地方被屢次使用,經過Feign能方便地實現這類「重用」。html

 1 經過案例快速上手Feign

    在FeignDemo-Server項目裏,搭建基於Eureka的服務器,該項目的端口號是8888,主機名是localhost,啓動後,能經過http://localhost:8888/eureka/查看註冊到Eureka服務器中的諸多服務提供者或調用者的信息。java

     在FeignDemo-ServiceProvider項目的控制器類裏,咱們提供了一個sayHello方法,本項目提供服務的端口號是1111,對外提供的application name(服務名)是sayHelloServiceProvider,是向FeignDemo-Server服務器(也是Eureka服務器)的http://localhost:8888/eureka/註冊服務。而提供sayHello的方法以下所示,從中,咱們能看到對應的RequestMapping值。web

    1          @RequestMapping(value = "/hello/{username}", method = RequestMethod.GET   )spring

    2          public String sayHello(@PathVariable("username") String username){瀏覽器

    3          return "hello " + username;緩存

    4      }服務器

    上述Eureka服務器和客戶端的代碼,是複用架構師入門:搭建基本的Eureka架構(從項目裏抽取)這篇文章裏的代碼。網絡

    這裏咱們將在FeignDemo-ServiceCaller項目裏,演示經過Feign調用服務的方式。架構

    第一步,在pom.xml裏,引入Eureka、Ribbon和Feign的相關包,關鍵代碼以下。其中,是經過第1行到第9行的代碼引入Eureka包,經過第10行到第13行的代碼引入Ribbon包,經過第14行到第17行的代碼引入Feign包。   app

1    <dependency>
2        <groupId>org.springframework.boot</groupId>
3        <artifactId>spring-boot-starter-web</artifactId>
4        <version>1.5.4.RELEASE</version>
5    </dependency>   
6        <dependency>
7            <groupId>org.springframework.cloud</groupId>
8            <artifactId>spring-cloud-starter-eureka</artifactId>
9        </dependency>
10     <dependency>
11           <groupId>org.springframework.cloud</groupId> 
12           <artifactId>spring-cloud-starter-ribbon</artifactId> 
13    </dependency>  
14     <dependency>
15            <groupId>org.springframework.cloud</groupId>
16            <artifactId>spring-cloud-starter-feign</artifactId>
17    </dependency>

    第二步,在application.yml裏,經過第3行的代碼,定義本項目的名字叫callHelloByFeign,經過第5行的代碼,指定本項目是工做在8080端口。同時經過第9行的代碼,指定本項目是向http://localhost:8888/eureka/ (也就是FeignDemo-Server)這個Eureka服務器註冊。    

1    spring:
2      application:
3        name: callHelloByFeign
4    server:
5      port: 8080
6    eureka: 
7      client:
8        serviceUrl:
9          defaultZone: http://localhost:8888/eureka/

    第三步,在啓動類裏,經過第1行的代碼,添加支持Feign的註釋,關鍵代碼以下。這樣,在啓動這個Eureka客戶端時,就能夠引入Feign支持。    

1    @EnableFeignClients
2    @EnableDiscoveryClient
3    @SpringBootApplication
4    public class ServiceCallerApp 
5    {
6        public static void main( String[] args )
7        {      SpringApplication.run(ServiceCallerApp.class, args);  }
8    }

    第四步,經過Feign封裝客戶端調用的細節,外部模塊是經過Feign來調用客戶端的,這部分的代碼是在Controller.java裏。     

1    省略必要的package和import的代碼
2    //經過註解指定待調用的服務名
3    @FeignClient("sayHelloServiceProvider")
4    //在這個接口裏,經過Feign封裝客戶端的調用細節 
5    interface FeignClientTool
6    {
7            @RequestMapping(method = RequestMethod.GET, value =   "/hello/{name}")
8          String sayHelloInClient(@PathVariable("name") String name);
9    }
10    //Controller是控制器類
11    @RestController
12    public class Controller {        
13          @Autowired
14         private FeignClientTool tool;    
15    //在callHello方法是,是經過Feign來調用服務
16        @RequestMapping(value = "/callHello", method = RequestMethod.GET)
17          public String callHello(){ 
18            return tool.sayHelloInClient("Peter");
19        }        
20    }

    在Controller.java這個文件,其實定義了一個接口和一個類。在第5行的FeignClientTool接口裏,咱們封裝了Feign的調用業務,具體來講,是經過第3行的FeignClient註解,指定了該接口會調用「sayHelloServiceProvider「服務提供者的服務,而經過第8行的,則指定了調用該服務提供者中sayHelloInClient的方法。

    而在第12行的Controller類裏,先是在第14行裏,經過Autowired註解,引入了FeignClientTool類型的tool類,隨後在第17行的callHello方法裏,是經過tool類的sayHelloInClient方法,調用了服務提供者的相關方法。

    也就是說,在callHello方法裏,咱們並無再經過RestTemplate,以輸入地址和服務名的方式調用服務,而是經過封裝在FeignClientTool(Feign接口)裏的方法調用服務。

    完成上述代碼後,咱們能夠經過以下的步驟查看運行效果。

    第一步,啓動FeignDemo-Server項目,隨後輸入http://localhost:8888/,能看到註冊到Eureka服務器裏的諸多服務。

    第二步,啓動FeignDemo-ServiceProvider項目,隨後輸入http://localhost:1111/hello/Peter,能調用其中的服務,此時,能在瀏覽裏看到「hello Peter」的輸出。

    第三步,啓動FeignDemo-ServiceCaller項目,隨後輸入http://localhost:8080/callHello,一樣能在瀏覽裏看到「hello Peter」的輸出。請注意,這裏的調用是經過Feign完成的。    

2 經過比較其它調用方式,瞭解Feign的封裝性    

    在以前的代碼裏,咱們是經過以下形式,經過RestTemplate對象來調用服務。

          1      RestTemplate template = getRestTemplate();

          2             String retVal = template.getForEntity("http://sayHello/hello/Eureka", String.class).getBody();

    在第2行的調用中,咱們須要指定url以及返回類型等信息。

    以前咱們還見過基於RestClient對象的調用方式,關鍵代碼以下。

          1      RestClient client = (RestClient)ClientFactory.getNamedClient("RibbonDemo"); 

          2       HttpRequest request = HttpRequest.newBuilder().uri(new URI("/hello")).build(); 

          3      HttpResponse response = client.executeWithLoadBalancer(request); 

    其中是在第1行指定發起調用的RestClient類型的對象,在第2行裏指定待調用的目標地址,隨後在第3行發起調用。

    這兩種調用方式有着以下的共同點:調用時,須要詳細地知道各類調用參數,好比服務提供者的url,若是有須要經過Ribbon實現負載均衡等機制,也須要在調用時一併指定。

    但事實上,這些調用方式的底層細節,應該向服務使用者屏蔽,好比在調用時,無需關注目標url等信息。這就比如某位老闆要祕書去訂飛機票,做爲服務使用者的老闆只應當關心調用的結果,好比買到的飛機票是幾點開的,該去哪一個航站樓登機,至於調用服務的底層細節,好比該到哪一個訂票網站去買,服務使用者無需知道。

    說得更專業些,這叫「解耦合」,即下降服務調動者和服務提供者之間的耦合度,這樣的好處是,一旦服務提供者改變了實現細節(沒改變服務調用接口),那麼服務調用者部分的代碼無需改動。

    咱們再來回顧下經過Feign調用服務的方式。

          1      private FeignClientTool tool; //定義Feign類

          2      tool.sayHelloInClient("Peter"); //直接調用

    第2行是調用服務,但其中,咱們看不到任何服務提供者的細節,由於這些都在第1行引用的FeignClientTool類裏封裝掉了。也就是說,經過基於Feign的調用方式,開發者能真正地作到「面向業務」,而無需過多地關注發起調用的細節。    

3 經過註解輸出調用日誌

    在開發和調試階段,咱們但願能看到日誌,從而能定位和排查問題。這裏,咱們將講述在Feign裏輸出日誌的方法,以便讓你們能在經過Feign調用服務時,看到具體的服務信息。

    這裏咱們將改寫FeignDemo-ServiceCaller項目。

    改動點1:在application.yml文件裏,增長以下的代碼,以開啓Feign客戶端的DEBUG日誌模式,請注意,這裏須要指定完成的路徑,就像第3行那樣。

          1      logging:

          2        level:

          3          com.controller.FeignClientTool: DEBUG  

    改動點2:在這個項目的啓動類ServiceCallerApp.java裏,增長定義日誌級別的代碼,在第7行的feignLoggerLevel方法裏,咱們經過第8行的代碼,指定了Feign日誌級別是FULL。    

1    //省略必要的pacakge和import代碼
2    @EnableFeignClients
3    @EnableDiscoveryClient
4    @SpringBootApplication
5    public class ServiceCallerApp{
6        @Bean //定義日誌級別是FULL
7        Level feignLoggerLevel()    { 
8            return Level.FULL; 
9        }
10        //啓動類
11        public static void main( String[] args )  { 
12           SpringApplication.run(ServiceCallerApp.class, args); 
13       }
14    }

    完成後,依次運行Eureka服務器、服務提供者和服務調用者的啓動類,隨後在瀏覽器裏輸入http://localhost:8080/callHello,即能在控制檯裏看到DEBUG級別的日誌,下面給出了部分輸出。

          1      2018-06-17 12:18:27.296 DEBUG 208 --- [rviceProvider-2] com.controller.FeignClientTool           : [FeignClientTool#sayHelloInClient] ---> GET http://sayHelloServiceProvider/hello/Peter?name=Peter HTTP/1.1

          2      2018-06-17 12:18:27.296 DEBUG 208 --- [rviceProvider-2] com.controller.FeignClientTool           : [FeignClientTool#sayHelloInClient] ---> END HTTP (0-byte body)

    從第1行的輸出裏,咱們能看到以GET的方式向FeignClientTool類的sayHelloInClient方法發起調用,從第2行的輸出裏,能看到調用結束。

    在上文裏,咱們用的是FULL級別的日誌,此外,還有NONE、BASIC和HEADERS這三種,在下表裏,咱們將詳細講述各級別日誌的輸出狀況。

日誌輸出級別

描述

NONE

不輸出任何日誌

BASIC

只輸出請求的方法,請求的URL和相應的狀態碼,以及執行的時間

HEADERS

除了會輸出BASIC級別的日誌外,還會記錄請求和響應的頭信息

FULL

輸出全部的和請求和響應相關的日誌信息

     通常狀況下,在調試階段,能夠把日誌級別設置成FULL,等上線後,能夠把級別調整爲BASIC,由於在生產環境上,過多的日誌反而會下降排查和定位問題的效率。    

4 壓縮請求和返回,以提高訪問效率

    在網絡傳輸過程當中,若是咱們能下降傳輸流量,那麼便可提高處理請求的效率。尤爲地,在一些平常訪問量比較高的網絡應用中,若是能下降處理請求(Request)和發送返回信息(Response)的時間,那麼就能提高本站的吞吐量。

    在Feign裏,咱們通常能經過以下的配置,來壓縮請求和響應。

    第一,能夠經過在application.yml裏增長以下的配置,從而壓縮請求和返回信息。

          1      feign:

          2        compression:

          3          request:

          4            enabled: true

          5      feign:

          6         compression:

          7           response:

          8            enabled: true

    其中,前4行是壓縮請求,然後4行是壓縮返回。

    第二,能夠經過以下的代碼,設置哪類請求(或返回)將被壓縮,這裏咱們在第4行裏,指定了兩類格式的請求將被壓縮。

          1      feign:    

          2        compression:

          3          request:

          4            mime-types: text/xml,application/xml

    第三,能夠經過以下的代碼,指定待壓縮請求的最小值,這裏是2048,也就是說,超過這個值的request纔會被壓縮。

          1      feign:    

          2        compression:

          3          request:

          4            min-request-size:2048

    本文謝絕轉載。其它和Spring Cloud相關的博文以下:    

 
相關文章
相關標籤/搜索