天天看點

Nacos:服務提供者和服務消費者(基于Feign和Ribbon兩種方式)

作者:船到橋頭自然沉0319

接上篇文章Docker下的Nacos:服務注冊與發現。在上篇文章中,已經給大家介紹了Nacos的注冊功能,我們通過項目yl-nacos-provider注冊了一個名稱為yl-nacos-provider的服務。在本篇文章中,我們繼續完善yl-nacos-provider這個項目,讓它作為服務提供者提供服務,同時實作一個消費者完成對服務的調用,消費者我們将采用兩種不同的方式來實作:Feign和Ribbon。先給展示基本用法,最後再總結Feign和Ribbon的異同。

依然需要說明一點,項目都是在Maven建構父子工程建構的基礎上,一步一步添加不同的功能不斷完善起來的。

一、首先是服務提供者yl-nacos-provider的改造

之前,我們已經在該項目中完成了Nacos注冊功能的實作,在這裡再給大家展示一下相應代碼片段。

  • 配置檔案application.yml
server:
  port: 9101
spring:
  application:
    name: yl-nacos-provider
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8849
        ip: localhost           
  • pom依賴
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    <version>0.2.2.RELEASE</version>
</dependency>           
  • 啟動類注解@EnableDiscoveryClient
@SpringBootApplication
@EnableDiscoveryClient
public class YlNacosProviderApplication {

    public static void main(String[] args) {
        SpringApplication.run(YlNacosProviderApplication.class, args);
    }

}
           

在本文中,為了實作服務提供者提供服務的能力,我們增加一個controller類對外提供服務,代碼如下:

@RestController
@RequestMapping("/ylnacos/provider")
public class YlNacosController {
    @RequestMapping("/hello")
    public String hello(@RequestParam("name") String name) {
        System.out.println("hello:" + name);
        return "hello," + name;
    }
}           

啟動項目,再去Nacos的服務清單查詢一下我們的服務是否注冊成功:

Nacos:服務提供者和服務消費者(基于Feign和Ribbon兩種方式)

在浏覽器裡調用一下我們的服務接口:

Nacos:服務提供者和服務消費者(基于Feign和Ribbon兩種方式)

至此,我們的服務提供者已經準備好。

二、服務消費者yl-nacos-consumer

在我們目前整體項目結構下,新增一個module項目yl-nacos-consumer,新增方法見Maven建構父子工程。

為服務消費者新增Nacos能力的支援。

server:
  port: 9102
spring:
  application:
    name: yl-nacos-consumer
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8849           
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    <version>0.2.2.RELEASE</version>
</dependency>           
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class YlNacosConsumerApplication {

    public static void main(String[] args) {
        SpringApplication.run(YlNacosConsumerApplication.class, args);
    }

}           

2.1Feign實作

Feign能夠實作像調用普通方法那樣調用我們的controller接口,實作方式如下。

為了讓服務消費者支援Feign能力,需要添加的内容如下:

  • pom新增Feign依賴
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>           
  • 啟動類新增注解@EnableFeignClients,這部分可以看啟動類注解@EnableDiscoveryClient這裡
  • Feign服務接口類的實作
@FeignClient("yl-nacos-provider:8849")
public interface INacosFeignService {
    @RequestMapping("/ylnacos/provider/hello")
    String hello(@RequestParam("name") String name);
}           

說明:寫一個接口類,注意是接口,在接口類上面添加@FeignClient("yl-nacos-provider:8849")注解,注解裡面的value值為服務提供者在Nacos注冊的服務名稱和Nacos的端口。

hello方法需要和服務提供者提供的服務接口的path以及參數完全一緻。例如我們服務提供者的服務接口在浏覽器裡的通路路徑為:localhost:9101/ylnacos/provider/hello?name=我是服務提供者接口消息,那麼在服務消費者的Feign接口類的方法的path為/ylnacos/provider/hello,參數name也必須一緻。這樣Feign在拼接調用路徑時,才能拼接出正确的通路URL。例如本例中拼接後的URL為:yl-nacos-provider:8849/ylnacos/provider/hello?name=XX。至于,怎麼把yl-nacos-provider:8849轉換成真實的URL域名(localhost:9101),這就是Feign做的事情了,想了解原理的同學,可以去看下。

完成Feign服務接口類後,再提供一個供我們調用的controller接口,把我們的Feign服務接口類注入進來,就可以像調用普通方法的方式來調用我們的服務接口了,代碼如下:

@RestController
@RequestMapping("/ylnacos/consumer")
public class YlNacosConsumerController {
    @Autowired
    INacosFeignService feignService;
    @RequestMapping("/hello")
    public String hello() {
        System.out.println("consumer hello");
        return feignService.hello("我是feign消費者");
    }
}
           

完成以上的準備工作後,啟動我們的服務消費者,然後通路我們的消費接口:

Nacos:服務提供者和服務消費者(基于Feign和Ribbon兩種方式)

成功輸出結果。

2.2Ribbon實作

支援Ribbon能力的代碼如下。

在啟動類裡初始化RestTemplate對象,該對象用來進行遠端調用。

啟動類的完整代碼如下:

@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class YlNacosConsumerApplication {

    public static void main(String[] args) {
        SpringApplication.run(YlNacosConsumerApplication.class, args);
    }

    @LoadBalanced
    @Bean
    public RestTemplate initRestTemplate(){
        return new RestTemplate();
    }
}           

在YlNacosConsumerController類新增一個接口:

@Autowired
RestTemplate restTemplate;
@RequestMapping("/ribbon/hello")
public String ribbonHello(){
    return restTemplate.getForObject("http://yl-nacos-provider:8849/ylnacos/provider/hello?name=我是Ribbon消費者", String.class);
}           

啟動服務消費者,在浏覽器裡通路該接口,如下:

Nacos:服務提供者和服務消費者(基于Feign和Ribbon兩種方式)

2.3總結

Feign是一款Java語言編寫的HttpClient綁定器,在Spring Cloud微服務中用于實作微服務之間的聲明式調用。Feign 可以定義請求到其他服務的接口,用于微服務間的調用,不用自己再寫http請求,在用戶端實作,調用此接口就像調用本地方法一樣來調用遠端服務。Feign是一個聲明式的web service用戶端,它使得編寫web service用戶端更為容易。建立接口,為接口添加注解,即可使用Feign。Feign可以使用Feign注解或者JAX-RS注解,還支援熱插拔的編碼器和解碼器。Spring Cloud為Feign添加了Spring MVC的注解支援,并整合了Ribbon和Eureka來為使用Feign時提供負載均衡。

Ribbon 作為負載均衡,在用戶端實作,服務端可以啟動兩個端口不同但servername一樣的服務,Ribbon是Netflix釋出的開源項目,主要功能是提供用戶端的軟體負載均衡算法,将Netflix的中間層服務連接配接在一起。Ribbon用戶端元件提供一系列完善的配置項如連接配接逾時,重試等。簡單的說,就是在配置檔案中列出Load Balancer後面所有的機器,Ribbon會自動的幫助你基于某種規則(如簡單輪詢,随機連接配接等)去連接配接這些機器。我們也很容易使用Ribbon實作自定義的負載均衡算法。簡單地說,Ribbon是一個用戶端負載均衡器。Ribbon工作時分為兩步:第一步先選擇 Eureka Server, 它優先選擇在同一個Zone且負載較少的Server;第二步再根據使用者指定的政策,在從Server取到的服務注冊清單中選擇一個位址。其中Ribbon提供了多種政策,例如輪詢、随機、根據響應時間權重等。

是以說,其實Feign提供的是HTTP請求,而具體請求哪個URL是由Ribbon來實作的。

下一篇:服務提供者和服務消費者在Docker的運作

繼續閱讀