SpringCloud微服務治理一(介紹,環境搭建,Eureka)

SpringCloud微服務治理一(介紹,環境搭建,Eureka)
SpringCloud微服務治理二(Robbin,Hystix,Feign)
SpringCloud微服務治理三(Zuul網關)php

1.遠程調用方式

瞭解一下微服務的調用方式java

1.1.RPC

RPC,即 Remote Procedure Call(遠程過程調用),是一個計算機通訊協議。 該協議容許運行於一臺計算機的程序調用另外一臺計算機的子程序,而程序員無需額外地爲這個交互做用編程。mysql

1.2.Http

Http協議:超文本傳輸協議,是一種應用層協議。程序員

2.Http客戶端工具

2.1 Spring的RestTemplate

Spring提供了一個RestTemplate模板工具類,對基於Http的客戶端進行了封裝,而且實現了對象與json的序列化和反序列化,很是方便。RestTemplate並無限定Http的客戶端類型,而是進行了抽象,目前經常使用的3種都有支持:web

  • HttpClient
  • OkHttp
  • JDK原生的URLConnection(默認的)

首先在項目中註冊一個RestTemplate對象,能夠在啓動類位置註冊:spring

@SpringBootApplication
public class HttpDemoApplication {

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

	@Bean
	public RestTemplate restTemplate() {
        // 默認的RestTemplate,底層是走JDK的URLConnection方式。
		return new RestTemplate();
	}
}
複製代碼

在測試類中直接@Autowired注入:sql

@RunWith(SpringRunner.class)
@SpringBootTest(classes = HttpDemoApplication.class)
public class HttpDemoApplicationTests {

	@Autowired
	private RestTemplate restTemplate;

	@Test
	public void httpGet() {
		User user = this.restTemplate.getForObject("http://localhost/hello", User.class);
		System.out.println(user);
	}
}
複製代碼

接下來正式介紹微服務。apache

3.SpringCloud

3.1.簡介

SpringCloud是Spring旗下的項目之一,官網地址:http://projects.spring.io/spring-cloud/編程

SpringCloud將如今很是流行的一些技術整合到一塊兒,實現了諸如:配置管理,服務發現,智能路由,負載均衡,熔斷器,控制總線,集羣狀態等等功能。其主要涉及的組件包括:json

netflix

  • Eureka:註冊中心
  • Zuul:服務網關
  • Ribbon:負載均衡
  • Feign:服務調用
  • Hystix:熔斷器

接下來,咱們就一一學習SpringCloud中的重要組件。

4.微服務場景模擬

首先,咱們須要模擬一個服務調用的場景。方便後面學習微服務架構

4.1.服務提供者

咱們新建一個項目,對外提供查詢用戶的服務。

4.1.1.Spring腳手架建立工程

依賴也已經所有自動引入:

<?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>

	<groupId>com.leyou.demo</groupId>
	<artifactId>user-service-demo</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>user-service-demo</name>
	<description>Demo project for Spring Boot</description>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.0.1.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>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-jdbc</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.mybatis.spring.boot</groupId>
			<artifactId>mybatis-spring-boot-starter</artifactId>
			<version>1.3.2</version>
		</dependency>
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

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

複製代碼

固然,由於要使用通用mapper,因此咱們須要手動加一條依賴:

<dependency>
    <groupId>tk.mybatis</groupId>
    <artifactId>mapper-spring-boot-starter</artifactId>
    <version>2.0.2</version>
</dependency>
複製代碼

很是快捷啊!

4.1.2.編寫代碼

添加一個對外查詢的接口:

@RestController
@RequestMapping("user")
public class UserController {

    @Autowired
    private UserService userService;

    @GetMapping("/{id}")
    public User queryById(@PathVariable("id") Long id) {
        return this.userService.queryById(id);
    }
}
複製代碼

Service:

@Service
public class UserService {

    @Autowired
    private UserMapper userMapper;

    public User queryById(Long id) {
        return this.userMapper.selectByPrimaryKey(id);
    }
}
複製代碼

mapper:

@Mapper
public interface UserMapper extends tk.mybatis.mapper.common.Mapper<User>{
}
複製代碼

實體類:

@Table(name = "tb_user")
public class User implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    // 用戶名
    private String userName;

    // 密碼
    private String password;

    // 姓名
    private String name;

    // 年齡
    private Integer age;

    // 性別,1男性,2女性
    private Integer sex;

    // 出生日期
    private Date birthday;

    // 建立時間
    private Date created;

    // 更新時間
    private Date updated;

    // 備註
    private String note;

   // 。。。省略getters和setters
}

複製代碼

屬性文件,這裏咱們採用了yaml語法,而不是properties:

server:
 port: 8081
spring:
 datasource:
 url: jdbc:mysql://localhost:3306/mydb01
 username: root
 password: 123
 hikari:
 maximum-pool-size: 20
 minimum-idle: 10
mybatis:
 type-aliases-package: com.leyou.userservice.pojo
複製代碼

4.2.服務調用者

4.2.1.建立工程

與上面相似,須要注意的是,咱們調用user-service的功能,所以不須要mybatis相關依賴了。

pom:

<?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>

	<groupId>com.leyou.demo</groupId>
	<artifactId>user-consumer-demo</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>user-consumer-demo</name>
	<description>Demo project for Spring Boot</description>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.0.1.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>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
        <!-- 添加OkHttp支持 -->
		<dependency>
			<groupId>com.squareup.okhttp3</groupId>
			<artifactId>okhttp</artifactId>
			<version>3.9.0</version>
		</dependency>
	</dependencies>

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

</project>

複製代碼

4.2.2.編寫代碼

首先在啓動類中註冊RestTemplate

@SpringBootApplication
public class UserConsumerDemoApplication {

    @Bean
    public RestTemplate restTemplate() {
        // 此次咱們使用了OkHttp客戶端,只須要注入工廠便可
        return new RestTemplate(new OkHttp3ClientHttpRequestFactory());
    }

    public static void main(String[] args) {
        SpringApplication.run(UserConsumerDemoApplication.class, args);
    }
}
複製代碼

經過RestTemplate遠程查詢user-service-demo中的接口:

@Component
public class UserDao {

    @Autowired
    private RestTemplate restTemplate;

    public User queryUserById(Long id){
        String url = "http://localhost:8081/user/" + id;
        return this.restTemplate.getForObject(url, User.class);
    }
}
複製代碼

而後編寫user-service,循環查詢UserDAO信息:

@Service
public class UserService {

    @Autowired
    private UserDao userDao;

    public List<User> querUserByIds(List<Long> ids){
        List<User> users = new ArrayList<>();
        for (Long id : ids) {
            User user = this.userDao.queryUserById(id);
            users.add(user);
        }
        return users;
    }
}
複製代碼

編寫controller:

@RestController
@RequestMapping("consume")
public class ConsumerController {

    @Autowired
    private UserService userService;

    @GetMapping
    public List<User> consume(@RequestParam("ids") List<Long> ids) {
        return this.userService.queryUserByIds(ids);
    }
}
複製代碼

4.3.問題?

  • 在consumer中,咱們把url地址硬編碼到了代碼中,不方便後期維護
  • consumer須要記憶user-service的地址,若是出現變動,可能得不到通知,地址將失效
  • consumer不清楚user-service的狀態,服務宕機也不知道
  • user-service只有1臺服務,不具有高可用性
  • 即使user-service造成集羣,consumer還需本身實現負載均衡

其實上面說的問題,歸納一下就是分佈式服務必然要面臨的問題:

  • 服務管理
    • 如何自動註冊和發現
    • 如何實現狀態監管
    • 如何實現動態路由
  • 服務如何實現負載均衡
  • 服務如何解決容災問題
  • 服務如何實現統一配置

以上的問題,咱們都將在SpringCloud中獲得答案。

5.Eureka註冊中心

5.1.原理圖

基本架構:

1525597885059

  • Eureka:就是服務註冊中心(能夠是一個集羣),對外暴露本身的地址
  • 提供者:啓動後向Eureka註冊本身信息(地址,提供什麼服務)
  • 消費者:向Eureka訂閱服務,Eureka會將對應服務的全部提供者地址列表發送給消費者,而且按期更新
  • 心跳(續約):提供者按期經過http方式向Eureka刷新本身的狀態

5.2.入門案例

5.2.1.編寫EurekaServer

接下來咱們建立一個項目,啓動一個EurekaServer:

依然使用spring提供的快速搭建工具,選擇依賴:

1525598312368

完整的Pom文件:

<?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>

	<groupId>com.leyou.demo</groupId>
	<artifactId>eureka-demo</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>eureka-demo</name>
	<description>Demo project for Spring Boot</description>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.0.1.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>
        <!-- SpringCloud版本,是最新的F系列 -->
		<spring-cloud.version>Finchley.RC1</spring-cloud.version>
	</properties>

	<dependencies>
        <!-- Eureka服務端 -->
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
		</dependency>
	</dependencies>

	<dependencyManagement>
		<dependencies>
            <!-- SpringCloud依賴,必定要放到dependencyManagement中,起到管理版本的做用便可 -->
			<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>

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

	<repositories>
		<repository>
			<id>spring-milestones</id>
			<name>Spring Milestones</name>
			<url>https://repo.spring.io/milestone</url>
			<snapshots>
				<enabled>false</enabled>
			</snapshots>
		</repository>
	</repositories>
</project>
複製代碼

編寫啓動類:

@SpringBootApplication
@EnableEurekaServer // 聲明這個應用是一個EurekaServer
public class EurekaDemoApplication {

	public static void main(String[] args) {
		SpringApplication.run(EurekaDemoApplication.class, args);
	}
}
複製代碼

編寫配置:

server:
 port: 10086 # 端口
spring:
 application:
 name: eureka-server # 應用名稱,會在Eureka中顯示
eureka:
 client:
 register-with-eureka: false # 是否註冊本身的信息到EurekaServer,默認是true
 fetch-registry: false # 是否拉取其它服務的信息,默認是true
 service-url: # EurekaServer的地址,如今是本身的地址,若是是集羣,須要加上其它Server的地址。
 defaultZone: http://127.0.0.1:${server.port}/eureka

複製代碼

啓動服務,並訪問:http://127.0.0.1:10086/eureka

1525604959508

1525605081129

5.2.2.將user-service註冊到Eureka

註冊服務,就是在服務上添加Eureka的客戶端依賴,客戶端代碼會自動把服務註冊到EurekaServer中。

咱們在user-service-demo中添加Eureka客戶端依賴:

先添加SpringCloud依賴:

<!-- SpringCloud的依賴 -->
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>Finchley.RC1</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>
<!-- Spring的倉庫地址 -->
<repositories>
    <repository>
        <id>spring-milestones</id>
        <name>Spring Milestones</name>
        <url>https://repo.spring.io/milestone</url>
        <snapshots>
            <enabled>false</enabled>
        </snapshots>
    </repository>
</repositories>
複製代碼

而後是Eureka客戶端:

<!-- Eureka客戶端 -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
複製代碼

在啓動類上開啓Eureka客戶端功能

經過添加@EnableDiscoveryClient來開啓Eureka客戶端功能

@SpringBootApplication
@EnableDiscoveryClient // 開啓EurekaClient功能
public class UserServiceDemoApplication {
	public static void main(String[] args) {
		SpringApplication.run(UserServiceDemoApplication.class, args);
	}
}
複製代碼

編寫配置

server:
 port: 8081
spring:
 datasource:
 url: jdbc:mysql://localhost:3306/mydb01
 username: root
 password: 123
 hikari:
 maximum-pool-size: 20
 minimum-idle: 10
 application:
 name: user-service # 應用名稱
mybatis:
 type-aliases-package: com.leyou.userservice.pojo
eureka:
 client:
 service-url: # EurekaServer地址
 defaultZone: http://127.0.0.1:10086/eureka
 instance:
 prefer-ip-address: true # 當調用getHostname獲取實例的hostname時,返回ip而不是host名稱
 ip-address: 127.0.0.1 # 指定本身的ip信息,不指定的話會本身尋找
複製代碼

注意:

  • 這裏咱們添加了spring.application.name屬性來指定應用名稱,未來會做爲應用的id使用。
  • 不用指定register-with-eureka和fetch-registry,由於默認是true

重啓項目,訪問Eureka監控頁面http://127.0.0.1:10086/eureka查看

1525609225152

咱們發現user-service服務已經註冊成功了

5.2.3.消費者從Eureka獲取服務

接下來咱們修改consumer-demo,嘗試從EurekaServer獲取服務。

方法與消費者相似,只須要在項目中添加EurekaClient依賴,就能夠經過服務名稱來獲取信息了!

1)添加依賴:

先添加SpringCloud依賴:

<!-- SpringCloud的依賴 -->
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>Finchley.RC1</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>
<!-- Spring的倉庫地址 -->
<repositories>
    <repository>
        <id>spring-milestones</id>
        <name>Spring Milestones</name>
        <url>https://repo.spring.io/milestone</url>
        <snapshots>
            <enabled>false</enabled>
        </snapshots>
    </repository>
</repositories>
複製代碼

而後是Eureka客戶端:

<!-- Eureka客戶端 -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
複製代碼

2)在啓動類開啓Eureka客戶端

@SpringBootApplication
@EnableDiscoveryClient // 開啓Eureka客戶端
public class UserConsumerDemoApplication {
    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate(new OkHttp3ClientHttpRequestFactory());
    }
    public static void main(String[] args) {
        SpringApplication.run(UserConsumerDemoApplication.class, args);
    }
}

複製代碼

3)修改配置:

server:
 port: 8080
spring:
 application:
 name: consumer # 應用名稱
eureka:
 client:
 service-url: # EurekaServer地址
 defaultZone: http://127.0.0.1:10086/eureka
 instance:
 prefer-ip-address: true # 當其它服務獲取地址時提供ip而不是hostname
 ip-address: 127.0.0.1 # 指定本身的ip信息,不指定的話會本身尋找
複製代碼

4)修改代碼,用DiscoveryClient類的方法,根據服務名稱,獲取服務實例:

@Service
public class UserService {

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private DiscoveryClient discoveryClient;// Eureka客戶端,能夠獲取到服務實例信息

    public List<User> queryUserByIds(List<Long> ids) {
        List<User> users = new ArrayList<>();
        // String baseUrl = "http://localhost:8081/user/";
        // 根據服務名稱,獲取服務實例
        List<ServiceInstance> instances = discoveryClient.getInstances("user-service");
        // 由於只有一個UserService,所以咱們直接get(0)獲取
        ServiceInstance instance = instances.get(0);
        // 獲取ip和端口信息
        String baseUrl = "http://"+instance.getHost() + ":" + instance.getPort()+"/user/";
        ids.forEach(id -> {
            // 咱們測試屢次查詢,
            users.add(this.restTemplate.getForObject(baseUrl + id, User.class));
            // 每次間隔500毫秒
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        return users;
    }
}
複製代碼

5.4.Eureka進階

5.4.1.高可用的Eureka Server

Eureka Server即服務的註冊中心,在剛纔的案例中,咱們只有一個EurekaServer,事實上EurekaServer也能夠是一個集羣,造成高可用的Eureka中心。

動手搭建高可用的EurekaServer

咱們假設要搭建兩條EurekaServer的集羣,端口分別爲:10086和10087

1)咱們修改原來的EurekaServer配置:

server:
 port: 10086 # 端口
spring:
 application:
 name: eureka-server # 應用名稱,會在Eureka中顯示
eureka:
 client:
 service-url: # 配置其餘Eureka服務的地址,而不是本身,好比10087
 defaultZone: http://127.0.0.1:10087/eureka

複製代碼

所謂的高可用註冊中心,其實就是把EurekaServer本身也做爲一個服務進行註冊,這樣多個EurekaServer之間就能互相發現對方,從而造成集羣。所以咱們作了如下修改:

  • 刪除了register-with-eureka=false和fetch-registry=false兩個配置。由於默認值是true,這樣就會吧本身註冊到註冊中心了。
  • 把service-url的值改爲了另一臺EurekaServer的地址,而不是本身

2)另一臺配置剛好相反:

server:
 port: 10087 # 端口
spring:
 application:
 name: eureka-server # 應用名稱,會在Eureka中顯示
eureka:
 client:
 service-url: # 配置其餘Eureka服務的地址,而不是本身,好比10087
 defaultZone: http://127.0.0.1:10086/eureka

複製代碼

注意:idea中一個應用不能啓動兩次,咱們須要從新配置一個啓動器:

1525615070033

1525615095693

1525615026937

而後啓動便可。

3)啓動測試:

1525615165157

4)客戶端註冊服務到集羣

由於EurekaServer不止一個,所以註冊服務的時候,service-url參數須要變化:

eureka:
 client:
 service-url: # EurekaServer地址,多個地址以','隔開
 defaultZone: http://127.0.0.1:10086/eureka,http://127.0.0.1:10087/eureka
複製代碼

5.4.2.服務提供者

服務提供者要向EurekaServer註冊服務,而且完成服務續約等工做。

服務註冊

服務提供者在啓動時,會檢測配置屬性中的:eureka.client.register-with-erueka=true參數是否正確,事實上默認就是true。若是值確實爲true,則會向EurekaServer發起一個Rest請求,並攜帶本身的元數據信息,Eureka Server會把這些信息保存到一個雙層Map結構中。第一層Map的Key就是服務名稱,第二層Map的key是服務的實例id。

服務續約

在註冊服務完成之後,服務提供者會維持一個心跳(定時向EurekaServer發起Rest請求),告訴EurekaServer:「我還活着」。這個咱們稱爲服務的續約(renew);

有兩個重要參數能夠修改服務續約的行爲:

eureka:
 instance:
 lease-expiration-duration-in-seconds: 90
 lease-renewal-interval-in-seconds: 30
複製代碼
  • lease-renewal-interval-in-seconds:服務續約(renew)的間隔,默認爲30秒
  • lease-expiration-duration-in-seconds:服務失效時間,默認值90秒

也就是說,默認狀況下每一個30秒服務會向註冊中心發送一次心跳,證實本身還活着。若是超過90秒沒有發送心跳,EurekaServer就會認爲該服務宕機,會從服務列表中移除,這兩個值在生產環境不要修改,默認便可。

可是在開發時,這個值有點太長了,常常咱們關掉一個服務,會發現Eureka依然認爲服務在活着。因此咱們在開發階段能夠適當調小。

eureka:
 instance:
 lease-expiration-duration-in-seconds: 10 # 10秒即過時
 lease-renewal-interval-in-seconds: 5 # 5秒一次心跳
複製代碼

實例id

先來看一下服務狀態信息:

在Eureka監控頁面,查看服務註冊信息:

1525617060656

在status一列中,顯示如下信息:

  • UP(1):表明如今是啓動了1個示例,沒有集羣
  • DESKTOP-2MVEC12:user-service:8081:是示例的名稱(instance-id),
    • 默認格式是:${hostname} + ${spring.application.name} + ${server.port}
    • instance-id是區分同一服務的不一樣實例的惟一標準,所以不能重複。

咱們能夠經過instance-id屬性來修改它的構成:

eureka:
 instance:
 instance-id: ${spring.application.name}:${server.port}
複製代碼

重啓服務再試試看:

1525617542081

5.4.3.服務消費者

獲取服務列表

當服務消費者啓動時會檢測eureka.client.fetch-registry=true參數的值,若是爲true,則會從Eureka Server服務的列表只讀備份,而後緩存在本地。而且每隔30秒會從新獲取並更新數據。咱們能夠經過下面的參數來修改:

eureka:
 client:
 registry-fetch-interval-seconds: 5
複製代碼

生產環境中,咱們不須要修改這個值。

可是爲了開發環境下,可以快速獲得服務的最新狀態,咱們能夠將其設置小一點。

5.4.4.失效剔除和自我保護

失效剔除

有些時候,咱們的服務提供方並不必定會正常下線,可能由於內存溢出、網絡故障等緣由致使服務沒法正常工做。Eureka Server須要將這樣的服務剔除出服務列表。所以它會開啓一個定時任務,每隔60秒對全部失效的服務(超過90秒未響應)進行剔除。

能夠經過eureka.server.eviction-interval-timer-in-ms參數對其進行修改,單位是毫秒,生成環境不要修改。

這個會對咱們開發帶來極大的不變,你對服務重啓,隔了60秒Eureka才反應過來。開發階段能夠適當調整,好比10S

自我保護

咱們關停一個服務,就會在Eureka面板看到一條警告:

1525618396076

這是觸發了Eureka的自我保護機制。當一個服務未按時進行心跳續約時,Eureka會統計最近15分鐘心跳失敗的服務實例的比例是否超過了85%。在生產環境下,由於網絡延遲等緣由,心跳失敗實例的比例頗有可能超標,可是此時就把服務剔除列表並不穩當,由於服務可能沒有宕機。Eureka就會把當前實例的註冊信息保護起來,不予剔除。生產環境下這頗有效,保證了大多數服務依然可用。

可是這給咱們的開發帶來了麻煩, 所以開發階段咱們都會關閉自我保護模式:

eureka:
 server:
 enable-self-preservation: false # 關閉自我保護模式(缺省爲打開)
 eviction-interval-timer-in-ms: 1000 # 掃描失效服務的間隔時間(缺省爲60*1000ms)
複製代碼
相關文章
相關標籤/搜索