springcloud學習筆記

1. 服務的註冊與發現(Eureka)

1、spring cloud簡介

spring cloud 爲開發人員提供了快速構建分佈式系統的一些工具,包括配置管理、服務發現、斷路器、路由、微代理、事件總線、全局鎖、決策競選、分佈式會話等等。它運行環境簡單,能夠在開發人員的電腦上跑。java

2、建立服務註冊中心

在這裏,咱們須要用的的組件上Spring Cloud Netflix的Eureka ,eureka是一個服務註冊和發現模塊。git

開發環境:eclipse luna4.四、jdk1.八、maven3.2.3github

1eureka-server工程web

Pom.xmlspring

<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">sql

  <modelVersion>4.0.0</modelVersion>apache

  <groupId>com.forezp</groupId>bootstrap

  <artifactId>eureka-server</artifactId>後端

  <version>0.0.1-SNAPSHOT</version>api

 

  <parent>

       <groupId>org.springframework.boot</groupId>

       <artifactId>spring-boot-starter-parent</artifactId>

       <version>1.5.2.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.cloud</groupId>

           <artifactId>spring-cloud-starter-eureka-server</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>Dalston.RC1</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>

 

2 啓動一個服務註冊中心,只須要一個註解@EnableEurekaServer,這個註解須要在springboot工程的啓動application類上加:

package com.forezp;

 

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

 

@EnableEurekaServer

@SpringBootApplication

public class EurekaServerApplication {

 

         public static void main(String[] args) {

                   SpringApplication.run(EurekaServerApplication.class, args);

         }

}

 

3.eureka是一個高可用的組件,它沒有後端緩存,每個實例註冊以後須要向註冊中心發送心跳(所以能夠在內存中完成),在默認狀況下erureka server也是一個eureka client ,必需要指定一個 server。eureka server的配置文件appication.yml,在resources中建立

server:

  port: 8761

 

eureka:

  instance:

    hostname: localhost

  client:

    registerWithEureka: false

    fetchRegistry: false

    serviceUrl:

      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/

4.eureka server 是有界面的,啓動工程,打開瀏覽器訪問: 
http://localhost:8761 ,界面以下

 

3、建立一個服務提供者 (eureka client)

當client向server註冊時,它會提供一些元數據,例如主機和端口,URL,主頁等。Eureka server 從每一個client實例接收心跳消息。 若是心跳超時,則一般將該實例從註冊server中刪除。

1.Pom.xml

<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.forezp</groupId>

  <artifactId>service-hi</artifactId>

  <version>0.0.1-SNAPSHOT</version>

 

  <parent>

        <groupId>org.springframework.boot</groupId>

        <artifactId>spring-boot-starter-parent</artifactId>

        <version>1.5.2.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.cloud</groupId>

            <artifactId>spring-cloud-starter-eureka</artifactId>

        </dependency>

        <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>Dalston.RC1</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>

  1. 經過註解@EnableEurekaClient 代表本身是一個eurekaclient.

package com.forezp;

 

import org.springframework.beans.factory.annotation.Value;

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

import org.springframework.cloud.netflix.eureka.EnableEurekaClient;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RequestParam;

import org.springframework.web.bind.annotation.RestController;

 

@SpringBootApplication

@EnableEurekaClient

@RestController

public class ServiceHiApplication {

 

    public static void main(String[] args) {

       SpringApplication.run(ServiceHiApplication.class, args);

    }

 

    @Value("${server.port}")

    String port;

    @RequestMapping("/hi")

    public String home(@RequestParam String name) {

       return "hi "+name+",i am from port:" +port;

    }

 

}

 

  1. 僅僅@EnableEurekaClient是不夠的,還須要在配置文件中註明本身的服務註冊中心的地址,application.yml配置文件以下:

eureka:

  client:

    serviceUrl:

      defaultZone: http://localhost:8761/eureka/

server:

  port: 8762

spring:

  application:

    name: service-hi

須要指明spring.application.name,這個很重要,這在之後的服務與服務之間相互調用通常都是根據這個name 。 
4.啓動工程,打開http://localhost:8761 ,即eureka server 的網址:

 

你會發現一個服務已經註冊在服務中了,服務名爲SERVICE-HI ,端口爲8762

這時打開 http://localhost:8762/hi?name=forezp ,你會在瀏覽器上看到 :

hi forezp,i am from port:8762

2. 服務消費者(rest+ribbon)

1、ribbon簡介

ribbon是一個負載均衡客戶端,能夠很好的控制htt和tcp的一些行爲。Feign默認集成了ribbon。

ribbon 已經默認實現了這些配置bean:

  • IClientConfig ribbonClientConfig: DefaultClientConfigImpl
  • IRule ribbonRule: ZoneAvoidanceRule
  • IPing ribbonPing: NoOpPing
  • ServerList ribbonServerList: ConfigurationBasedServerList
  • ServerListFilter ribbonServerListFilter: ZonePreferenceServerListFilter
  • ILoadBalancer ribbonLoadBalancer: ZoneAwareLoadBalancer

2、準備工做

這一篇文章基於上一篇文章的工程,啓動eureka-server 工程;啓動service-hi工程,它的端口爲8762;將service-hi的配置文件的端口改成8763,並啓動,這時你會發現:service-hi在eureka-server註冊了2個實例,這就至關於一個小的集羣。訪問localhost:8761如圖所示:

 

3、建一個服務消費者

項目結構如圖

 

從新新建一個spring-boot工程,取名爲:service-ribbon; 
在它的pom.xml文件分別引入起步依賴spring-cloud-starter-eureka、spring-cloud-starter-ribbon、spring-boot-starter-web,代碼以下:

<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.forezp</groupId>

  <artifactId>service-ribbon</artifactId>

  <version>0.0.1-SNAPSHOT</version>

 

  <parent>

        <groupId>org.springframework.boot</groupId>

        <artifactId>spring-boot-starter-parent</artifactId>

        <version>1.5.2.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.cloud</groupId>

            <artifactId>spring-cloud-starter-eureka</artifactId>

        </dependency>

        <dependency>

            <groupId>org.springframework.cloud</groupId>

            <artifactId>spring-cloud-starter-ribbon</artifactId>

        </dependency>

        <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>Dalston.RC1</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>

在工程的配置文件指定服務的註冊中心地址爲http://localhost:8761/eureka/,程序名稱爲 service-ribbon,程序端口爲8764。配置文件application.yml以下:

eureka:

  client:

    serviceUrl:

      defaultZone: http://localhost:8761/eureka/

server:

  port: 8764

spring:

  application:

    name: service-ribbon

在工程的啓動類中,經過@EnableDiscoveryClient向服務中心註冊;而且向程序的ioc注入一個bean: restTemplate;並經過@LoadBalanced註解代表這個restRemplate開啓負載均衡的功能。

package com.forezp;

 

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

import org.springframework.cloud.client.loadbalancer.LoadBalanced;

import org.springframework.context.annotation.Bean;

import org.springframework.web.client.RestTemplate;

 

@SpringBootApplication

@EnableDiscoveryClient

public class ServiceRibbonApplication {

 

    public static void main(String[] args) {

        SpringApplication.run(ServiceRibbonApplication.class, args);

    }

 

    @Bean

    @LoadBalanced

    RestTemplate restTemplate() {

        return new RestTemplate();

    }

 

}

寫一個測試類HelloService,經過以前注入ioc容器的restTemplate來消費service-hi服務的「/hi」接口,在這裏咱們直接用的程序名替代了具體的url地址,在ribbon中它會根據服務名來選擇具體的服務實例,根據服務實例在請求的時候會用具體的url替換掉服務名,代碼以下:

package com.forezp.service;

 

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Service;

import org.springframework.web.client.RestTemplate;

 

 

@Service

public class HelloService {

 

    @Autowired

    RestTemplate restTemplate;

 

    public String hiService(String name) {

        return restTemplate.getForObject("http://SERVICE-HI/hi?name="+name,String.class);

    }

 

}

寫一個controller,在controller中用調用HelloService 的方法,代碼以下:

package com.forezp.web;

 

import com.forezp.service.HelloService;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RequestParam;

import org.springframework.web.bind.annotation.RestController;

 

 

@RestController

public class HelloControler {

@Autowired

    HelloService helloService;

 

    @RequestMapping(value = "/hi")

    public String hi(@RequestParam String name){

        return helloService.hiService(name);

    }

}

在瀏覽器上屢次訪問http://localhost:8764/hi?name=forezp,瀏覽器交替顯示:

hi forezp,i am from port:8762

hi forezp,i am from port:8763

3.服務消費者(Feign)

1、Feign簡介

Feign是一個聲明式的僞Http客戶端,它使得寫Http客戶端變得更簡單。使用Feign,只須要建立一個接口並註解。它具備可插拔的註解特性,可以使用Feign 註解和JAX-RS註解。Feign支持可插拔的編碼器和解碼器。Feign默認集成了Ribbon,並和Eureka結合,默認實現了負載均衡的效果。

簡而言之:

  • Feign 採用的是基於接口的註解
  • Feign 整合了ribbon

2、準備工做

繼續用上一節的工程, 啓動eureka-server,端口爲8761; 啓動service-hi 兩次,端口分別爲8762 、8763.

3、建立一個feign的服務

新建一個spring-boot工程,取名爲serice-feign,在它的pom文件引入Feign的起步依賴spring-cloud-starter-feign、Eureka的起步依賴spring-cloud-starter-eureka、Web的起步依賴spring-boot-starter-web,代碼以下:

<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.forezp</groupId>

  <artifactId>service-feign</artifactId>

  <version>0.0.1-SNAPSHOT</version>

 

  <parent>

        <groupId>org.springframework.boot</groupId>

        <artifactId>spring-boot-starter-parent</artifactId>

        <version>1.5.2.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.cloud</groupId>

            <artifactId>spring-cloud-starter-eureka</artifactId>

        </dependency>

        <dependency>

            <groupId>org.springframework.cloud</groupId>

            <artifactId>spring-cloud-starter-feign</artifactId>

        </dependency>

        <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>Dalston.RC1</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>

在工程的配置文件application.yml文件,指定程序名爲service-feign,端口號爲8765,服務註冊地址爲http://localhost:8761/eureka/ ,代碼以下:

eureka:

  client:

    serviceUrl:

      defaultZone: http://localhost:8761/eureka/

server:

  port: 8765

spring:

  application:

    name: service-feign

在程序的啓動類ServiceFeignApplication ,加上@EnableFeignClients註解開啓Feign的功能:

package com.forezp;

 

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

import org.springframework.cloud.netflix.feign.EnableFeignClients;

 

@SpringBootApplication

@EnableDiscoveryClient

@EnableFeignClients

public class ServiceFeignApplication {

 

    public static void main(String[] args) {

        SpringApplication.run(ServiceFeignApplication.class, args);

    }

}

定義一個feign接口,經過@ FeignClient(「服務名」),來指定調用哪一個服務。好比在代碼中調用了service-hi服務的「/hi」接口,代碼以下:

package com.forezp.service;

 

import org.springframework.cloud.netflix.feign.FeignClient;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RequestMethod;

import org.springframework.web.bind.annotation.RequestParam;

 

@FeignClient(value = "service-hi")

public interface SchedualServiceHi {

    @RequestMapping(value = "/hi",method = RequestMethod.GET)

    String sayHiFromClientOne(@RequestParam(value = "name") String name);

}

啓動程序,屢次訪問http://localhost:8765/hi?name=forezp,瀏覽器交替顯示:

hi forezp,i am from port:8762

hi forezp,i am from port:8763

 

4.斷路器(Hystrix)

在微服務架構中,根據業務來拆分紅一個個的服務,服務與服務之間能夠相互調用(RPC),在Spring Cloud能夠用RestTemplate+Ribbon和Feign來調用。爲了保證其高可用,單個服務一般會集羣部署。因爲網絡緣由或者自身的緣由,服務並不能保證100%可用,若是單個服務出現問題,調用這個服務就會出現線程阻塞,此時如有大量的請求涌入,Servlet容器的線程資源會被消耗完畢,致使服務癱瘓。服務與服務之間的依賴性,故障會傳播,會對整個微服務系統形成災難性的嚴重後果,這就是服務故障的「雪崩」效應。

爲了解決這個問題,業界提出了斷路器模型。

1、斷路器簡介

Netflix開源了Hystrix組件,實現了斷路器模式,SpringCloud對這一組件進行了整合。 在微服務架構中,一個請求須要調用多個服務是很是常見的,以下圖:

 

較底層的服務若是出現故障,會致使連鎖故障。當對特定的服務的調用的不可用達到一個閥值(Hystric 是5秒20次) 斷路器將會被打開。

 

斷路打開後,可用避免連鎖故障,fallback方法能夠直接返回一個固定值。

2、準備工做

這篇文章基於上一篇文章的工程,首先啓動上一篇文章的工程,啓動eureka-server 工程;啓動service-hi工程,它的端口爲8762。

3、在ribbon使用斷路器

改造serice-ribbon 工程的代碼,首先在pox.xml文件中加入spring-cloud-starter-hystrix的起步依賴:

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

在程序的啓動類ServiceRibbonApplication 加@EnableHystrix註解開啓Hystrix:

package com.forezp;

 

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

import org.springframework.cloud.client.loadbalancer.LoadBalanced;

import org.springframework.cloud.netflix.hystrix.EnableHystrix;

import org.springframework.context.annotation.Bean;

import org.springframework.web.client.RestTemplate;

 

@SpringBootApplication

@EnableDiscoveryClient

@EnableHystrix

public class ServiceRibbonApplication {

 

    public static void main(String[] args) {

        SpringApplication.run(ServiceRibbonApplication.class, args);

    }

 

    @Bean

    @LoadBalanced

    RestTemplate restTemplate() {

        return new RestTemplate();

    }

}

 

改造HelloService類,在hiService方法上加上@HystrixCommand註解。該註解對該方法建立了熔斷器的功能,並指定了fallbackMethod熔斷方法,熔斷方法直接返回了一個字符串,字符串爲」hi,」+name+」,sorry,error!」,代碼以下:

package com.forezp.service;

 

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Service;

import org.springframework.web.client.RestTemplate;

 

import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;

 

 

@Service

public class HelloService {

 

    @Autowired

    RestTemplate restTemplate;

 

    @HystrixCommand(fallbackMethod = "hiError")

    public String hiService(String name) {

        return restTemplate.getForObject("http://SERVICE-HI/hi?name="+name,String.class);

    }

 

    public String hiError(String name) {

        return "hi,"+name+",sorry,error!";

    }}

 

啓動:service-ribbon 工程,當咱們訪問http://localhost:8764/hi?name=forezp,瀏覽器顯示:

hi forezp,i am from port:8762

此時關閉 service-hi 工程,當咱們再訪問http://localhost:8764/hi?name=forezp,瀏覽器會顯示:

hi ,forezp,orry,error!

這就說明當 service-hi 工程不可用的時候,service-ribbon調用 service-hi的API接口時,會執行快速失敗,直接返回一組字符串,而不是等待響應超時,這很好的控制了容器的線程阻塞。

4、Feign中使用斷路器

Feign是自帶斷路器的,在D版本的Spring Cloud中,它沒有默認打開。須要在配置文件中配置打開它,在配置文件加如下代碼:

feign.hystrix.enabled=true

eureka:

  client:

    serviceUrl:

      defaultZone: http://localhost:8761/eureka/

server:

  port: 8765

spring:

  application:

    name: service-feign

feign:

  hystrix:

    enabled:

      true   

 

基於service-feign工程進行改造,只須要在FeignClient的SchedualServiceHi接口的註解中加上fallback的指定類就好了:

value"service-hi"@FeignClient(=,fallback = SchedualServiceHiHystric.class)
publicinterfaceSchedualServiceHi {
value"/hi"    @RequestMapping(=,method = RequestMethod.GET)
value"name"    String sayHiFromClientOne(@RequestParam(=) String name);
}

 

SchedualServiceHiHystric須要實現SchedualServiceHi 接口,並注入到Ioc容器中,代碼以下:

@Component
publicclass SchedualServiceHiHystric implements SchedualServiceHi {
@Override   
publicsayHiFromClientOne   String(String name) {
return"sorry "       +name;
    }
}

 

啓動四servcie-feign工程,瀏覽器打開http://localhost:8765/hi?name=forezp,注意此時service-hi工程沒有啓動,網頁顯示:

sorry forezp

打開service-hi工程,再次訪問,瀏覽器顯示:

hi forezp,i am from port:8762

這證實斷路器起到做用了。

5、Hystrix Dashboard (斷路器:Hystrix 儀表盤)

基於service-ribbon 改造,Feign的改造和這同樣。

首選在pom.xml引入spring-cloud-starter-hystrix-dashboard的起步依賴:

<dependency>
<groupId></groupId>           org.springframework.boot
<artifactId></artifactId>           spring-boot-starter-actuator
</dependency>       
 
<dependency>       
<groupId></groupId>           org.springframework.cloud
<artifactId></artifactId>           spring-cloud-starter-hystrix-dashboard
</dependency>       

在主程序啓動類中加入@EnableHystrixDashboard註解,開啓hystrixDashboard:

@SpringBootApplication
@EnableDiscoveryClient
@EnableHystrix
@EnableHystrixDashboard
publicclass ServiceRibbonApplication {
 
publicstaticvoidmain   (String[] args) {
        SpringApplication.run(ServiceRibbonApplication.class, args);
    }
 
@Bean   
@LoadBalanced   
    RestTemplate restTemplate() {
returnnew       RestTemplate();
    }
 
}

打開瀏覽器:訪問http://localhost:8764/hystrix,界面以下:

 

點擊monitor stream,進入下一個界面,訪問:http://localhost:8764/hi?name=forezp

此時會出現監控界面:

 

5.路由網關(zuul)

在微服務架構中,須要幾個基礎的服務治理組件,包括服務註冊與發現、服務消費、負載均衡、斷路器、智能路由、配置管理等,由這幾個基礎組件相互協做,共同組建了一個簡單的微服務系統。一個簡單的微服務系統以下圖:

 
注意:A服務和B服務是能夠相互調用的,做圖的時候忘記了。而且配置服務也是註冊到服務註冊中心的。

在Spring Cloud微服務系統中,一種常見的負載均衡方式是,客戶端的請求首先通過負載均衡(zuul、Ngnix),再到達服務網關(zuul集羣),而後再到具體的服。,服務統一註冊到高可用的服務註冊中心集羣,服務的全部的配置文件由配置服務管理(下一篇文章講述),配置服務的配置文件放在git倉庫,方便開發人員隨時改配置。

1、Zuul簡介

Zuul的主要功能是路由轉發和過濾器。路由功能是微服務的一部分,好比/api/user轉發到user服務,/api/shop轉發到shop服務。zuul默認和Ribbon結合實現了負載均衡的功能。

zuul有如下功能:

  • Authentication
  • Insights
  • Stress Testing
  • Canary Testing
  • Dynamic Routing
  • Service Migration
  • Load Shedding
  • Security
  • Static Response handling
  • Active/Active traffic management

2、準備工做

繼續使用上一節的工程。在原有的工程上,建立一個新的工程。

3、建立service-zuul工程

其pom.xml文件以下:

<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.forezp</groupId>

  <artifactId>service-zuul</artifactId>

  <version>0.0.1-SNAPSHOT</version>

  <name>service-zuul</name>

  <description>Demo project for Spring Boot</description>

 

  <parent>

        <groupId>org.springframework.boot</groupId>

        <artifactId>spring-boot-starter-parent</artifactId>

        <version>1.5.2.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.cloud</groupId>

            <artifactId>spring-cloud-starter-eureka</artifactId>

        </dependency>

        <dependency>

            <groupId>org.springframework.cloud</groupId>

            <artifactId>spring-cloud-starter-zuul</artifactId>

        </dependency>

        <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>Dalston.RC1</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>

 

在其入口applicaton類加上註解@EnableZuulProxy,開啓zuul的功能:

package com.forezp;

 

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

import org.springframework.cloud.netflix.eureka.EnableEurekaClient;

import org.springframework.cloud.netflix.zuul.EnableZuulProxy;

 

@EnableZuulProxy

@EnableEurekaClient

@SpringBootApplication

public class ServiceZuulApplication {

 

    public static void main(String[] args) {

        SpringApplication.run(ServiceZuulApplication.class, args);

    }

}

 

加上配置文件application.yml加上如下的配置代碼:

eureka:

  client:

    serviceUrl:

      defaultZone: http://localhost:8761/eureka/

server:

  port: 8769

spring:

  application:

    name: service-zuul

zuul:

  routes:

    api-a:

      path: /api-a/**

      serviceId: service-ribbon

    api-b:

      path: /api-b/**

      serviceId: service-feign

 

首先指定服務註冊中心的地址爲http://localhost:8761/eureka/,服務的端口爲8769,服務名爲service-zuul;以/api-a/ 開頭的請求都轉發給service-ribbon服務;以/api-b/開頭的請求都轉發給service-feign服務;

依次運行這五個工程;打開瀏覽器訪問:http://localhost:8769/api-a/hi?name=forezp ;瀏覽器顯示:

hi forezp,i am from port:8762

打開瀏覽器訪問:http://localhost:8769/api-b/hi?name=forezp ;瀏覽器顯示:

hi forezp,i am from port:8762

這說明zuul起到了路由的做用

4、服務過濾

zuul不只只是路由,而且還能過濾,作一些安全驗證。繼續改造工程;

package com.forezp;

import com.netflix.zuul.ZuulFilter;

import com.netflix.zuul.context.RequestContext;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.stereotype.Component;

 

import javax.servlet.http.HttpServletRequest;

 

@Component

public class MyFilter extends ZuulFilter{

 

    private static Logger log = LoggerFactory.getLogger(MyFilter.class);

    @Override

    public String filterType() {

        return "pre";

    }

 

    @Override

    public int filterOrder() {

        return 0;

    }

 

    @Override

    public boolean shouldFilter() {

        return true;

    }

 

    @Override

    public Object run() {

        RequestContext ctx = RequestContext.getCurrentContext();

        HttpServletRequest request = ctx.getRequest();

        log.info(String.format("%s >>> %s", request.getMethod(), request.getRequestURL().toString()));

        Object accessToken = request.getParameter("token");

        if(accessToken == null) {

            log.warn("token is empty");

            ctx.setSendZuulResponse(false);

            ctx.setResponseStatusCode(401);

            try {

                ctx.getResponse().getWriter().write("token is empty");

            }catch (Exception e){}

 

            return null;

        }

        log.info("ok");

        return null;

    }

}

  • filterType:返回一個字符串表明過濾器的類型,在zuul中定義了四種不一樣生命週期的過濾器類型,具體以下: 

    • pre:路由以前
    • routing:路由之時
    • post: 路由以後
    • error:發送錯誤調用
    • filterOrder:過濾的順序
    • shouldFilter:這裏能夠寫邏輯判斷,是否要過濾,本文true,永遠過濾。
    • run:過濾器的具體邏輯。可用很複雜,包括查sql,nosql去判斷該請求到底有沒有權限訪問。

這時訪問:http://localhost:8769/api-a/hi?name=forezp ;網頁顯示:

token is empty

訪問 http://localhost:8769/api-a/hi?name=forezp&token=22 ; 
網頁顯示:

hi forezp,i am from port:8762

6.分佈式配置中心(Spring Cloud Config)

1、簡介

在分佈式系統中,因爲服務數量巨多,爲了方便服務配置文件統一管理,實時更新,因此須要分佈式配置中心組件。在Spring Cloud中,有分佈式配置中心組件spring cloud config ,它支持配置服務放在配置服務的內存中(即本地),也支持放在遠程Git倉庫中。在spring cloud config 組件中,分兩個角色,一是config server,二是config client。

2、構建Config Server

建立一個spring-boot項目,取名爲config-server,其pom.xml:

<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.forezp</groupId>

  <artifactId>config-server</artifactId>

  <version>0.0.1-SNAPSHOT</version>

  <name>config-server</name>

  <description>Demo project for Spring Boot</description>

 

   <parent>

        <groupId>org.springframework.boot</groupId>

        <artifactId>spring-boot-starter-parent</artifactId>

        <version>1.5.2.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.cloud</groupId>

            <artifactId>spring-cloud-config-server</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>

    </dependencies>

 

    <dependencyManagement>

        <dependencies>

            <dependency>

                <groupId>org.springframework.cloud</groupId>

                <artifactId>spring-cloud-dependencies</artifactId>

                <version>Camden.SR6</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>

 

在程序的入口Application類加上@EnableConfigServer註解開啓配置服務器的功能,代碼以下:

package com.forezp;

 

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

import org.springframework.cloud.config.server.EnableConfigServer;

 

@SpringBootApplication

@EnableConfigServer

public class ConfigServerApplication {

 

    public static void main(String[] args) {

        SpringApplication.run(ConfigServerApplication.class, args);

    }

}

 

 

須要在程序的配置文件application.properties文件配置如下:

spring.application.name=config-server

server.port=8888

 

spring.cloud.config.server.git.uri=https://github.com/forezp/SpringcloudConfig/

spring.cloud.config.server.git.searchPaths=respo

spring.cloud.config.label=master

spring.cloud.config.server.git.username=

spring.cloud.config.server.git.password=

 

spring.cloud.config.server.git.uri:配置git倉庫地址

spring.cloud.config.server.git.searchPaths:配置倉庫路徑

spring.cloud.config.label:配置倉庫的分支

spring.cloud.config.server.git.username:訪問git倉庫的用戶名

spring.cloud.config.server.git.password:訪問git倉庫的用戶密碼

若是Git倉庫爲公開倉庫,能夠不填寫用戶名和密碼,若是是私有倉庫須要填寫,本例子是公開倉庫,放心使用。

遠程倉庫https://github.com/forezp/SpringcloudConfig/ 中有個文件config-client-dev.properties文件中有一個屬性:

foo = foo version 3

啓動程序:訪問http://localhost:8888/foo/dev

name"foo"profiles["dev"]label"master"{"":,"":,"":,
version"792ffc77c03f4b138d28e89b576900ac5e01a44b"statenullpropertySources[]"":,"":,"":}

證實配置服務中心能夠從遠程程序獲取配置信息。

http請求地址和資源文件映射以下:

  • /{application}/{profile}[/{label}]
  • /{application}-{profile}.yml
  • /{label}/{application}-{profile}.yml
  • /{application}-{profile}.properties
  • /{label}/{application}-{profile}.properties

3、構建一個config client

從新建立一個springboot項目,取名爲config-client,其pom文件:

<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.forezp</groupId>

  <artifactId>config-client</artifactId>

  <version>0.0.1-SNAPSHOT</version>

  <name>config-client</name>

  <description>Demo project for Spring Boot</description>

 

  <parent>

        <groupId>org.springframework.boot</groupId>

        <artifactId>spring-boot-starter-parent</artifactId>

        <version>1.5.2.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.cloud</groupId>

            <artifactId>spring-cloud-starter-config</artifactId>

        </dependency>

 

        <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>Dalston.RC1</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>

 

其配置文件bootstrap.properties

spring.application.name=config-client

spring.cloud.config.label=master

spring.cloud.config.profile=dev

spring.cloud.config.uri= http://localhost:8888/

server.port=8881

 

 spring.cloud.config.label 指明遠程倉庫的分支

  • spring.cloud.config.profile
    • dev開發環境配置文件
    • test測試環境
    • pro正式環境
    • spring.cloud.config.uri= http://localhost:8888/ 指明配置服務中心的網址。

程序的入口類,寫一個API接口「/hi」,返回從配置中心讀取的foo變量的值,代碼以下:

package com.forezp;

 

import org.springframework.beans.factory.annotation.Value;

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RestController;

 

@SpringBootApplication

@RestController

public class ConfigClientApplication {

 

    public static void main(String[] args) {

        SpringApplication.run(ConfigClientApplication.class, args);

    }

 

    @Value("${foo}")

    String foo;

    @RequestMapping(value = "/hi")

    public String hi(){

        return foo;

    }

}

 

打開網址訪問:http://localhost:8881/hi,網頁顯示:

foo version 3

這就說明,config-client從config-server獲取了foo的屬性,而config-server是從git倉庫讀取的,如圖:

 

7. 高可用的分佈式配置中心(Spring Cloud Config)

上一篇文章講述了一個服務如何從配置中心讀取文件,配置中心如何從遠程git讀取配置文件,當服務實例不少時,都從配置中心讀取文件,這時能夠考慮將配置中心作成一個微服務,將其集羣化,從而達到高可用,架構圖以下:

 

1、準備工做

繼續使用上一篇文章的工程,建立一個eureka-server工程,用做服務註冊中心。

在其pom.xml文件引入Eureka的起步依賴spring-cloud-starter-eureka-server,代碼以下:

<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.forezp</groupId>

      <artifactId>eureka-server</artifactId>

      <version>0.0.1-SNAPSHOT</version>

      <packaging>jar</packaging>

 

      <parent>

           <groupId>org.springframework.boot</groupId>

           <artifactId>spring-boot-starter-parent</artifactId>

           <version>1.5.2.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.cloud</groupId>

                 <artifactId>spring-cloud-starter-eureka-server</artifactId>

           </dependency>

           <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>Dalston.RC1</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>

在配置文件application.yml上,指定服務端口爲8889,加上做爲服務註冊中心的基本配置,代碼以下:

server:

  port: 8889

 

eureka:

  instance:

    hostname: localhost

  client:

    registerWithEureka: false

    fetchRegistry: false

    serviceUrl:

      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/

入口類:

package com.forezp;

 

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

 

 

@EnableEurekaServer

@SpringBootApplication

public class EurekaServerApplication {

 

    public static void main(String[] args) {

        SpringApplication.run(EurekaServerApplication.class, args);

    }

}

2、改造config-server

在其pom.xml文件加上EurekaClient的起步依賴spring-cloud-starter-eureka,代碼以下:

<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.forezp</groupId>

  <artifactId>config-server</artifactId>

  <version>0.0.1-SNAPSHOT</version>

  <name>config-server</name>

  <description>Demo project for Spring Boot</description>

 

  <parent>

           <groupId>org.springframework.boot</groupId>

           <artifactId>spring-boot-starter-parent</artifactId>

           <version>1.5.2.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.cloud</groupId>

                 <artifactId>spring-cloud-config-server</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>

      </dependencies>

 

      <dependencyManagement>

           <dependencies>

                 <dependency>

                      <groupId>org.springframework.cloud</groupId>

                      <artifactId>spring-cloud-dependencies</artifactId>

                      <version>Camden.SR6</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>

配置文件application.yml,指定服務註冊地址爲http://localhost:8889/eureka/,其餘配置同上一篇文章,完整的配置以下:

spring.application.name=config-server

server.port=8888

 

spring.cloud.config.server.git.uri=https://github.com/forezp/SpringcloudConfig/

spring.cloud.config.server.git.searchPaths=respo

spring.cloud.config.label=master

spring.cloud.config.server.git.username=

spring.cloud.config.server.git.password=

eureka.client.serviceUrl.defaultZone=http://localhost:8889/eureka/

入口類:

package com.forezp;

 

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

import org.springframework.cloud.config.server.EnableConfigServer;

import org.springframework.cloud.netflix.eureka.EnableEurekaClient;

 

@SpringBootApplication

@EnableConfigServer

@EnableEurekaClient

public class ConfigServerApplication {

 

    public static void main(String[] args) {

        SpringApplication.run(ConfigServerApplication.class, args);

    }

}

3、改造config-client

將其註冊微到服務註冊中心,做爲Eureka客戶端,須要pom文件加上起步依賴spring-cloud-starter-eureka,代碼以下:

<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.forezp</groupId>

  <artifactId>config-client</artifactId>

  <version>0.0.1-SNAPSHOT</version>

  <name>config-client</name>

  <description>Demo project for Spring Boot</description>

 

  <parent>

           <groupId>org.springframework.boot</groupId>

           <artifactId>spring-boot-starter-parent</artifactId>

           <version>1.5.2.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.cloud</groupId>

                 <artifactId>spring-cloud-starter-config</artifactId>

           </dependency>

 

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

          

           <dependency>

            <groupId>org.springframework.cloud</groupId>

            <artifactId>spring-cloud-starter-config</artifactId>

        </dependency>

 

        <dependency>

            <groupId>org.springframework.boot</groupId>

            <artifactId>spring-boot-starter-web</artifactId>

        </dependency>

 

        <dependency>

            <groupId>org.springframework.cloud</groupId>

            <artifactId>spring-cloud-starter-eureka</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>Dalston.RC1</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>

配置文件bootstrap.properties,注意是bootstrap。加上服務註冊地址爲http://localhost:8889/eureka/

spring.application.name=config-client

spring.cloud.config.label=master

spring.cloud.config.profile=dev

#spring.cloud.config.uri= http://localhost:8888/

 

eureka.client.serviceUrl.defaultZone=http://localhost:8889/eureka/

spring.cloud.config.discovery.enabled=true

spring.cloud.config.discovery.serviceId=config-server

server.port=8881

  • spring.cloud.config.discovery.enabled 是從配置中心讀取文件。
  • spring.cloud.config.discovery.serviceId 配置中心的servieId,即服務名。

這時發現,在讀取配置文件再也不寫ip地址,而是服務名,這時若是配置服務部署多份,經過負載均衡,從而高可用。

依次啓動eureka-servr,config-server,config-client 
訪問網址:http://localhost:8889/

 

訪問http://localhost:8881/hi,瀏覽器顯示:

foo version 3

 

 

8.消息總線(Spring Cloud Bus)

Spring Cloud Bus 將分佈式的節點用輕量的消息代理鏈接起來。它能夠用於廣播配置文件的更改或者服務之間的通信,也能夠用於監控。本文要講述的是用Spring Cloud Bus實現通知微服務架構的配置文件的更改。

1、準備工做

本文仍是基於上一篇文章來實現。按照官方文檔,咱們只須要在配置文件中配置 spring-cloud-starter-bus-amqp ;這就是說咱們須要裝rabbitMq

2、改造config-client

在pom文件加上起步依賴spring-cloud-starter-bus-amqp,完整的配置文件以下:

<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.forezp</groupId>

  <artifactId>config-client</artifactId>

  <version>0.0.1-SNAPSHOT</version>

  <name>config-client</name>

  <description>Demo project for Spring Boot</description>

 

 <parent>

        <groupId>org.springframework.boot</groupId>

        <artifactId>spring-boot-starter-parent</artifactId>

        <version>1.5.2.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.retry</groupId>

            <artifactId>spring-retry</artifactId>

        </dependency>

        <dependency>

            <groupId>org.springframework.cloud</groupId>

            <artifactId>spring-cloud-starter-config</artifactId>

        </dependency>

 

        <dependency>

            <groupId>org.springframework.boot</groupId>

            <artifactId>spring-boot-starter-web</artifactId>

        </dependency>

        <dependency>

            <groupId>org.springframework.boot</groupId>

            <artifactId>spring-boot-starter-aop</artifactId>

        </dependency>

 

 

        <dependency>

            <groupId>org.springframework.cloud</groupId>

            <artifactId>spring-cloud-starter-eureka</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-bus-amqp</artifactId>

        </dependency>

 

        <dependency>

            <groupId>org.springframework.boot</groupId>

            <artifactId>spring-boot-starter-actuator</artifactId>

        </dependency>

    </dependencies>

 

    <dependencyManagement>

        <dependencies>

            <dependency>

                <groupId>org.springframework.cloud</groupId>

                <artifactId>spring-cloud-dependencies</artifactId>

                <version>Dalston.RC1</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>

 

在配置文件application.properties中加上RabbitMq的配置,包括RabbitMq的地址、端口,用戶名、密碼,代碼以下:

spring.application.name=config-client

spring.cloud.config.label=master

spring.cloud.config.profile=dev

#spring.cloud.config.uri= http://localhost:8888/

 

eureka.client.serviceUrl.defaultZone=http://localhost:8889/eureka/

spring.cloud.config.discovery.enabled=true

spring.cloud.config.discovery.serviceId=config-server

server.port=8882

 

spring.rabbitmq.host=localhost

spring.rabbitmq.port=15672

spring.rabbitmq.username=guest

spring.rabbitmq.password=guest

 

若是rabbitmq有用戶名密碼,輸入便可。

依次啓動eureka-server、confg-cserver,啓動兩個config-client,端口爲:888一、8882。

訪問http://localhost:8881/hi 或者http://localhost:8882/hi 瀏覽器顯示:

foo version 3

這時咱們去代碼倉庫將foo的值改成「foo version 4」,即改變配置文件foo的值。若是是傳統的作法,須要重啓服務,才能達到配置文件的更新。此時,咱們只須要發送post請求:http://localhost:8881/bus/refresh,你會發現config-client會從新讀取配置文件

 

從新讀取配置文件:

 

這時咱們再訪問http://localhost:8881/hi 或者http://localhost:8882/hi 瀏覽器顯示:

foo version 4

另外,/bus/refresh接口能夠指定服務,即便用」destination」參數,好比 「/bus/refresh?destination=customers:**」 即刷新服務名爲customers的全部服務,無論ip。

3、分析

此時的架構圖: 

當git文件更改的時候,經過pc端用post 向端口爲8882的config-client發送請求/bus/refresh/;此時8882端口會發送一個消息,由消息總線向其餘服務傳遞,從而使整個微服務集羣都達到更新配置文件。

9. 服務鏈路追蹤(Spring Cloud Sleuth)

這篇文章主要講述服務追蹤組件zipkin,Spring Cloud Sleuth集成了zipkin組件。

1、簡介

Add sleuth to the classpath of a Spring Boot application (see below for Maven and Gradle examples), and you will see the correlation data being collected in logs, as long as you are logging requests.

—— 摘自官網

Spring Cloud Sleuth 主要功能就是在分佈式系統中提供追蹤解決方案,而且兼容支持了 zipkin,你只須要在pom文件中引入相應的依賴便可。

2、服務追蹤分析

微服務架構上經過業務來劃分服務的,經過REST調用,對外暴露的一個接口,可能須要不少個服務協同才能完成這個接口功能,若是鏈路上任何一個服務出現問題或者網絡超時,都會造成致使接口調用失敗。隨着業務的不斷擴張,服務之間互相調用會愈來愈複雜。

 

隨着服務的愈來愈多,對調用鏈的分析會愈來愈複雜。它們之間的調用關係也許以下:

 

3、術語

  • Span:基本工做單元,例如,在一個新建的span中發送一個RPC等同於發送一個迴應請求給RPC,span經過一個64位ID惟一標識,trace以另外一個64位ID表示,span還有其餘數據信息,好比摘要、時間戳事件、關鍵值註釋(tags)、span的ID、以及進度ID(一般是IP地址) 
    span在不斷的啓動和中止,同時記錄了時間信息,當你建立了一個span,你必須在將來的某個時刻中止它。
  • Trace:一系列spans組成的一個樹狀結構,例如,若是你正在跑一個分佈式大數據工程,你可能須要建立一個trace。
  • Annotation:用來及時記錄一個事件的存在,一些核心annotations用來定義一個請求的開始和結束 

    • cs - Client Sent -客戶端發起一個請求,這個annotion描述了這個span的開始
    • sr - Server Received -服務端得到請求並準備開始處理它,若是將其sr減去cs時間戳即可獲得網絡延遲
    • ss - Server Sent -註解代表請求處理的完成(當請求返回客戶端),若是ss減去sr時間戳即可獲得服務端須要的處理請求時間
    • cr - Client Received -代表span的結束,客戶端成功接收到服務端的回覆,若是cr減去cs時間戳即可獲得客戶端從服務端獲取回覆的全部所需時間 
      將Span和Trace在一個系統中使用Zipkin註解的過程圖形化:

將Span和Trace在一個系統中使用Zipkin註解的過程圖形化:

 

4、構建工程

基本知識講解完畢,下面咱們來實戰,本文的案例主要有三個工程組成:一個server-zipkin,它的主要做用使用ZipkinServer 的功能,收集調用數據,並展現;一個service-hi,對外暴露hi接口;一個service-miya,對外暴露miya接口;這兩個service能夠相互調用;而且只有調用了,server-zipkin纔會收集數據的,這就是爲何叫服務追蹤了。

4.1 構建server-zipkin

建一個spring-boot工程取名爲server-zipkin,在其pom引入依賴:

<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.forezp</groupId>

  <artifactId>server-zipkin</artifactId>

  <version>0.0.1-SNAPSHOT</version>

  <name>server-zipkin</name>

  <description>Demo project for Spring Boot</description>

 

  <parent>

           <groupId>org.springframework.boot</groupId>

           <artifactId>spring-boot-starter-parent</artifactId>

           <version>1.5.2.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</artifactId>

           </dependency>

 

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

 

           <dependency>

                 <groupId>io.zipkin.java</groupId>

                 <artifactId>zipkin-server</artifactId>

           </dependency>

 

           <dependency>

                 <groupId>io.zipkin.java</groupId>

                 <artifactId>zipkin-autoconfigure-ui</artifactId>

           </dependency>

 

      </dependencies>

 

      <dependencyManagement>

           <dependencies>

                 <dependency>

                      <groupId>org.springframework.cloud</groupId>

                      <artifactId>spring-cloud-dependencies</artifactId>

                      <version>Camden.SR6</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>

 

在其程序入口類, 加上註解@EnableZipkinServer,開啓ZipkinServer的功能:

package com.forezp;

 

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

import zipkin.server.EnableZipkinServer;

 

@SpringBootApplication

@EnableZipkinServer

public class ServerZipkinApplication {

 

      public static void main(String[] args) {

           SpringApplication.run(ServerZipkinApplication.class, args);

      }}

 

在配置文件application.properties指定服務端口爲:

server.port9411=

4.2 建立service-hi

在其pom引入起步依賴spring-cloud-starter-zipkin,代碼以下:

<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.forezp</groupId>

  <artifactId>service-hi</artifactId>

  <version>0.0.1-SNAPSHOT</version>

 

  <parent>

           <groupId>org.springframework.boot</groupId>

           <artifactId>spring-boot-starter-parent</artifactId>

           <version>1.5.2.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>

           <!--compile('org.springframework.cloud:spring-cloud-starter-zipkin')-->

 

           <dependency>

                 <groupId>org.springframework.cloud</groupId>

                 <artifactId>spring-cloud-starter-zipkin</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>Dalston.RC1</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>

 

在其配置文件application.properties指定zipkin server的地址,頭經過配置「spring.zipkin.base-url」指定:

 
.port8988server=
.zipkin.base9411spring-url=http://localhost:
.application.namespring=service-hi

經過引入spring-cloud-starter-zipkin依賴和設置spring.zipkin.base-url就能夠了。

入口類對外暴露接口:

package com.forezp;

 

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

import org.springframework.context.annotation.Bean;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RestController;

import org.springframework.web.client.RestTemplate;

import org.springframework.cloud.sleuth.sampler.AlwaysSampler;

import java.util.logging.Level;

import java.util.logging.Logger;

 

@SpringBootApplication

@RestController

public class ServiceHiApplication {

 

      public static void main(String[] args) {

           SpringApplication.run(ServiceHiApplication.class, args);

      }

 

      private static final Logger LOG = Logger.getLogger(ServiceHiApplication.class.getName());

 

 

      @Autowired

      private RestTemplate restTemplate;

 

      @Bean

      public RestTemplate getRestTemplate(){

           return new RestTemplate();

      }

 

      @RequestMapping("/hi")

      public String callHome(){

           LOG.log(Level.INFO, "calling trace service-hi  ");

           return restTemplate.getForObject("http://localhost:8989/miya", String.class);

      }

      @RequestMapping("/info")

      public String info(){

           LOG.log(Level.INFO, "calling trace service-hi ");

 

           return "i'm service-hi";

 

      }

 

      @Bean

      public AlwaysSampler defaultSampler(){

           return new AlwaysSampler();

      }

}

 

4.3 建立service-miya

建立過程同service-hi,引入相同的依賴,配置下spring.zipkin.base-url。

server.port=8989

spring.zipkin.base-url=http://localhost:9411

spring.application.name=service-miya

 

對外暴露接口:

package com.forezp;

 

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

import org.springframework.context.annotation.Bean;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RestController;

import org.springframework.web.client.RestTemplate;

 

import java.util.logging.Level;

import java.util.logging.Logger;

 

@SpringBootApplication

@RestController

public class ServiceMiyaApplication {

 

      public static void main(String[] args) {

           SpringApplication.run(ServiceMiyaApplication.class, args);

      }

 

      private static final Logger LOG = Logger.getLogger(ServiceMiyaApplication.class.getName());

 

 

      @RequestMapping("/hi")

      public String home(){

           LOG.log(Level.INFO, "hi is being called");

           return "hi i'm miya!";

      }

 

      @RequestMapping("/miya")

      public String info(){

           LOG.log(Level.INFO, "info is being called");

           return restTemplate.getForObject("http://localhost:8988/info",String.class);

      }

 

      @Autowired

      private RestTemplate restTemplate;

 

      @Bean

      public RestTemplate getRestTemplate(){

           return new RestTemplate();

      }

}

 

 

4.4 啓動工程,演示追蹤

依次啓動上面的三個工程,打開瀏覽器訪問:http://localhost:9411/,會出現如下界面:

 

訪問:http://localhost:8988/hi,瀏覽器出現:

i’m service-hi

再打開http://localhost:9411/的界面,點擊Dependencies,能夠發現服務的依賴關係:

 

點擊find traces,能夠看到具體服務相互調用的數據:

 

10.高可用的服務註冊中心

服務註冊中心Eureka Server,是一個實例,當成千上萬個服務向它註冊的時候,它的負載是很是高的,這在生產環境上是不太合適的,這篇文章主要介紹怎麼將Eureka Server集羣化。

高可用的註冊中心實現思路

Eureka經過「夥伴」機制實現高可用。每一臺Eureka都須要在配置中指定另外一個Eureka的地址做爲夥伴,Eureka啓動時會向本身的夥伴節點獲取當前已經存在的註冊列表, 這樣在向Eureka集羣中新加機器時就不須要擔憂註冊列表不完整的問題。

除此以外,Eureka還支持Region和Zone的概念。其中一個Region能夠包含多個Zone。Eureka在啓動時須要指定一個Zone名,即當前Eureka屬於哪一個zone, 若是不指定則屬於defaultZone。Eureka Client也須要指定Zone, Client(當與Ribbon配置使用時)在向Server獲取註冊列表時會優先向本身Zone的Eureka發請求,若是本身Zone中的Eureka全掛了纔會嘗試向其它Zone。Region和Zone能夠對應於現實中的大區和機房,如在華北地區有10個機房,在華南地區有20個機房,那麼分別爲Eureka指定合理的Region和Zone能有效避免跨機房調用,同時一個地區的Eureka壞掉不會致使整個該地區的服務都不可用。

本文咱們經過運行eureka-server多個實例,並進行互相註冊的方式來實現高可用的部署,咱們只須要將Eureke Server配置其餘可用的serviceUrl就能實現高可用部署。

咱們能夠建立三個註冊中心節點,每一個節點進行兩兩註冊,實現徹底對等的效果,能夠達到集羣的最高可用性,任何一個節點掛掉都不會影響服務的註冊與發現。

 

1、服務器準備

在winsow環境下測試 ,打開C:\Windows\System32\drivers\etc的hosts文件,添加下列內容
127.0.0.1   eureka-server-peer1 
127.0.0.1   eureka-server-peer2 
127.0.0.1   eureka-server-peer3 

2、建立三個項目

項目名稱分別爲spring-cloud-server、spring-cloud-server_一、spring-cloud-server_2;

Pom.xml均爲

<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.springcloud</groupId>

  <artifactId>spring-cloud-server_2</artifactId>

  <version>0.0.1-SNAPSHOT</version>

 

  <parent>

           <groupId>org.springframework.boot</groupId>

           <artifactId>spring-boot-starter-parent</artifactId>

           <version>1.5.2.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.cloud</groupId>

                 <artifactId>spring-cloud-starter-eureka-server</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>Dalston.RC1</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>

 

3、修改application.properties

spring-cloud-server的

server.port=8761

spring.application.name=microservice-eureka-server

spring.profiles=peer1

eureka.instance.hostname=eureka-server-peer1

eureka.client.register-with-eureka=false

eureka.client.fetch-registry=false

eureka.client.serviceUrl.defaultZone=http://eureka-server-peer2:8762/eureka/,http://eureka-server-peer3:8763/eureka/

 

spring-cloud-server_1的

server.port=8762

spring.application.name=microservice-eureka-server

spring.profiles=peer2

eureka.instance.hostname=eureka-server-peer2

eureka.client.register-with-eureka=false

eureka.client.fetch-registry=false

eureka.client.serviceUrl.defaultZone=http://eureka-server-peer1:8761/eureka/,http://eureka-server-peer3:8763/eureka/

 

spring-cloud-server_2的

server.port=8763

spring.application.name=microservice-eureka-server

spring.profiles=peer3

eureka.instance.hostname=eureka-server-peer3

eureka.client.register-with-eureka=false

eureka.client.fetch-registry=false

eureka.client.serviceUrl.defaultZone=http://eureka-server-peer1:8761/eureka/,http://eureka-server-peer2:8762/eureka/

 

4、啓動類

更改對應的類名便可

package com.forezp;

 

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

 

@EnableEurekaServer

@SpringBootApplication

public class EurekaServerApplication {

 

      public static void main(String[] args) {

           SpringApplication.run(EurekaServerApplication.class, args);

      }

}

 

 

5、分別啓動三個項目

訪問http://localhost:8761/  能夠看到DS Replicas中出現peer二、peer3

 

 

同理訪問http://localhost:8762/  能夠看到peer一、peer3節點;訪問http://localhost:8763/  能夠看到peer一、peer2節點;

 

6、建立一個服務提供者 (eureka client)

參考1中步驟,其中配置信息以下:

eureka:

  client:

    serviceUrl:

      defaultZone: http://eureka-server-peer1:8761/eureka/

server:

  port: 8888

spring:

  application:

    name: service-hi

啓動後,發現分別訪問http://localhost:8761/ 、http://localhost:8762/ 、http://localhost:8763/ ,都可看到service-hi註冊在服務中

 

 

當關閉spring-cloud-server服務,訪問http://localhost:8762/ 、http://localhost:8763/ ,一樣能夠看到service-hi註冊在服務中。這樣就實現了集羣的高可用。

相關文章
相關標籤/搜索