Eureka實戰

1、微服務架構中關鍵組件:服務提供者、服務消費者、服務發現組件

  其中,服務提供者的變化依賴於服務發現組件,對服務消費者來說透明
2、服務發現組件的功能
  1)服務註冊表:用來記錄各個微服務的信息,名稱、IP、端口等。並提供查詢API(用於查詢可用的微服務實例)和管理API(用於服務的註冊和註銷)
  2)服務註冊:指微服務在啓動時,將自己的信息註冊到服務發現組件上的過程
  3)服務發現:指查詢可用微服務列表及其網絡地址的機制
  4)服務檢查:服務發現組件使用一定機制定時檢測已註冊的服務,如發現某實例長時間無法訪問,就會從服務註冊表中移除該實例
3、Eureka:是Netflix開源的服務發現組件,本身是一個REST的服務,包含Server和Client兩部分
在這裏插入圖片描述
4、Eureka元數據
  1)標準元數據:主機名、IP地址、端口號、狀態頁、健康檢查等
  2)自定義元數據:使用eureka.instance.metadata-map配置
5、REST端點
  Eureka Server提供了一些REST端點,服務可使用這些端點操作Eureka,從而實現註冊與發現,前面使用的Eureka Client就是java編寫的操作REST端點的類庫。可以使用XML或JSON與端點通信,默認XML

操作 請求方式 端點URL 返回值說明
註冊新服務 POST /eureka/apps/{appID} 傳遞JSON或者XML格式參數內容,HTTP code爲204時表示成功
註銷服務 DELETE /eureka/apps/{appID}/{instanceID} HTTP code爲200時表示成功
心跳檢測 PUT /eureka/apps/{appID}/{instanceID} HTTP code爲200時表示成功
查詢所有服務 GET /eureka/apps HTTP code爲200時表示成功,返回XML/JSON數據內容
查詢appID下的服務列表 GET /eureka/apps/{appID} HTTP code爲200時表示成功,返回XML/JSON數據內容
查詢指定appID下指定instanceID的服務 GET /eureka/apps/{appID}/{instanceID} 獲取指定appID以及InstanceId的服務信息,HTTP code爲200時表示成功,返回XML/JSON數據內容
查詢指定instanceID服務列表 GET /eureka/apps/instances/{instanceID} 獲取指定instanceID的服務列表,HTTP code爲200時表示成功,返回XML/JSON數據內容
變更服務狀態 PUT /eureka/apps/{appID}/{instanceID}/status?value=DOWN 服務上線、服務下線等狀態變動,HTTP code爲200時表示成功
變更元數據 PUT /eureka/apps/{appID}/{instanceID}/metadata?key=value HTTP code爲200時表示成功
查詢指定IP下的服務列表 GET /eureka/vips/{vipAddress} HTTP code爲200時表示成功
查詢指定安全IP下的服務列表 GET /eureka/svips/{svipAddress} HTTP code爲200時表示成功

  其中appID是應用程序名稱即微服務集羣名稱,instanceID是實例相關聯的唯一ID即某一個服務節點的ID
6、Eureka的自我保護模式
  默認EurekaServer在90秒沒有接收到某個微服務實例的心跳,將會註銷該實例。當EurekaServer節點在短時間內丟失過多客戶端時(可能發生了網絡分區故障),那麼這個節點就會進入自我保護模式,即保護服務註冊表中的信息,不再刪除服務註冊表中的數據(也就是不會註銷任何微服務),當網絡故障恢復後,該EurekaServer節點會自動退出自我保護模式
  注:可食用eureka.server.enable-self-preservation = false 禁用自我保護模式
7、多網卡環境下的IP選擇
  1)忽略指定名稱的網卡:spring.cloud.inetutils.ignored-interfaces = - docker0
  2)使用正則表達式,指定使用的網絡地址:spring.cloud.inetutils.preferredNetworks: -192.168
  3)只使用站點本地地址:spring.cloud.inetutils.useOnlySiteLocalInterfaces = true
  4)手動指定IP地址:eureka.instance.ip-address = 127.0.0.1
8、開啓Eureka的健康檢查
  eureka.client.healthcheck.enabled = true
  注:該配置只能配置在application.yml中,不能配置在bootstrap.yml中
9、競品對比
  SpringCloud的服務註冊發現組件可使用:Eureka、Zookeeper、Consul

組件名 語言 CAP 一致性算法 服務健康檢查 對外暴露接口 SpringCloud集成
Eureka Java AP 可配支持 HTTP 已集成
Consul Go CP Raft 支持 HTTP/DNS 已集成
Zookeeper Java CP Paxos 支持 客戶端 已集成
  注:1)Raft:Raft是一種共識算法,旨在替代Paxos。 它通過邏輯分離比Paxos更容易理解,但它也被正式證明是安全的,並提供了一些額外的功能。[1] Raft提供了一種在計算系統集羣中分佈狀態機的通用方法,確保集羣中的每個節點都同意一系列相同的狀態轉換。 它有許多開源參考實現,具有Go,C ++,Java和Scala中的完整規範實現。 2)Paxos:Paxos算法是萊斯利·蘭伯特(Leslie Lamport,就是 LaTeX 中的"La",此人現在在微軟研究院)於1990年提出的一種基於消息傳遞的一致性算法。這個算法被認爲是類似算法中最有效的。

10、Demo

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>1.4.3.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.springcloud.demo</groupId>
	<artifactId>spring-cloud-demo</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>spring-cloud-demo</name>
	<description>Demo project for Spring Boot</description>
	<packaging>pom</packaging>

	<properties>
		<java.version>1.8</java.version>
	</properties>

	<modules>
		<module>eureka1</module>
		<module>eureka2</module>
		<module>movie</module>
		<module>user</module>
	</modules>

	<dependencies>
		<!-- spring boot -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-jpa</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>

		<!-- 其他依賴 -->
		<dependency>
			<groupId>com.h2database</groupId>
			<artifactId>h2</artifactId>
		</dependency>
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<optional>true</optional>
		</dependency>

	</dependencies>

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

</project>

1)Eureka1(集羣節點1)

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>com.springcloud.demo</groupId>
		<artifactId>spring-cloud-demo</artifactId>
		<version>0.0.1-SNAPSHOT</version>
	</parent>
	<groupId>com.springcloud.demo</groupId>
	<artifactId>eureka1</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>eureka1</name>
	<description>Demo project for Spring Boot</description>

	<properties>
		<java.version>1.8</java.version>
	</properties>

	<dependencies>
		<!-- eureka server -->
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-eureka-server</artifactId>
		</dependency>
		<!-- spring boot 權限 -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-security</artifactId>
		</dependency>
	</dependencies>

	<dependencyManagement>
		<dependencies>
			<!-- spring cloud -->
			<dependency>
				<groupId>org.springframework.cloud</groupId>
				<artifactId>spring-cloud-dependencies</artifactId>
				<version>Camden.SR4</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
		</dependencies>
	</dependencyManagement>

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

</project>

server:
  port: 8761
eureka:
  client:
    # 是否將自己註冊到EurekaServer,默認true
#    registerWithEureka: false
    # 是否從EurekaServer獲取信息,默認true,eureka集羣同步信息時需要開啓
#    fetchRegistry: false
    serviceUrl:
      # 設置與EurekaServer交互的地址,多個地址可用英文逗號分隔
#      defaultZone: http://peer2:8762/eureka/
      defaultZone: http://user:123qwe@peer2:8762/eureka/
  instance:
    hostname: peer1
spring:
  application:
    name: eureka1
security:
  basic:
    # 開啓基於HTTP basic的認證
    enabled: true
  # 設置登錄用戶名密碼
  user:
    name: user
    password: 123qwe
package com.springcloud.demo.eureka1;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

@SpringBootApplication
@EnableEurekaServer
public class Eureka1Application {

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

}

2)Eureka2(集羣節點2)

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>com.springcloud.demo</groupId>
		<artifactId>spring-cloud-demo</artifactId>
		<version>0.0.1-SNAPSHOT</version>
	</parent>
	<groupId>com.springcloud.demo</groupId>
	<artifactId>eureka2</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>eureka2</name>
	<description>Demo project for Spring Boot</description>

	<properties>
		<java.version>1.8</java.version>
	</properties>

	<dependencies>
		<!-- eureka server -->
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-eureka-server</artifactId>
		</dependency>
		<!-- spring boot 權限 -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-security</artifactId>
		</dependency>
	</dependencies>

	<dependencyManagement>
		<dependencies>
			<!-- spring cloud -->
			<dependency>
				<groupId>org.springframework.cloud</groupId>
				<artifactId>spring-cloud-dependencies</artifactId>
				<version>Camden.SR4</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
		</dependencies>
	</dependencyManagement>

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

</project>

server:
  port: 8762
eureka:
  client:
#    # 是否將自己註冊到EurekaServer,默認true
#    registerWithEureka: false
#    # 是否從EurekaServer獲取信息,默認true,eureka集羣同步信息時需要開啓
#    fetchRegistry: false
    serviceUrl:
      # 設置與EurekaServer交互的地址,多個地址可用英文逗號分隔
#      defaultZone: http://peer1:8761/eureka/
      defaultZone: http://user:123qwe@peer1:8761/eureka/
  instance:
    hostname: peer2
spring:
  application:
    name: eureka2
security:
  basic:
    # 開啓基於HTTP basic的認證
    enabled: true
  # 設置登錄用戶名密碼
  user:
    name: user
    password: 123qwe
package com.springcloud.demo.eureka2;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

@SpringBootApplication
@EnableEurekaServer
public class Eureka2Application {

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

}

3)User(用戶服務)

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>com.springcloud.demo</groupId>
		<artifactId>spring-cloud-demo</artifactId>
		<version>0.0.1-SNAPSHOT</version>
	</parent>
	<groupId>com.springcloud.demo</groupId>
	<artifactId>user</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>user</name>
	<description>Demo project for Spring Boot</description>

	<properties>
		<java.version>1.8</java.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>

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

	</dependencies>

	<dependencyManagement>
		<dependencies>
			<!-- spring cloud -->
			<dependency>
				<groupId>org.springframework.cloud</groupId>
				<artifactId>spring-cloud-dependencies</artifactId>
				<version>Camden.SR4</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
		</dependencies>
	</dependencyManagement>

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

</project>

server:
  port: 8000
spring:
  jpa:
    generate-ddl: false
    show-sql: true
    hibernate:
      ddl-auto: none
  datasource:
    platform: h2
    schema: classpath:schema.sql
    data: classpath:data.sql
  application:
    # 用於指定註冊到EurekaServer上的應用名稱
    name: user
logging:
  level:
    root: INFO
    org.hibernate: INFO
    org.hibernate.type.descriptor.sql.BasicBinder: TRACE
    org.hibernate.type.descriptor.sql.BasicExtractor: TRACE
eureka:
  client:
    serviceUrl:
          # 設置與EurekaServer交互的地址,多個地址可用英文逗號分隔
#          defaultZone: http://peer1:8761/eureka/, http://peer2:8762/eureka/
          defaultZone: http://user:123qwe@peer1:8761/eureka/, http://user:123qwe@peer2:8762/eureka/
  instance:
    # 表示將自己的IP註冊到EurekaServer,默認false表示註冊微服務所在操作系統到hostname到EurekaServer
    prefer-ip-address: true
package com.springcloud.demo.user;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;

@SpringBootApplication
@EnableEurekaClient // 聲明這是一個EurekaClient,@EnableDiscoverClient是一個抽象聲明,組件實現可以使用eureka、zookeeper、consul
public class UserApplication {

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

}

package com.springcloud.demo.user;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import java.math.BigDecimal;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import lombok.Getter;
import lombok.Setter;

@Entity
@Getter
@Setter
@JsonIgnoreProperties(value = { "hibernateLazyInitializer", "handler" })
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @Column
    private String username;

    @Column
    private String name;

    @Column
    private Integer age;

    @Column
    private BigDecimal balance;
}

package com.springcloud.demo.user;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface UserRepository extends JpaRepository<User, Long> {
}

package com.springcloud.demo.user;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class UserController {
    @Autowired
    private UserRepository userRepository;

    @GetMapping("/{id}")
    public User findById(@PathVariable Long id) {
        return userRepository.getOne(id);
    }
}

4)Movie(電影服務)

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>com.springcloud.demo</groupId>
		<artifactId>spring-cloud-demo</artifactId>
		<version>0.0.1-SNAPSHOT</version>
	</parent>
	<groupId>com.springcloud.demo</groupId>
	<artifactId>movie</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>movie</name>
	<description>Demo project for Spring Boot</description>

	<properties>
		<java.version>1.8</java.version>
	</properties>

	<dependencies>
		<!-- eureka client -->
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-eureka</artifactId>
		</dependency>
		<!-- fastjson -->
		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>fastjson</artifactId>
			<version>1.2.57</version>
		</dependency>
	</dependencies>

	<dependencyManagement>
		<dependencies>
			<!-- spring cloud -->
			<dependency>
				<groupId>org.springframework.cloud</groupId>
				<artifactId>spring-cloud-dependencies</artifactId>
				<version>Camden.SR4</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
		</dependencies>
	</dependencyManagement>

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

</project>

server:
  port: 8010
spring:
  application:
    # 用於指定註冊到EurekaServer上的應用名稱
    name: movie
eureka:
  client:
    serviceUrl:
          # 設置與EurekaServer交互的地址,多個地址可用英文逗號分隔
#          defaultZone: http://peer1:8761/eureka/, http://peer2:8762/eureka/
          defaultZone: http://user:123qwe@peer1:8761/eureka/, http://user:123qwe@peer2:8762/eureka/
  instance:
    # 表示將自己的IP註冊到EurekaServer,默認false表示註冊微服務所在操作系統到hostname到EurekaServer
    prefer-ip-address: true
package com.springcloud.demo.movie;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;

@SpringBootApplication
@EnableEurekaClient // 聲明這是一個EurekaClient,@EnableDiscoverClient是一個抽象聲明,組件實現可以使用eureka、zookeeper、consul
public class MovieApplication {

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

}

package com.springcloud.demo.movie;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

@Configuration
public class MovieConfiguration {
    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

package com.springcloud.demo.movie;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import java.math.BigDecimal;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import lombok.Getter;
import lombok.Setter;

@Entity
@Getter
@Setter
@JsonIgnoreProperties(value = { "hibernateLazyInitializer", "handler" })
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @Column
    private String username;

    @Column
    private String name;

    @Column
    private Integer age;

    @Column
    private BigDecimal balance;
}

package com.springcloud.demo.movie;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

@RestController
public class MovieController {
    @Autowired
    private RestTemplate restTemplate;

    @GetMapping("/user/{id}")
    public User findById(@PathVariable Long id) {
        // 此處暫未通過微服務調用
        return restTemplate.getForObject("http://127.0.0.1:8000/" + id, User.class);
    }
}

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