spring cloud

第一篇:服務的註冊與發現Eureka(Finchley版本html

1、spring cloud簡介

鑑於《史上最簡單的Spring Cloud教程》很受讀者歡迎,再次我特地升級了一下版本,目前支持的版本爲Spring Boot版本2.0.3.RELEASE,Spring Cloud版本爲Finchley.RELEASE。java

Finchley版本的官方文檔以下: 
http://cloud.spring.io/spring-cloud-static/Finchley.RELEASE/single/spring-cloud.htmlgit

spring cloud 爲開發人員提供了快速構建分佈式系統的一些工具,包括配置管理、服務發現、斷路器、路由、微代理、事件總線、全局鎖、決策競選、分佈式會話等等。它運行環境簡單,能夠在開發人員的電腦上跑。另外說明spring cloud是基於springboot的,因此須要開發中對springboot有必定的瞭解,若是不瞭解的話能夠看這篇文章:2小時學會springboot。另外對於「微服務架構」 不瞭解的話,能夠經過搜索引擎搜索「微服務架構」瞭解下。github

2、建立服務註冊中心

在這裏,我仍是採用Eureka做爲服務註冊與發現的組件,至於Consul 以後會出文章詳細介紹。web

2.1 首先建立一個maven主工程。spring

首先建立一個主Maven工程,在其pom文件引入依賴,spring Boot版本爲2.0.3.RELEASE,Spring Cloud版本爲Finchley.RELEASE。這個pom文件做爲父pom文件,起到依賴版本控制的做用,其餘module工程繼承該pom。這一系列文章所有采用這種模式,其餘文章的pom跟這個pom同樣。再次說明一下,之後再也不重複引入。代碼以下:sql

<?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></modelVersion>   4.0.0
 
<groupId></groupId>   com.forezp
<artifactId></artifactId>   sc-f-chapter1
<version></version>   0.0.1-SNAPSHOT
<packaging></packaging>   pom
 
<name></name>   sc-f-chapter1
<description></description>   Demo project for Spring Boot
 
<parent>   
<groupId></groupId>       org.springframework.boot
<artifactId></artifactId>       spring-boot-starter-parent
<version></version>       2.0.3.RELEASE
<relativePath/>       
</parent>   
 
<modules>   
<module></module>       eureka-server
<module></module>       service-hi
</modules>   
 
<properties>   
<project.build.sourceEncoding></project.build.sourceEncoding>       UTF-8
<project.reporting.outputEncoding></project.reporting.outputEncoding>       UTF-8
<java.version></java.version>       1.8
<spring-cloud.version></spring-cloud.version>       Finchley.RELEASE
</properties>   
 
<dependencies>   
<dependency>       
<groupId></groupId>           org.springframework.boot
<artifactId></artifactId>           spring-boot-starter-test
<scope></scope>           test
</dependency>       
</dependencies>   
 
<dependencyManagement>   
<dependencies>       
<dependency>           
<groupId></groupId>               org.springframework.cloud
<artifactId></artifactId>               spring-cloud-dependencies
<version></version>               ${spring-cloud.version}
<type></type>               pom
<scope></scope>               import
</dependency>           
</dependencies>       
</dependencyManagement>   
 
<build>   
<plugins>       
<plugin>           
<groupId></groupId>               org.springframework.boot
<artifactId></artifactId>               spring-boot-maven-plugin
</plugin>           
</plugins>       
</build>   
 
</project>
 

2.2 而後建立2model工程:一個model工程做爲服務註冊中心,即Eureka Server,另外一個做爲Eureka Client。apache

下面以建立server爲例子,詳細說明建立過程:bootstrap

右鍵工程->建立model-> 選擇spring initialir 以下圖:後端

 

下一步->選擇cloud discovery->eureka server ,而後一直下一步就好了。

 

建立完後的工程,其pom.xml繼承了父pom文件,並引入spring-cloud-starter-netflix-eureka-server的依賴,代碼以下:

<?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></modelVersion>   4.0.0
 
<groupId></groupId>   com.forezp
<artifactId></artifactId>   eureka-server
<version></version>   0.0.1-SNAPSHOT
<packaging></packaging>   jar
 
<name></name>   eureka-server
<description></description>   Demo project for Spring Boot
 
<parent>   
<groupId></groupId>       com.forezp
<artifactId></artifactId>       sc-f-chapter1
<version></version>       0.0.1-SNAPSHOT
</parent>   
 
<dependencies>   
<dependency>       
<groupId></groupId>           org.springframework.cloud
<artifactId></artifactId>           spring-cloud-starter-netflix-eureka-server
</dependency>       
</dependencies>   
 
</project>

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

 
@SpringBootApplication
@EnableEurekaServer
publicclass EurekaServerApplication {
 
publicstaticvoidmain   (String[] args) {
        SpringApplication.run( EurekaServerApplication.class, args );
    }
}
 

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

server:
8761  port:
 
eureka:
  instance:
    hostname: localhost
client :
false    registerWithEureka:
false    fetchRegistry:
    serviceUrl:
//${eureka.instance.hostname}:${server.port}/eureka/      defaultZone: http:
 
spring:
  application:
server    name: eurka-

經過eureka.client.registerWithEureka:false和fetchRegistry:false來代表本身是一個eureka server.

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

 

No application available 沒有服務被發現 ……^_^ 
由於沒有註冊服務固然不可能有服務被發現了。

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

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

建立過程同server相似,建立完pom.xml以下:

<?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></modelVersion>   4.0.0
 
<groupId></groupId>   com.forezp
<artifactId></artifactId>   service-hi
<version></version>   0.0.1-SNAPSHOT
<packaging></packaging>   jar
 
<name></name>   service-hi
<description></description>   Demo project for Spring Boot
 
<parent>   
<groupId></groupId>       com.forezp
<artifactId></artifactId>       sc-f-chapter1
<version></version>       0.0.1-SNAPSHOT
</parent>   
 
<dependencies>   
<dependency>       
<groupId></groupId>           org.springframework.cloud
<artifactId></artifactId>           spring-cloud-starter-netflix-eureka-client
</dependency>       
<dependency>       
<groupId></groupId>           org.springframework.boot
<artifactId></artifactId>           spring-boot-starter-web
</dependency>       
</dependencies>   
 
<build>   
<plugins>       
<plugin>           
<groupId></groupId>               org.springframework.boot
<artifactId></artifactId>               spring-boot-maven-plugin
</plugin>           
</plugins>       
</build>   
 
 
</project>
 

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

@SpringBootApplication
@EnableEurekaClient
@RestController
publicclass ServiceHiApplication {
 
publicstaticvoidmain   (String[] args) {
        SpringApplication.run( ServiceHiApplication.class, args );
    }
 
@Value"${server.port}"   ()
    String port;
 
@RequestMapping"/hi"   ()
publichomeRequestParam"name""forezp"   String(@(value =, defaultValue =) String name) {
return"hi "" ,i am from port:"       + name ++ port;
    }
 
}
 
 

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

server:
8762  port:
 
spring:
  application:
    name: service-hi
 
eureka:
client :
    serviceUrl:
//localhost:8761/eureka/      defaultZone: http:
 
·        1
·        2
·        3
·        4
·        5
·        6
·        7
·        8
·        9
·        10
·        11
·        12
·        13

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

 

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

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

hi forezp,i am from port:8762

第二篇: 服務消費者(rest+ribbon)(Finchley版本)

在上一篇文章,講了服務的註冊和發現。在微服務架構中,業務都會被拆分紅一個獨立的服務,服務與服務的通信是基於http restful的。Spring cloud有兩種服務調用方式,一種是ribbon+restTemplate,另外一種是feign。在這一篇文章首先講解下基於ribbon+rest。

1、ribbon簡介

Ribbon is a client side load balancer which gives you a lot of control over the behaviour of HTTP and TCP clients. Feign already uses Ribbon, so if you are using @FeignClient then this section also applies.

—–摘自官網

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個實例,這就至關於一個小的集羣。

如何在idea下啓動多個實例,請參照這篇文章: 
https://blog.csdn.net/forezp/article/details/76408139

訪問localhost:8761如圖所示: 
如何一個工程啓動多個實例,請看這篇文章:https://blog.csdn.net/forezp/article/details/76408139

 

3、建一個服務消費者

從新新建一個spring-boot工程,取名爲:service-ribbon; 
在它的pom.xml繼承了父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></modelVersion>   4.0.0
 
<groupId></groupId>   com.forezp
<artifactId></artifactId>   service-ribbon
<version></version>   0.0.1-SNAPSHOT
<packaging></packaging>   jar
 
<name></name>   service-ribbon
<description></description>   Demo project for Spring Boot
 
 
<parent>   
<groupId></groupId>       com.forezp
<artifactId></artifactId>       sc-f-chapter2
<version></version>       0.0.1-SNAPSHOT
</parent>   
 
<dependencies>   
<dependency>       
<groupId></groupId>           org.springframework.cloud
<artifactId></artifactId>           spring-cloud-starter-netflix-eureka-client
</dependency>       
<dependency>       
<groupId></groupId>           org.springframework.boot
<artifactId></artifactId>           spring-boot-starter-web
</dependency>       
<dependency>       
<groupId></groupId>           org.springframework.cloud
<artifactId></artifactId>           spring-cloud-starter-netflix-ribbon
</dependency>       
</dependencies>   
</project>

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

eureka:
client :
    serviceUrl:
//localhost:8761/eureka/      defaultZone: http:
server:
8764  port:
spring:
  application:
    name: service-ribbon

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

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

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

@Service
publicclass HelloService {
 
@Autowired   
    RestTemplate restTemplate;
 
publichiService   String(String name) {
return"http://SERVICE-HI/hi?name="       restTemplate.getForObject(+name,String.class);
    }
 
 
}

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

 
@RestController
publicclass HelloControler {
 
@Autowired   
    HelloService helloService;
 
@GetMapping"/hi"   (value =)
publichi   String(@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

這說明當咱們經過調用restTemplate.getForObject(「http://SERVICE-HI/hi?name=「+name,String.class)方法時,已經作了負載均衡,訪問了不一樣的端口的服務實例。

4、此時的架構

 

  • 一個服務註冊中心,eureka server,端口爲8761
  • service-hi工程跑了兩個實例,端口分別爲8762,8763,分別向服務註冊中心註冊
  • sercvice-ribbon端口爲8764,向服務註冊中心註冊
  • 當sercvice-ribbon經過restTemplate調用service-hi的hi接口時,由於用ribbon進行了負載均衡,會輪流的調用service-hi:8762和8763 兩個端口的hi接口;

第三篇: 服務消費者(Feign)(Finchley版本)

上一篇文章,講述瞭如何經過RestTemplate+Ribbon去消費服務,這篇文章主要講述如何經過Feign去消費服務。

1、Feign簡介

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

簡而言之:

  • Feign 採用的是基於接口的註解
  • Feign 整合了ribbon,具備負載均衡的能力
  • 整合了Hystrix,具備熔斷的能力

2、準備工做

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

3、建立一個feign的服務

新建一個spring-boot工程,取名爲serice-feign,在它的pom文件引入Feign的起步依賴spring-cloud-starter-feign、Eureka的起步依賴spring-cloud-starter-netflix-eureka-client、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></modelVersion>   4.0.0
 
<groupId></groupId>   com.forezp
<artifactId></artifactId>   service-feign
<version></version>   0.0.1-SNAPSHOT
<packaging></packaging>   jar
 
<name></name>   service-feign
<description></description>   Demo project for Spring Boot
 
 
<parent>   
<groupId></groupId>       com.forezp
<artifactId></artifactId>       sc-f-chapter3
<version></version>       0.0.1-SNAPSHOT
</parent>   
 
<dependencies>   
<dependency>       
<groupId></groupId>           org.springframework.cloud
<artifactId></artifactId>           spring-cloud-starter-netflix-eureka-client
</dependency>       
<dependency>       
<groupId></groupId>           org.springframework.boot
<artifactId></artifactId>           spring-boot-starter-web
</dependency>       
<dependency>       
<groupId></groupId>           org.springframework.cloud
<artifactId></artifactId>           spring-cloud-starter-openfeign
</dependency>       
</dependencies>   
 
</project>   

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

eureka:
client :
    serviceUrl:
//localhost:8761/eureka/      defaultZone: http:
server:
8765  port:
spring:
  application:
    name: service-feign

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

@SpringBootApplication
@EnableEurekaClient
@EnableDiscoveryClient
@EnableFeignClients
publicclass ServiceFeignApplication {
 
publicstaticvoidmain   (String[] args) {
        SpringApplication.run( ServiceFeignApplication.class, args );
    }
}
 
 
·        1
·        2
·        3
·        4
·        5
·        6
·        7
·        8
·        9
·        10
·        11
·        12
·        13

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

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

在Web層的controller層,對外暴露一個」/hi」的API接口,經過上面定義的Feign客戶端SchedualServiceHi 來消費服務。代碼以下:

@RestController
publicclass HiController {
 
 
//編譯器報錯,無視。 由於這個Bean是在程序啓動的時候注入的,編譯器感知不到,因此報錯。   
@Autowired   
    SchedualServiceHi schedualServiceHi;
 
@GetMapping"/hi"   (value =)
publicsayHi   String(@RequestParam String name) {
return       schedualServiceHi.sayHiFromClientOne( name );
    }
}
 

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

hi forezp,i am from port:8762

hi forezp,i am from port:8763

 

第四篇:斷路器(Hystrix)(Finchley版本)

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

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

1、斷路器簡介

Netflix has created a library called Hystrix that implements the circuit breaker pattern. In a microservice architecture it is common to have multiple layers of service calls.

. —-摘自官網

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

 

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

 

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

2、準備工做

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

3、在ribbon使用斷路器

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

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

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

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

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

@Service
publicclass HelloService {
 
@Autowired   
    RestTemplate restTemplate;
 
@HystrixCommand"hiError"   (fallbackMethod =)
publichiService   String(String name) {
return"http://SERVICE-HI/hi?name="       restTemplate.getForObject(+name,String.class);
    }
 
publichiError   String(String name) {
return"hi,"",sorry,error!"       +name+;
    }
 
}
·         

啓動: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

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

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

第五篇: 路由網關(zuul)(Finchley版本)

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

 
注意: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文件以下:

<?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></modelVersion>   4.0.0
 
<groupId></groupId>   com.forezp
<artifactId></artifactId>   service-zuul
<version></version>   0.0.1-SNAPSHOT
<packaging></packaging>   jar
 
<name></name>   service-zuul
<description></description>   Demo project for Spring Boot
 
<parent>   
<groupId></groupId>       com.forezp
<artifactId></artifactId>       sc-f-chapter5
<version></version>       0.0.1-SNAPSHOT
</parent>   
 
<dependencies>   
<dependency>       
<groupId></groupId>           org.springframework.cloud
<artifactId></artifactId>           spring-cloud-starter-netflix-eureka-client
</dependency>       
<dependency>       
<groupId></groupId>           org.springframework.boot
<artifactId></artifactId>           spring-boot-starter-web
</dependency>       
<dependency>       
<groupId></groupId>           org.springframework.cloud
<artifactId></artifactId>           spring-cloud-starter-netflix-zuul
</dependency>       
</dependencies>   
</project>
 

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

@SpringBootApplication
@EnableZuulProxy
@EnableEurekaClient
@EnableDiscoveryClient
publicclass ServiceZuulApplication {
 
publicstaticvoidmain   (String[] args) {
        SpringApplication.run( ServiceZuulApplication.class, args );
    }
}
 

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

eureka:
  client:
    serviceUrl:
8761      defaultZone: http://localhost:/eureka/
server:
8769  port:
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不只只是路由,而且還能過濾,作一些安全驗證。繼續改造工程;

@Component
publicclass MyFilter extends ZuulFilter {
 
privatestatic   Logger log = LoggerFactory.getLogger(MyFilter.class);
@Override   
publicfilterType   String() {
return"pre"       ;
    }
 
@Override   
publicintfilterOrder   () {
return0       ;
    }
 
@Override   
publicbooleanshouldFilter   () {
returntrue       ;
    }
 
@Override   
publicrun   Object() {
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();
"%s >>> %s"        log.info(String.format(, request.getMethod(), request.getRequestURL().toString()));
"token"        Object accessToken = request.getParameter();
ifnull       (accessToken ==) {
"token is empty"            log.warn();
false            ctx.setSendZuulResponse();
401            ctx.setResponseStatusCode();
try           {
"token is empty"                ctx.getResponse().getWriter().write();
catch            }(Exception e){}
 
returnnull           ;
        }
"ok"        log.info();
returnnull       ;
    }
}
  • 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

 

第六篇: 分佈式配置中心(Spring Cloud Config)(Finchley版本)

在上一篇文章講述zuul的時候,已經提到過,使用配置服務來保存各個服務的配置文件。它就是Spring Cloud Config。

1、簡介

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

2、構建Config Server

父maven工程省略,父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></modelVersion>   4.0.0
 
<groupId></groupId>   com.forezp
<artifactId></artifactId>   sc-f-chapter6
<version></version>   0.0.1-SNAPSHOT
<packaging></packaging>   pom
 
<modules>   
<module></module>       config-server
<module></module>       config-client
</modules>   
 
<name></name>   sc-f-chapter6
<description></description>   Demo project for Spring Boot
 
<parent>   
<groupId></groupId>       org.springframework.boot
<artifactId></artifactId>       spring-boot-starter-parent
<version></version>       2.0.3.RELEASE
<relativePath/>       
</parent>   
 
 
<properties>   
<project.build.sourceEncoding></project.build.sourceEncoding>       UTF-8
<project.reporting.outputEncoding></project.reporting.outputEncoding>       UTF-8
<java.version></java.version>       1.8
<spring-cloud.version></spring-cloud.version>       Finchley.RELEASE
</properties>   
 
<dependencies>   
<dependency>       
<groupId></groupId>           org.springframework.boot
<artifactId></artifactId>           spring-boot-starter-test
<scope></scope>           test
</dependency>       
</dependencies>   
 
<dependencyManagement>   
<dependencies>       
<dependency>           
<groupId></groupId>               org.springframework.cloud
<artifactId></artifactId>               spring-cloud-dependencies
<version></version>               ${spring-cloud.version}
<type></type>               pom
<scope></scope>               import
</dependency>           
</dependencies>       
</dependencyManagement>   
 
<build>   
<plugins>       
<plugin>           
<groupId></groupId>               org.springframework.boot
<artifactId></artifactId>               spring-boot-maven-plugin
</plugin>           
</plugins>       
</build>   
 
 
</project>

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

<?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></modelVersion>   4.0.0
 
<groupId></groupId>   com.forezp
<artifactId></artifactId>   config-server
<version></version>   0.0.1-SNAPSHOT
<packaging></packaging>   jar
 
<name></name>   config-server
<description></description>   Demo project for Spring Boot
 
<parent>   
<groupId></groupId>       com.forezp
<artifactId></artifactId>       sc-f-chapter6
<version></version>       0.0.1-SNAPSHOT
</parent>   
 
<dependencies>   
<dependency>       
<groupId></groupId>           org.springframework.boot
<artifactId></artifactId>           spring-boot-starter-web
</dependency>       
<dependency>       
<groupId></groupId>           org.springframework.cloud
<artifactId></artifactId>           spring-cloud-config-server
</dependency>       
</dependencies>   
<build>   
<plugins>       
<plugin>           
<groupId></groupId>               org.springframework.boot
<artifactId></artifactId>               spring-boot-maven-plugin
</plugin>           
</plugins>       
</build>   
 
 
</project>

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

 
@SpringBootApplication
@EnableConfigServer
publicclass ConfigServerApplication {
 
publicstaticvoidmain   (String[] args) {
        SpringApplication.run(ConfigServerApplication.class, args);
    }
}
 

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

.application.namespring=config-server
.port8888server=
 
.cloud.config.server.git.uri.comspring=https://github/forezp/SpringcloudConfig/
.cloud.config.server.git.searchPathsspring=respo
.cloud.config.labelspring=master
.cloud.config.server.git.usernamespring=
.cloud.config.server.git.passwordspring=
 
 
  • 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文件:

<?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></modelVersion>   4.0.0
 
<groupId></groupId>   com.forezp
<artifactId></artifactId>   config-client
<version></version>   0.0.1-SNAPSHOT
<packaging></packaging>   jar
 
<name></name>   config-client
<description></description>   Demo project for Spring Boot
 
<parent>   
<groupId></groupId>       com.forezp
<artifactId></artifactId>       sc-f-chapter6
<version></version>       0.0.1-SNAPSHOT
</parent>   
 
<dependencies>   
<dependency>       
<groupId></groupId>           org.springframework.boot
<artifactId></artifactId>           spring-boot-starter-web
</dependency>       
<dependency>       
<groupId></groupId>           org.springframework.cloud
<artifactId></artifactId>           spring-cloud-starter-config
</dependency>       
</dependencies>   
 
<build>   
<plugins>       
<plugin>           
<groupId></groupId>               org.springframework.boot
<artifactId></artifactId>               spring-boot-maven-plugin
</plugin>           
</plugins>       
</build>   
 
 
</project>

其配置文件bootstrap.properties

.application.namespring=config-client
.cloud.config.labelspring=master
.cloud.config.profilespring=dev
.cloud.config.uri8888spring= http://localhost:/
.port8881server=
  • spring.cloud.config.label 指明遠程倉庫的分支
  • spring.cloud.config.profile
    • dev開發環境配置文件
    • test測試環境
    • pro正式環境
  • spring.cloud.config.uri= http://localhost:8888/ 指明配置服務中心的網址。

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

@SpringBootApplication
@RestController
publicclass ConfigClientApplication {
 
publicstaticvoidmain   (String[] args) {
        SpringApplication.run(ConfigClientApplication.class, args);
    }
 
@Value"${foo}"   ()
    String foo;
@RequestMapping"/hi"   (value =)
publichi   String(){
return       foo;
    }
}
 

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

foo version 3

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

 

 

第七篇: 高可用的分佈式配置中心(Spring Cloud Config)(Finchley版本)

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

 

1、準備工做

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

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

<?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></modelVersion>   4.0.0
 
<groupId></groupId>   com.forezp
<artifactId></artifactId>   config-server
<version></version>   0.0.1-SNAPSHOT
<packaging></packaging>   jar
 
<name></name>   config-server
<description></description>   Demo project for Spring Boot
 
<parent>   
<groupId></groupId>       com.forezp
<artifactId></artifactId>       sc-f-chapter7
<version></version>       0.0.1-SNAPSHOT
</parent>   
 
<dependencies>   
<dependency>       
<groupId></groupId>           org.springframework.cloud
<artifactId></artifactId>           spring-cloud-starter-netflix-eureka-client
</dependency>       
<dependency>       
<groupId></groupId>           org.springframework.boot
<artifactId></artifactId>           spring-boot-starter-web
</dependency>       
<dependency>       
<groupId></groupId>           org.springframework.cloud
<artifactId></artifactId>           spring-cloud-config-server
</dependency>       
 
</dependencies>   
<build>   
<plugins>       
<plugin>           
<groupId></groupId>               org.springframework.boot
<artifactId></artifactId>               spring-boot-maven-plugin
</plugin>           
</plugins>       
</build>   
 
 
 
</project>
 

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

server:
8889  port:
 
eureka:
  instance:
    hostname: localhost
client :
false    registerWithEureka:
false    fetchRegistry:
    serviceUrl:
//${eureka.instance.hostname}:${server.port}/eureka/      defaultZone: http:

入口類:

@EnableEurekaServer
@SpringBootApplication
publicclass EurekaServerApplication {
 
publicstaticvoidmain   (String[] args) {
        SpringApplication.run(EurekaServerApplication.class, args);
    }
}
 

2、改造config-server

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

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

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

.application.namespring=config-server
.port8888server=
 
.cloud.config.server.git.uri.comspring=https://github/forezp/SpringcloudConfig/
.cloud.config.server.git.searchPathsspring=respo
.cloud.config.labelspring=master
.cloud.config.server.git.usernamespring= your username
.cloud.config.server.git.passwordspring= your password
.client.serviceUrl.defaultZone8889eureka=http://localhost:/eureka/

最後須要在程序的啓動類Application加上@EnableEureka的註解。

3、改造config-client

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

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

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

.application.namespring=config-client
.cloud.config.labelspring=master
.cloud.config.profilespring=dev
#spring.cloud.config.uri= http://localhost:8888/
 
.client.serviceUrl.defaultZone8889eureka=http://localhost:/eureka/
.cloud.config.discovery.enabledspring=true
.cloud.config.discovery.serviceIdspring=config-server
.port8881server=
 
  • 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

第八篇: 消息總線(Spring Cloud Bus)(Finchley版本)

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

1、準備工做

本文仍是基於上一篇文章來實現。按照官方文檔,咱們只須要在配置文件中配置 spring-cloud-starter-bus-amqp ;這就是說咱們須要裝rabbitMq,點擊rabbitmq下載。至於怎麼使用 rabbitmq,搜索引擎下。

2、改造config-client

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

<dependencies>
<dependency>       
<groupId></groupId>           org.springframework.cloud
<artifactId></artifactId>           spring-cloud-starter-config
</dependency>       
 
<dependency>       
<groupId></groupId>           org.springframework.boot
<artifactId></artifactId>           spring-boot-starter-web
</dependency>       
 
<dependency>       
<groupId></groupId>           org.springframework.cloud
<artifactId></artifactId>           spring-cloud-starter-netflix-eureka-client
</dependency>       
 
<dependency>       
<groupId></groupId>           org.springframework.cloud
<artifactId></artifactId>           spring-cloud-starter-bus-amqp
</dependency>       
 
<dependency>       
<groupId></groupId>           org.springframework.boot
<artifactId></artifactId>           spring-boot-starter-actuator
</dependency>       
 

在配置文件application.properties中加上RabbitMq的配置,包括RabbitMq的地址、端口,用戶名、密碼。並須要加上spring.cloud.bus的三個配置,具體以下:

 
.rabbitmq.hostspring=localhost
.rabbitmq.port5672spring=
.rabbitmq.usernamespring=guest
.rabbitmq.passwordspring=guest
 
.cloud.bus.enabledspring=true
.cloud.bus.trace.enabledspring=true
.endpoints.web.exposure.includemanagement=bus-refresh
 

ConfigClientApplication啓動類代碼以下:

@SpringBootApplication
@EnableEurekaClient
@EnableDiscoveryClient
@RestController
@RefreshScope
publicclass ConfigClientApplication {
 
/**   
     * http://localhost:8881/actuator/bus-refresh
     */
 
publicstaticvoidmain   (String[] args) {
        SpringApplication.run(ConfigClientApplication.class, args);
    }
 
@Value"${foo}"   ()
    String foo;
 
@RequestMapping"/hi"   (value =)
publichi   String(){
return       foo;
    }
}
 

依次啓動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/actuator/bus-refresh,你會發現config-client會從新讀取配置文件。若是是spring boot 2.0如下的版本,則調用http://localhost:8881/bus/refresh刷新。

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

foo version 4

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

3、分析

此時的架構圖: 

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

 

第九篇: 服務鏈路追蹤(Spring Cloud Sleuth)(Finchley版本)

這篇文章主要講述服務追蹤組件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 Cloud爲F版本的時候,已經不須要本身構建Zipkin Server了,只須要下載jar便可,下載地址:

https://dl.bintray.com/openzipkin/maven/io/zipkin/java/zipkin-server/

也能夠在這裏下載:

連接: https://pan.baidu.com/s/1w614Z8gJXHtqLUB6dKWOpQ 密碼: 26pf

下載完成jar 包以後,須要運行jar,以下:

java -jar zipkin-server-2.10.1-exec.jar

訪問瀏覽器localhost:9494

4.2 建立service-hi

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

<?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></modelVersion>   4.0.0
 
<groupId></groupId>   com.forezp
<artifactId></artifactId>   service-zipkin
<version></version>   0.0.1-SNAPSHOT
<packaging></packaging>   jar
 
<name></name>   service-hi
<description></description>   Demo project for Spring Boot
 
<parent>   
<groupId></groupId>       com.forezp
<artifactId></artifactId>       sc-f-chapter9
<version></version>       0.0.1-SNAPSHOT
</parent>   
 
 
 
<dependencies>   
 
<dependency>       
<groupId></groupId>           org.springframework.boot
<artifactId></artifactId>           spring-boot-starter-web
</dependency>       
 
<dependency>       
<groupId></groupId>           org.springframework.cloud
<artifactId></artifactId>           spring-cloud-starter-zipkin
</dependency>       
 
 
 
</dependencies>   
 
<build>   
<plugins>       
<plugin>           
<groupId></groupId>               org.springframework.boot
<artifactId></artifactId>               spring-boot-maven-plugin
</plugin>           
</plugins>       
</build>   
 
</project>

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

 
 
server.port=8988
spring.zipkin.base-url=http://localhost:9411
spring.application.name=service-hi

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

對外暴露接口:

com.forezp;package
 
.sampler.Sampler;import brave
.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
.util.logging.Level;import java
.util.logging.Logger;import java
 
@SpringBootApplication
@RestController
public class ServiceHiApplication {
 
    public static void main(String[] args) {
.run.class;        SpringApplication(ServiceHiApplication, args)
    }
 
.getLogger.class.getName;    private static final Logger LOG = Logger(ServiceHiApplication())
 
 
    @Autowired
;    private RestTemplate restTemplate
 
    @Bean
    public RestTemplate getRestTemplate(){
;        return new RestTemplate()
    }
 
"/hi"    @RequestMapping()
    public String callHome(){
.log.INFO"calling trace service-hi  ";        LOG(Level,)
.getForObject"http://localhost:8989/miya".class;        return restTemplate(, String)
    }
"/info"    @RequestMapping()
    public String info(){
.log.INFO"calling trace service-hi ";        LOG(Level,)
 
"i'm service-hi";        return
 
    }
 
    @Bean
    public Sampler defaultSampler() {
.ALWAYS;        return Sampler_SAMPLE
    }
 
 
}
 

4.3 建立service-miya

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

對外暴露接口:

 
com.forezp;package
 
.sampler.Sampler;import brave
.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
 
.util.logging.Level;import java
.util.logging.Logger;import java
 
@SpringBootApplication
@RestController
public class ServiceMiyaApplication {
 
    public static void main(String[] args) {
.run.class;        SpringApplication(ServiceMiyaApplication, args)
    }
 
.getLogger.class.getName;    private static final Logger LOG = Logger(ServiceMiyaApplication())
 
 
"/hi"    @RequestMapping()
    public String home(){
.log.INFO"hi is being called";        LOG(Level,)
"hi i'm miya!";        return
    }
 
"/miya"    @RequestMapping()
    public String info(){
.log.INFO"info is being called";        LOG(Level,)
.getForObject"http://localhost:8988/info".class;        return restTemplate(,String)
    }
 
    @Autowired
;    private RestTemplate restTemplate
 
    @Bean
    public RestTemplate getRestTemplate(){
;        return new RestTemplate()
    }
 
 
    @Bean
    public Sampler defaultSampler() {
.ALWAYS;        return Sampler_SAMPLE
    }
}
·        2

4.4 啓動工程,演示追蹤

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

 

訪問:http://localhost:8989/miya,瀏覽器出現:

i’m service-hi

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

 

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

相關文章
相關標籤/搜索