SpringCloud學習:Eureka、Feign(含示例代碼)

一、Spring Cloud Netflix簡介
SpringCloud是一個基於SpringBoot實現的雲應用開發工具,它爲基於JVM的雲應用開發中的配置故那裏、服務發現、斷路器、智能路由、微代理、控制總線、全局鎖、決策競選、分佈式會話和集羣狀態管理等操作提供了簡單的開發方式。
SpringCloud下包含了多個工程,其中的Spring Cloud Netflix提供了一系列搭建微服務基礎架構的功能組件。
Netflix的部分組件及功能特性如下:
Eureka(服務註冊與發現框架):一個基於REST風格的服務組件,用於定位服務,以實現雲端的負載均衡和中間層服務器的故障轉移
Hystrix(服務容錯組件):容錯管理工具,旨在通過控制服務和第三方庫的節點,從而對延遲和故障提供強大的容村能力
Zuul(服務網關):邊緣服務工具,提供動態路由、監控、貪心、安全等邊緣服務
Ribbon(客戶端負載均衡器):提供客戶端負載均衡算法,將Netflix的中間層服務連接起來
Feign(聲明式HTTP客戶端):可以創建聲明式、模板化的HTTP客戶端,進行微服務調用

二、Eureka(服務註冊與發現框架)

1、服務註冊與發現
在進行普通架構的應用開發時,如果服務端提供了一個REST API或者Thrift API的服務,客戶端爲了能完成一次服務請求,需要知道服務實例的網絡位置(IP:Port)。傳統架構的應用都是運行在物理硬件之上,服務實例的網絡位置時相對固定的。
但是在微服務架構之下,一個微服務可能會在某一時刻進行銷燬重建,或是伸縮漂移,這樣一來服務實例的網絡位置就變得不可預知。爲了解決這一問題,我們需要在微服務架構中引入了服務註冊與發現功能。
服務發現有如下兩種模式:
a、客戶端服務發現(Client-Side Discovery)

客戶端負責決定可用的服務實例的網絡地址,以及圍繞他們的負載均衡。客戶端向服務註冊表發送一個請求,服務註冊表是一個可用服務實例的數據庫。客戶端使用一個負載均衡算法,去選擇一個可用的服務實例,來響應這個請求。
一個服務實例被啓動,他的網絡地址會被寫到註冊表上,當服務實例終止,會從註冊表中刪除。這個服務實例的註冊表通過心跳機制動態刷新。

b、服務端服務發現(Server-Side Discovery)

客戶端通過負載均衡器向某個服務提出請求,負載均衡器向服務註冊表發出請求,將每個請求轉發往可用的服務實例。和客戶端發現一樣,服務實例啓動時在服務註冊表中註冊,當服務實例銷燬,將會從服務註冊表中進行刪除。
客戶端無需關注發現的細節,只需要簡單的向負載均衡器發送請求,實際上減少了編程語言框架需要完成的服務發現邏輯。
缺點是,除非部署環境能夠提供負載均衡,否則負載均衡器是另外一個需要配置管理的高可用系統功能。

2、Eureka介紹
Eureka是一種基於REST的服務,主要用於AWS雲中的定位服務,以實現中間層服務器的負載均衡和故障轉移。Eureka提供了基於Java的客戶端組件,使得與服務的交互更容易。客戶端還有一個內置的負載均衡器,用於執行基本的輪訓負載均衡。
Eureka架構體系圖如下:

Eureka Server實例作爲服務註冊中心的角色,負責接受來自Eureka Client的服務註冊,並加以保存。
Eureka Client內嵌於一個微服務中,會將當前實例作爲服務實例註冊到服務註冊中心(Eureka Server),註冊內容包括IP、Port和服務實例名稱。消費者同樣內嵌了Eureka Client,在進行服務調用的時候,可以通過Eureka提供的DiscoveryClient和服務實例的名稱,從服務註冊中心(Eureka Server)獲取服務實例列表,然後得到服務實例的IP和Port,以完成服務調用。

3、示例代碼
a、Eureka Server(服務註冊中心)
1)在IDE中創建一個Maven項目,然後在該項目的pom.xml文件中,添加以下依賴。
<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.1.RELEASE</version>
    </parent> <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <java.version>1.8</java.version>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build> <dependencies>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka-server</artifactId>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies> <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Camden.SR5</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
2)在src/main/java包下創建EurekaRegistryDemo類,並使用@EnableEurekaServer和@SpringBootApplication註解
@EnableEurekaServer
@SpringBootApplication
public class EurekaRegistryDemo 
{
    public static void main( String[] args )
    {
        SpringApplication.run(EurekaRegistryDemo.class, args);
    }
}
3)在src/main/resources包下創建application.yml配置文件
server:
  port: 8080 #當前應用端口
spring:
  application:
    name: eureka-registry #應用名稱
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8080/eureka/ #Eureka Server地址
    register-with-eureka:
      false #因爲自己是註冊中心,所以不註冊自己
    fetch-registry:
      false
  instance:
    metadataMap:
      instanceId: ${spring.application.name}:${spring.application.instance_id:${random.value}}
4)運行EurekaRegistryDemo.java,將會啓動服務註冊中心,訪問地址爲:localhost:8080

b、Eureka Client(服務提供者)
1)創建一個maven項目作爲服務提供者,提供一個REST服務,並且通過Eureka Client,把服務實例註冊到註冊中心
項目pom.xml文件和上面Eureka Server相同。
2)在src/main/java包下創建以下java類
應用啓動類:
@SpringBootApplication
@EnableEurekaClient
@EnableAutoConfiguration
public class EurekaClientDemo {

 public static void main(String[] args) {
  new SpringApplicationBuilder(EurekaClientDemo.class).web(true).run(args);
 }
}
REST服務接口:
public interface TestApi {
 @RequestMapping(value="/testhello/{name}", method=RequestMethod.GET)
 public String testHello(@PathVariable("name") String name);
}
REST服務實現類:
@RestController
public class TestControl implements TestApi {

 public String testHello(@PathVariable("name")String name) {
  return "Hello world,"+name;
 }

}
3)在src/main/resources包下創建配置文件application.properties
這裏的配置文件使用了另外一種文件格式,如果使用Eureka Server相同的文件格式也是可以的。
server.port=9090
spring.application.name=eureka.client
eureka.client.serviceUrl.defaultZone=http://localhost:8080/eureka/
eureka.instance.appname=eureka.client.01
4)啓動 EurekaClientDemo類,刷新註冊中心頁面,將會看到服務提供者實例已經註冊到註冊中心,並且可以直接在瀏覽器訪問該實例暴露出來的REST服務

三、Feign(服務消費者)
Feign可以創建聲明式、模板化的HTTP客戶端,進行微服務調用。接下來我們將會使用Feign和Eureka Client編寫一個服務消費者,從Eureka Server中查詢到服務提供實例的調用地址,並完成服務調用。
1、創建maven項目,pom.xml文件中的依賴配置如下:
<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.1.RELEASE</version>
    </parent> <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <java.version>1.8</java.version>
    </properties> <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build> <dependencies>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-feign</artifactId>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka</artifactId>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency> <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies> <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Camden.SR5</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
2、創建應用程序啓動類FeginApplication,並且添加@SpringBootApplication和@EnableDiscoveryClient註解
@SpringBootApplication
@EnableDiscoveryClient

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

}
3、創建一個REST服務實現類,在實現類中使用Eureka提供的DiscoveryClient類,通過服務提供者實例的名稱從註冊中心中查詢服務提供者實例的具體地址,然後使用Feign進行服務調用。在這裏需要使用到服務提供者的REST服務接口,生成代理,進行服務調用,所以需要依賴服務提供者的服務接口。在服務提供者項目中將接口導出成jar,然後給當前項目依賴就可以。
@RestController
public class TestService {

    private TestApi computeClient;
    
    private static final String SERVER_NAME = "eureka.client";

 @Autowired
 private DiscoveryClient discoveryClient;
 
 @RequestMapping(value = "/gethello/{name}", method = RequestMethod.GET)
    public String getHello(@PathVariable("name") String name) {
  
  Builder feignBuilder= Feign.builder().decoder(new ResponseEntityDecoder(new SpringDecoder(new ObjectFactory<HttpMessageConverters>(){
   public HttpMessageConverters getObject() throws BeansException {
    return new HttpMessageConverters();
   }
  }))).client(new ApacheHttpClient()).contract(new SpringMvcContract());
  computeClient = feignBuilder.target(TestApi.class,discoveryClient.getInstances(SERVER_NAME).get(0).getUri().toString());
        return computeClient.testHello(name);
    }
}
代碼說明:
a、discoveryClient.getInstances(SERVER_NAME).get(0).getUri().toString()
通過discoveryClient,從服務註冊中心中,獲取名爲SERVER_NAME,即“eureka.client”的服務實例列表。因爲當前只有一個服務提供者,所以直接取列表中的第一個實例的地址信息。
b、Feign默認的decoder需要在被調用的服務接口上添加@RequestLine(“GET /test/{name}”)才能被正常調用。在這裏爲了能直接支持@RequestMapping註解,所以構造Feign的時候添加了devoder,沒有使用默認的
c、代碼中沒有使用默認的FeignClient進行調用,而是替換成了ApacheHttpClient

4、在src/main/resources包下,創建配置文件application.properties
server.port=7070
spring.application.name=eureka.test
eureka.client.serviceUrl.defaultZone=http://localhost:8080/eureka/
eureka.instance.appname=eureka.test.01
5、啓動應用後,可以在服務註冊中心頁面中看到服務消費者實例也註冊到了註冊中心裏,此時在瀏覽器訪問localhost:7070/gethello/aaa可以測試服務調用功能。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章