說明:本文部分內容來自https://github.com/a982338665/Spring-Boot/blob/master
本文案例源碼:https://github.com/wind-free/spring-cloud/tree/master
一、搭建一個父級工程
1)File——>New——>Projcet...
2)選擇Spring Initializr,選擇對應的JDK,Choose Initializr Server URL 選擇 default——>Next
3).輸入項目組Group:com.xxx;組件名稱Artifact:xxxx;Type:選擇Maven Project;修改自動生成的Package——>Next
4)選擇你需要的Spring Boot版本,其他的先不選——>Next
5)Project Name工程名稱,和組件名稱Artifact一樣;Project location:設置項目文件存放目錄——>Finish
6)父級工程創建完成后刪除src文件夾
7)修改pom文件(打包方式一定要改成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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<!--申明此項目為springboot項目-->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>springcloud</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<name>springcloud</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
二、搭建eureka server(注冊中心)
服務注冊和發現模塊
1.euraka-server創建:
1)File—>New—>Module...
2)選擇Spring Initializr,選擇對應的JDK,Choose Initializr Server URL 選擇 default——>Next
3).輸入項目組Group:com.xxx;組件名稱Artifact:xxxx;Type:選擇Maven Project;修改自動生成的Package——>Next
4) Dpendencies選擇Spring Cloud Discovery—>Eureka Server,選擇你需要的Spring Boot版本——>Next
5)Project Name工程名稱一般不做修改,和組件名稱Artifact一樣;Content root、Module file location 均按自動生成,不做修改——>Finish
6)向EurekaServerApplication添加注解@EnableEurekaServer表明是一個eureka服務
7)將application.properties修改為application.yml(重命名快捷鍵Shift+F6),修改完成后加入以下配置:
server:
port: 8761 #指定該Eureka實例的端口
eureka:
instance:
hostname: localhost #設置當前實例的主機名稱
client:
registerWithEureka: false #禁止注冊自身
fetchRegistry: false #因為該服務沒有注冊到其他注冊中心,所以關閉從注冊中心拉取服務列表。
serviceUrl: #服務注冊中心地址
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
#eureka是一個高可用的組件,它沒有后端緩存,每一個實例注冊之后需要向注冊中心發送心跳(因此可以在內存中完成)
#通過eureka.client.registerWithEureka:false和fetchRegistry:false來表明自己是一個eureka server.
#
8)修改pom文件
使用父工程spring-cloud的spring boot依賴
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>pers.li</groupId>
<artifactId>eureka-server</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>eureka-server</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>pers.li</groupId>
<artifactId>boot-parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<spring-cloud.version>Finchley.RELEASE</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-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>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
</project>
9)打開http://localhost:8761,即eureka server的網址,可以看見注冊的服務
2.eureka-client=01創建同上
1)EurekaClient01Application中加入以下兩個注解
@EnableEurekaClient
@EnableEurekaClient
@RestController
@RestController
@SpringBootApplication @EnableEurekaClient @RestController public class EurekaClient01Application { public static void main(String[] args) { SpringApplication.run(EurekaClient01Application.class, args); } @Value("${server.port}") String port; @RequestMapping("/hi") public String home(@RequestParam String name) { return "hi "+name+",i am from port:" +port; } }
2)application.yml配置
eureka: client: serviceUrl: defaultZone: http://localhost:8761/eureka/
server: port: 8762 spring: application: # 此處名稱最好寫項目名稱,便於識別服務提供者 name: eureka-client-01
3)在啟動類里面隨便寫一個接口
@SpringBootApplication
@EnableEurekaClient
@RestController
public class EurekaClient01Application {
public static void main(String[] args) {
SpringApplication.run(EurekaClient01Application.class, args);
}
@Value("${server.port}")
String port;
@RequestMapping("/hi")
public String home(@RequestParam String name) {
return "hi "+name+",i am from port:" +port;
}
}
4)打開http://localhost:8762/hi?name=forezp,返回接口訪問內容(上一個eureka server服務不要關閉)
三、ribbon+restTemplate-服務消費者
1.在微服務架構中,業務都會被拆分成一個獨立的服務,服務與服務的通訊是基於http restful的。 Spring cloud有兩種服務調用方式,一種是ribbon+restTemplate,另一種是feign。
2.ribbon是一個負載均衡客戶端,可以很好的控制htt和tcp的一些行為。Feign默認集成了ribbon。
1)基於以上項目復制eureka-client-01創建eureka-client-02並修改yml中端口為8763並啟動
spring.application.name不修改,仍為eureka-client-01:
由於服務之間是根據此名稱進行相互調用,所以此時表
示
8763,8762對外提供一 個服務,服務名為eureka-client-01=====>等同於一個小的集群

2)創建一個服務消費者:service-ribbon(創建步驟和之前一樣這里就不截圖了)
1.創建步驟:
a.File—>New—>Module...
b.選擇Spring Initializr,選擇對應的JDK,Choose Initializr Server URL 選擇 default——>Next
c.輸入項目組Group:com.xxx;組件名稱Artifact:xxxx;Type:選擇Maven Project;修改自動生成的Package——>Next
d.Dpendencies選擇Spring Cloud Discovery—>Eureka Server,選擇你需要的Spring Boot版本——>Next
e.Project Name工程名稱一般不做修改,和組件名稱Artifact一樣;Content root、Module file location 均按自動生成,不做修改——>Finish
2.啟動類中添加注解和方法
a.@EnableDiscoveryClient
b.通過LoadBalanced注解表明這個restRemplate開啟負載均衡的功能
@SpringBootApplication @EnableDiscoveryClient public class ServiceRibbonApplication { public static void main(String[] args) { SpringApplication.run(ServiceRibbonApplication.class, args); } @Bean @LoadBalanced RestTemplate restTemplate() { return new RestTemplate(); } }
c.編寫測試類controller和service,主要調用是因為service中的RestTemplate
service-ribbon結構
HelloRibbonService
package com.example.serviceribbon.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
@Service
public class HelloRibbonService {
@Autowired
RestTemplate restTemplate;
public String hiService(String name) {
//使用注冊到Eureka服務中心的客戶端,由客戶端分配具體調用哪個服務
return restTemplate.getForObject("http://eureka-client-01/hi?name="+name,String.class);
}
}
HelloRibbonController
package com.example.serviceribbon.controller;
import com.example.serviceribbon.service.HelloRibbonService;
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 HelloRibbonController {
@Autowired
HelloRibbonService helloRibbonService;
@RequestMapping(value = "/hi")
public String hi(@RequestParam String name){
return helloRibbonService.hiService(name);
}
}
d.瀏覽器上多次訪問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")方法時,已經做了負載均衡,訪問了不同端口的服務實例。
場景總結:
1.一個服務注冊中心,eureka-server端口為8761
2.向服務注冊中心eureka-server注冊兩個客戶端服務:名稱為eureka-client-01包含服務:8762/8763
3.向服務之策中心eureka-server注冊消費者服務:service-ribbon端口:8764
4.當service-ribbon通過restTemplate調用eureka-client-01的hi接口時,因為用了ribbon負載均衡,會輪流的調用eureka-client-01:8762和8763兩個端口的hi接口;
四、Feign-服務消費者
1.Feign是一個聲明式的偽Http客戶端,它使得寫Http客戶端變得更簡單。
Feign是一個聲明式的偽Http客戶端,它使得寫Http客戶端變得更簡單。
使用Feign,只需要創建一個接口並注解。它具有可插拔的注解特性,可使用Feign 注解和JAX-RS注解。
使用Feign,只需要創建一個接口並注解。它具有可插拔的注解特性,可使用Feign 注解和JAX-RS注解。
Feign支持可插拔的編碼器和解碼器。Feign默認集成了Ribbon,並和Eureka結合,默認實現了負載均衡的效果
Feign支持可插拔的編碼器和解碼器。Feign默認集成了Ribbon,並和Eureka結合,默認實現了負載均衡的效果
2.簡單理解:
2.簡單理解:
·Feign 采用的是基於接口的注解
·Feign 采用的是基於接口的注解
·Feign 整合了ribbon
·Feign 整合了ribbon
1)創建一個服務消費者service-feign
a.application.yml指定文件程序名為service-feign,端口號為8765
b.pom文件中加入feign依賴入
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>service-feign</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>service-feign</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>com.example</groupId>
<artifactId>spring-cloud</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<spring-cloud.version>Hoxton.SR1</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
</dependency>
<!--高版本feign依賴============================-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</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>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
</project>
c.啟動類中加入@EnableFeignClients注解開啟Feign的功能(@EnableDiscoveryClient和@EnableFeignClients)
package com.example.servicefeign;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class ServiceFeignApplication {
public static void main(String[] args) {
SpringApplication.run(ServiceFeignApplication.class, args);
}
}
d.編寫測試類service
和controller,feign基於接口——創建serviceTest
HelloFeignService
package com.example.servicefeign.service;
import com.example.servicefeign.service.impl.HelloFeignServiceImpl;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
@FeignClient(value = "eureka-client-01", fallback = HelloFeignServiceImpl.class)
public interface HelloFeignService {
@GetMapping(value = "/hi")
String sayHiFromClientOne(@RequestParam (value = "name") String name);
}
HelloFeignServiceImpl
package com.example.servicefeign.service.impl;
import com.example.servicefeign.service.HelloFeignService;
public class HelloFeignServiceImpl implements HelloFeignService {
@Override
public String sayHiFromClientOne(String name) {
return "hello"+name;
}
}
HelloFeignController
package com.example.servicefeign.controller;
import com.example.servicefeign.service.HelloFeignService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloFeignController {
@Autowired
private HelloFeignService helloFeignService;
@GetMapping(value = "hi")
public String sayHi(@RequestParam String name){
return helloFeignService.sayHiFromClientOne(name);
}
}
e.瀏覽器上多次訪問http://localhost:8765/hi?name=Feign,瀏覽器交替顯示:“hi ,i am from port:8762”,“hi Feign,i am from port:8763”;
五、斷路器(Hystrix)
1.微服務架構中,根據業務分析來拆分一個個的服務,服務與服務之間可以相互調用(RPC)在Spring Cloud可以用RestTemplate+Ribbon和Feign來調用。為了保證其高可用,單個服務通常會集群部署。由於網絡原因或者自身的原因,服務並不能保證100%可用,如果單個服務出現問題,調用這個服務就會出現線程阻塞,此時若有大量的請求涌入,Servlet容器的線程資源會被消耗完畢,導致服務癱瘓。服務與服務之間的依賴性,故障會傳播,會對整個微服務系統造成災難性的嚴重后果,這就是服務故障的“雪崩”效應。為了解決這個問題,業界提出了斷路器模型。
2.Netflix開源了Hystrix組件,實現了斷路模式,SpringCloud對這一組件進行了整合。
在微服務架構中,一個請求需要調用多個服務是非常常見的,叫底層的服務如果出現故障,會導致連鎖故障。當對特定的服務的調用的不可用達到一個閾值(Hystrix是5秒20次斷路器將會被打開。斷路打開后,可用避免連鎖故障,fallback方法可以直接返回一個固定值)。
3.Ribbon使用斷路器:
1)添加斷路器依賴:spring-cloud-starter-hystrix如果springboot是2.0及以上的新版本還需要加入一個依賴

2)啟動類加注解@EnableHystrix開啟Hystrix(@EnableDiscoveryClient和@EnableHystrix)

3)改造HelloRibbonService類,在hiService方法上加上@HystrixCommand注解
注意: 該注解對該方法創建了熔斷器的功能,並指定了fallbackMethod熔斷方法, 熔斷方法直接返回了一個字符串,字符串為“hi,”+name+“,sorry,error!”,
package com.example.serviceribbon.service; import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.web.client.RestTemplate; @Service public class HelloRibbonService { @Autowired RestTemplate restTemplate; @HystrixCommand(fallbackMethod="hiError") public String hiService(String name) { //使用注冊到Eureka服務中心的客戶端,由客戶端分配具體調用哪個服務
return restTemplate.getForObject("http://eureka-client-01/hi?name="+name,String.class); } public String hiError(String name){ return "hi" + name +"sorry,error!"; } }
4)斷路測試: ·啟動ribben訪問 ·關閉eureka-client-01,再訪問,會得到短路由返回值 ·eureka-client-01工程不可用的時候,service-ribbon調用 service-hi的API接口時, 會執行快速失敗,直接返回一組字符串,而不是等待響應超時,這很好的控制了容器的線程阻塞
4.Feign中使用斷路器:
4.Feign中使用斷路器:
1)
Feign是自帶斷路器的,在D版本的Spring Cloud中,它沒有默認打開。需要在配置文件中配置打開:feign.hystrix.enabled=true

2)在@FeignClient接口的注解中加上fallback的指定類HelloFeignServiceImpl
在@FeignClient接口的注解中加上fallback的指定類HelloFeignServiceImpl

3)HelloFeignServiceImpl
需要實現HelloFeignService接口,並注入到Ioc容器中(組件注解)
HelloFeignServiceImpl
需要實現HelloFeignService接口,並注入到Ioc容器中(組件注解) 4)斷路測試-同上
1.
Hystrix Dashboard (斷路器:Hystrix 儀表盤):
--儀表盤添加+ribbon和feign相同
--以ribbon為例:
1)添加依賴
<!--添加斷路器-儀表盤依賴==========-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
2)主程序啟動類中:
·加入@EnableHystrixDashboard注解,開啟hystrixDashboard
·在spring版本2.0以上需要注入一個servlet(啟動類中)
//儀表盤注解
@EnableHystrixDashboard
3)訪問http://localhost:8764/hystrix
·第一個文本框輸入http://localhost:8764/hystrix.stream

4)點擊
monitor stream,進入下一個界面
·顯示加載中load....
5)
訪問:http://localhost:8764/hi?name=forezp,查看監控界面

六、路由網關-zuul
1.在Spring Cloud微服務系統中,一種常見的負載均衡方式是:
1.在Spring Cloud微服務系統中,一種常見的負載均衡方式是:
1)客戶端請求-->負載均衡(zuul、Ngnix)-->
2)服務網關(zuul集群)-->具體的服務器 -->
3)服務統一注冊到高可用的服務注冊中心集群
4)服務的所有的配置文件由配置服務管理, 配置服務的配置文件放在git倉庫,方便開發人員隨時改配置
2.Zuul的主要功能是路由轉發和過濾器。路由功能是微服務的一部分, 比如/api/user轉發到到user服務,/api/shop轉發到到shop服務。 zuul默認和Ribbon結合實現了負載均衡的功能
3.創建service-zuul工程:
1)pom依賴:spring-cloud-starter-netflix-zuul
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
2)applicaton類
·加上注解@EnableZuulProxy,開啟zuul的功能
·加上注解@EnableEurekaClient,注冊進eureka服務
3)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 服務
4)測試:
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
4.zuul不僅只是路由,並且還能過濾,做一些安全驗證,詳見filter
package com.example.servicezuul.filter;
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 Filter extends ZuulFilter {
private static Logger log = LoggerFactory.getLogger(Filter.class);
/**
* filterType:返回一個字符串代表過濾器的類型:
* 在zuul中定義了四種不同生命周期的過濾器類型-
* pre:路由之前
* routing:路由之時
* post: 路由之后
* error:發送錯誤調用
* @return
*/
@Override
public String filterType() {
return "pre";
}
/**
* filterOrder:過濾的順序
* @return
*/
@Override
public int filterOrder() {
return 0;
}
/**
* shouldFilter:這里可以寫邏輯判斷,是否要過濾,本文true,永遠過濾
* @return
*/
@Override
public boolean shouldFilter() {
return true;
}
/**
* run:過濾器的具體邏輯。可用很復雜,包括查sql,nosql去判斷該請求到底有沒有權限訪問
* @return
*/
@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;
}
}
5.測試filter:
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)
1.在分布式系統中,由於服務數量居多,為了方便服務配置文件統一管理,實時更新,所以需要分布式配置中心組件。在Spring Cloud中,有分布式配置中心組件spring cloud config,它支持配置服務放在配置服務的內存中(即本地),也支持放在遠程Git倉庫中。在spring cloud config 組件中,分兩個角色,一是config server,二是config client。
2.創建config-server工程:
1)pom.xml添加依賴:spring-cloud-config-server
2)Application類加上@EnableA上@EnableConfigServer注解開啟配置服務器的功能
3)配置文件修改指向git——文件為:config-client-dev.properties
4)測試
a)訪問http://localhost:8888/config-client-dev.properties
展示其內容:foo: foo version 2
b)具體的映射關系測試請查看其配置文件
的映射關系測試請查看其配置文件
http請求地址和資源文件映射如下:
/{application}/{profile}[/{label}]
/{application}-{profile}.yml
/{label}/{application}-{profile}.yml
/{application}-{profile}.properties
/{label}/{application}-{profile}.properties
#{application}映射客戶端的"spring.application.name"
#{profile}映射客戶端的"spring.profiles.active"(逗號分隔列表)
3.創建一個config-client工程
1)pom.xml添加依賴.xml添加依賴:spring-cloud-starter-config
2)配置文件bootstrap.properties
3)程序的入口類,寫一個API接口“/hi”,返回從配置中心讀取的foo變量的值
程序的入口類,寫一個API接口“/hi”,返回從配置中心讀取的foo變量的值
4)測試
打開網址訪問:http://localhost:8881/hi,網頁顯示:
dev|å¼åè
模å¼é
ç½®
這就說明,config-client從config-server獲取了foo的屬性,而config-server是從git倉庫讀取的
八、高可用的分布式配置中心(Spring Cloud Config)
1.當config-client很多時,可以將config-server做成集群,達成高可用
2.創建一個config-eureka-server工程,用作服務注冊中心
1)eureka依賴
2)yml上,指定服務端口為8889,加上作為服務注冊中心的基本配置
3)入口類: @EnableEurekaServer
3.改造config-server
1)pom.xml文件加上EurekaClient的起步依賴
2)配置文件application.yml,指定服務注冊地址為http://localhost:8889/eureka/
3)最后需要在程序的啟動類Application加上@EnableEurekaClient的注解
4.改造config-client
1)將其注冊微到服務注冊中心,作為Eureka客戶端,需要pom文件加上起步依賴
2)配置文件bootstrap.properties,注意是bootstrap
加上服務注冊地址為http://localhost:8889/eureka
spring.cloud.config.discovery.enabled是從配置中心讀取文件。
spring.cloud.config.discovery.serviceId配置中心的serviceId,即服務名。
5.測試
這時發現,在讀取配置文件不再寫ip地址,而是服務名,這時如果配置服務部署多份,通過負載均衡,從而高可用。