SpringCloud之Eureka 原 薦

Eureka簡介

什麼是Eureka?

Eureka是一種基於rest提供服務註冊和發現的產品:

  • Eureka-Server: 用於定位服務,以實現中間層服務器的負載平衡和故障轉移。
  • Eureka-client:用於服務間的交互,內置負載均衡器,可以進行基本的循環負載均衡

爲什麼使用Eureka

  • 提供了完整的服務註冊與服務發現,並且也經受住了Netflix的考驗,通過註解或簡單配置即可
  • 與SpringCloud無縫集成,提供了一套完整的解決方案,使用非常方便

特性

Eureka 是一種客戶端服務發現模式,提供Server和Client兩個組件。Eureka Server作爲服務註冊表的角色,提供REST API管理服務實例的註冊和查詢。POST請求用於服務註冊,PUT請求用於實現心跳機制,DELETE請求服務註冊表移除實例信息,GET請求查詢服務註冊表來獲取所有的可用實例。Eureka Client是Java實現的Eureka客戶端,除了方便集成外,還提供了比較簡單的Round-Robin Balance。配合使用Netflix Ribbon ,可以實現更復雜的基於流量、資源佔用情況、請求失敗等因素的Banlance策略,爲系統提供更爲可靠的彈性保證。

eureka的server,client是相對於註冊發現服務的,並不是常見RPC請求的client,server,服務註冊在Eureka Server上,每30秒發送心跳來維持註冊狀態。客戶端90s內都沒有發心跳,Eureka Server就會認爲服務不可用並將其從服務註冊表移除。服務的註冊和更新信息會同步到Eureka集羣的其他節點。所有zone的Eureka Client每30秒查詢一次當前zone的服務註冊表獲取所有可用服務,然後採用合適的Balance策略向某一個服務實例發起請求。

Eureka是一個AP的系統,具備高可用性和分區容錯性。每個Eureka Client本地都有一份它最新獲取到的服務註冊表的緩存信息,即使所有的Eureka Server都掛掉了,依然可以根據本地緩存的服務信息正常工作。Eureka Server沒有基於quorum 機制實現,而是採用P2P的去中心化結構,這樣相比於zookeeper,集羣不需要保證至少幾臺Server存活才能正常工作,增強了可用性。但是這種結構註定了Eureka不可能有zookeeper那樣的一致性保證,同時因爲Client緩存更新不及時、Server間同步失敗等原因,都會導致Client訪問不到新註冊的服務或者訪問到過期的服務。

當Eureka Server節點間某次信息同步失敗時,同步失敗的操作會在客戶端下次心跳發起時再次同步;如果Eureka Server和Eureka Client間有網絡分區存在(默認的檢測機制是15分鐘內低於85%的心跳彙報),Eureka Server會進入自我保護模式,不再把過期服務從服務註冊表移除(這種情況下客戶端有可能獲取已經停止的服務,配合使用Hystrix通過熔斷機制來容錯和降級,彌補基於客戶端服務發現的時效性的缺點)。更復雜的情況見在Eureka官網文檔上有詳細說明:Understanding Eureka Peer to Peer Communication

同類型的技術還有哪些?

dubbo,NacosConsul

搭建EurekaServer

現在搭建eureka實在是方便,我這邊使用的是IDEA新建的;

  • 新建model,選擇spring Initializr 選擇spring initializr
  • 選擇Eureka Server

    選擇Eureka Server

  • POM文件:

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.0.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <spring-cloud.version>Greenwich.M1</spring-cloud.version>
    </properties>
    
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>&lt;dependency&gt;
        &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
        &lt;artifactId&gt;spring-boot-starter-test&lt;/artifactId&gt;
        &lt;scope&gt;test&lt;/scope&gt;
    &lt;/dependency&gt;</dependencies>
    
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
    
  • application配置如下

    server.port=8081
    eureka.client.register-with-eureka=false
    eureka.client.fetch-registry=false
    eureka.client.serviceUrl.defaultZone=http://localhost:${server.port}/eureka/
    

    默認該服務註冊中心也會將自己作爲客戶端來嘗試註冊它自己,所以我們需要禁用它的客戶端註冊行爲,只需要在application.properties配置文件中增加以上信息即可;

  • 進入管理頁面

eureka註冊中心

此時還沒有啓動provide,所以目前提供方是空的;

搭建 provide Server

  • 新建的流程與eureka server一致,只是選擇組件的時候選擇eureka Discovery

    image

  • POM文件

<properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <spring-cloud.version>Greenwich.M1</spring-cloud.version>
    </properties>

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

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.16.16</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
  • appliaction.yml
server:
  port: 8080 # 服務端口
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8081/eureka/ # 服務註冊中心地址
spring:
  application:
    name: eureka-provider # 服務名稱

  • 提供服務代碼

@RestController @Slf4j public class ComputeController {

@Autowired
private DiscoveryClient discoveryClient;
@Autowired
private Registration registration;

@RequestMapping(value = "/add" ,method = RequestMethod.GET)
public Integer add(@RequestParam Integer a, @RequestParam Integer b) {
    ServiceInstance serviceInstance = this.serviceInstance();
    Integer r = a + b;
    log.info("/add, host:" + serviceInstance.getHost() + ", service_id:" + serviceInstance.getServiceId() + ", result:" + r);
    return r;
}

/**
 * 獲取當前服務的服務實例
 *
 * @return ServiceInstance
 */
public ServiceInstance serviceInstance() {
    List<ServiceInstance> list = discoveryClient.getInstances(registration.getServiceId());
    if (list != null && list.size() > 0) {
        return list.get(0);
    }
    return null;
}
}

  • 註冊中心監控

    服務提供者

此時可以看到服務提供者註冊成功了

搭建 Consumer Server

  • 創建方式與 provide Server一致
  • POM 文件內容也一致
  • application.yml
server:
  port: 8082 # 服務端口
eureka:
  client:
    register-with-eureka: false     #因此處只是消費,不提供服務,所以不需要向eureka server註冊
    service-url:
      defaultZone: http://localhost:8081/eureka/ # 服務註冊中心地址
spring:
  application:
    name: eureka-consumer # 服務名稱# 服務名稱
  • 消費者代碼
package com.lc.springcloud.eureka.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

/**
 * Eureka客戶端Controller
 * @author LC
 * @date 2018/11/9
 */
@RestController
public class ConsumerController {

    @Autowired
    private RestTemplate restTemplate;

    @RequestMapping(value = "/add", method = RequestMethod.GET)
    public String add() {
        System.out.println(restTemplate.getForEntity("http://EUREKA-PROVIDER/add?a=10&b=20", String.class).getBody());
        return restTemplate.getForEntity("http://EUREKA-PROVIDER/add?a=10&b=20", String.class).getBody();
    }
}
 

至此,spring cloud之eureka搭建完畢

文中示例代碼:eureka 示例

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章