SpringCloud 是利用SpringBoot的開發便利性巧妙的簡化了分佈式系統基礎設施的開發 ,如服務註冊與發現,配置中心,網關服務,負載均衡,熔斷器,消息總線,數據監控等,若是想了學習如下內容請先對SpringBoot有必定的瞭解 ,本簡書主要從SpringCloud的入門到SpringCloud的項目實戰做爲學習路線 如沒有SpringBoot的基礎請先關注 暫時不要閱讀java
在介紹SpringCloud以前不少人都會將SpringCloud與Dubbo進行對比 首先要認可Dubbo的性能確實比SpringCloud的性能好 由於SpringCloud是基於Http協議每次都要建立鏈接傳輸的也是文本內容 而Dubbo是基於Netty的TCP協議及二進制的傳輸協議 更接近底層,因此在性能方面不用質疑的web
Eureka: 服務註冊與發現,用於服務管理spring
Ribbon: 基於客戶端的負載均衡組件bootstrap
Hystrix: 容錯框架,可以防止服務的雪崩效應api
Feign: Web服務客戶端,可以簡化Http接口的調用安全
Zuul: API網關提供路由轉發,請求過濾等功能springboot
Config: 分佈式配置管理bash
Sleuth: 服務鏈路跟蹤網絡
Stream: 構建消息驅動的微服務應用程序的框架架構
Bus : 消息代理的集羣消息總線(集成消息中間件Kafka ,RabbitMQ) . . . . . .
註冊中心在微服務架構中是必不可少的一部分,主要是用來實現服務的治理功能. 常見的註冊中心有Eureka和Zookeeper 在分佈式系統領域有個CAP定理 C:數據一致性 A:服務可用性 P: 服務對網絡分區故障的容錯性 這三個特性在任何分佈式系統中都不能同時知足,最多同時知足兩個 Eureka是基於AP原則構建 Zookeeper是基於CP原則構建 若是要保證AP就要用Eureka 想要保證CP就要用Zookeeper Dubbo大部分都是基於Zookeeper做爲註冊中心 ,SpringCloud都是使用Eureka做爲註冊中心
首先建立一個maven項目 spring-eureka-registry 在pom.xml裏添加相關依賴
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jolokia</groupId>
<artifactId>jolokia-core</artifactId>
</dependency>
</dependencies>
複製代碼
建立一個啓動類EurekaRegistryMsApplication
@EnableEurekaServer
@SpringBootApplication
public class EurekaRegistryMsApplication {
public static void main(String[] args) {
new SpringApplicationBuilder(EurekaRegistryMsApplication.class).web(true).run(args);
}
}
複製代碼
@EnableEurekaServer註解表示開啓EurekaServer 接下來建立一個application.yml 咱們這裏使用yml格式的
server:
port: ${port:${PORT:8763}}
management:
port: 9274
context-path: '/55395018-70b7-47c3-8fef-5bf24c9da9af'
eureka:
instance:
hostname: eureka1
prefer-ip-address: false
instance-id: ${spring.application.name}:${spring.cloud.client.ipAddress}:${spring.application.instance_id:${server.port}}
metadata-map:
cluster: prontera
management:
port: ${management.port}
context-path: ${management.context-path}
health:
path: ${management.context-path}/health
status-page-url-path: ${management.context-path}/info
health-check-url-path: ${management.context-path}/health
client:
service-url:
defaultZone: 'http://${eureka.instance.hostname}:${server.port}/eureka/'
fetch-registry: false
register-with-eureka: false
server:
renewal-percent-threshold: '0.8'
spring:
application:
name: 'registry'
複製代碼
這裏須要注意的是register-with-eureka: false 屬性 不須要註冊本身 接下來就能夠直接運行EurekaRegistryMsApplication啓動類了 而後訪問http://localhost:8763/ 就能夠看到Eureka提供的Web控制檯了
這裏用了@SpringCloudApplication註解,它整合了@SpringBootApplication、@EnableDiscoveryClient、@EnableCircuitBreaker,主要目的仍是簡化配置。
####2.Ribbon 客戶端負載均衡 目前主流的負載方案有兩種:一是集中式負載均衡,在消費者和服務提供方中間使用獨立的代理方式進行負載,有硬件的(F5),也有軟件的(Nginx).另外一種就是客戶端本身作負載均衡,根據本身的請求作負載,Ribbon就屬於客戶端本身作負載均衡. 經過Spring Cloud Ribbon的封裝,咱們在微服務架構中使用客戶端負載均衡調用很是簡單,只須要以下兩步:
- 服務提供者只須要啓動多個服務實例並註冊到一個註冊中心或是多個相關聯的服務註冊中心.
- 服務消費者直接經過調用被@LoadBalanced註解修飾過的RestTemplate來實現面向服務的接口調用.
這樣咱們就能夠將服務提供者的高可用以及服務消費者的負載均衡調用一塊兒實現了.
Spring Cloud整合Ribbon只須要在pom.xml中加入依賴便可 其餘的能夠不用配置 由於Eureka中已經中已經引用了Ribbon
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-ribbon</artifactId>
</dependency>
複製代碼
@SpringBootApplication
@EnableEurekaClient
public class SpringbootRestTemplateApplication {
@Autowired
private RestTemplateBuilder builder;
@Bean
@LoadBalanced // 添加負載均衡支持,很簡單,只須要在RestTemplate上添加@LoadBalanced註解,那麼RestTemplate即具備負載均衡的功能,若是不加@LoadBalanced註解的話,會報java.net.UnknownHostException:springboot-h2異常,此時沒法經過註冊到Eureka Server上的服務名來調用服務,由於RestTemplate是沒法從服務名映射到ip:port的,映射的功能是由LoadBalancerClient來實現的。
public RestTemplate restTemplate() {
return builder.build();
}
public static void main(String[] args) {
SpringApplication.run(SpringbootRestTemplateApplication.class, args);
}
}
複製代碼
@RestController
public class RestTemplateController {
@Autowired
private RestTemplate restTemplate;
@GetMapping("/hello/{id}")
public User findById(@PathVariable Long id) {// 將原來的ip:port的形式,改爲註冊到Eureka Server上的應用名便可
User u = this.restTemplate.getForObject("http://SERVICE-HELLO/hello" + id, User.class);
System.out.println(u);
return u;
}
}
複製代碼
除了使用@LoadBalanced註解外,咱們還能夠直接使用Ribbon所提供的LoadBalancerClient來實現負載均衡: application.yml
stores:
ribbon:
listOfServers: www.baidu.com,www.jianshu.com,www.163.com
複製代碼
@RestController
public class HelloController { protected Logger logger = LoggerFactory.getLogger(HelloController.class);
@Autowired private RestTemplate restTemplate;
@Autowired private LoadBalancerClient loadBalancerClient;
@RequestMapping(value = "/hello", method = RequestMethod.GET) public String hello() {
return restTemplate.getForEntity("http://SERVICE-HELLO/hello", String.class).getBody();
}
@RequestMapping(value = "/helloEx", method = RequestMethod.GET)
public String helloEx() {
ServiceInstance instance = this.loadBalancerClient.choose("SERVICE-HELLO");
URI helloUri = URI.create(String.format("http://%s:%s/hello", instance.getHost(), instance.getPort()));
logger.info("Target service uri = {}. ", helloUri.toString());
return new RestTemplate().getForEntity(helloUri,String.class).getBody(); } }
複製代碼
API網關是對外服務的一個入口,隱藏了內部的實現,是微服務架構中必不可少的一個組件.API網關能夠爲咱們管理大量的API接口,還能夠對接客戶,適配協議,進行安全認證,路由轉發,限制流量,日誌監控,防止爬蟲,進行灰度發佈等, Zuul可以與Eureka,Ribbon,Hystrix等組件配合使用.
建立一個項目命名application-gateway 加入依賴
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zuul</artifactId>
</dependency>
複製代碼
爲了最後的實戰演練 下面是須要添加的所有依賴
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zuul</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix-sidecar</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-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>org.jolokia</groupId>
<artifactId>jolokia-core</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-zipkin</artifactId>
</dependency>
</dependencies>
複製代碼
spring-cloud-starter-zuul依賴中還包含了:
spring-cloud-start-hystrix: 該依賴用來在網關服務中實現對微服務轉發時候的保護機制,經過線程隔離和斷路器,防止微服務的故障引起API網關資源沒法釋放,從而影響其餘應用的對外服務
spring-cloud-starter-ribbon: 該依賴用來實如今網關服務進行路由轉發時候的客戶端負載均衡以及請求重試. spring-boot-starter-actuator: 該依賴用來提供常規的微服務管理端點.另外 在Spring Cloud Zuul 中還提供了 /routes端點來返回當前的全部路由規則
建立啓動類ApiGatewayMsApplication 使用@EnableZuulProxy註解開啓Zuul的API網關服務功能
@EnableZuulProxy
@SpringCloudApplication
public class ApiGatewayMsApplication {
public static void main(String[] args) {
SpringApplication.run(ApiGatewayMsApplication.class, args);
}
}
複製代碼
配置文件bootstrap.yml
server:
port: 7291
management:
port: 10211
context-path: '/fb83deee-dd46-472b-99a9-f0ebffe20d0e'
eureka:
client:
service-url:
defaultZone: 'http://eureka1:8763/eureka/,http://eureka2:8762/eureka/'
instance:
instance-id: ${spring.application.name}:${spring.cloud.client.ipAddress}:${spring.application.instance_id:${server.port}}
metadata-map:
cluster: prontera
management:
port: ${management.port}
context-path: ${management.context-path}
health:
path: ${management.context-path}/health
status-page-url-path: ${management.context-path}/info
health-check-url-path: ${management.context-path}/health
prefer-ip-address: false
zuul:
routes:
quartz:
sensitiveHeaders: "*"
serviceId: application-quartz
stripPrefix: false
path: /quartz/**
manager:
sensitiveHeaders: "*"
serviceId: trade-manager
stripPrefix: false
path: /manager/**
api:
sensitiveHeaders: "*"
serviceId: trade-api
stripPrefix: false
path: /api/**
spring:
application:
name: gateway
cloud:
loadbalancer:
retry:
enabled: false #關閉重試
zipkin:
base-url: 'http://zipkin_server:9411/'
ribbon:
MaxAutoRetries: 0
MaxAutoRetriesNextServer: 0
OkToRetryOnAllOperations: false
ConnectTimeout: 6500
ReadTimeout: 60000
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 65000
複製代碼
完成上面的工做後 啓動網關服務 就經過Zuul實現了API網關服務
咱們此時能夠經過Eureka查看註冊的服務
在這裏讀者須要看一下個人配置文件
在這裏是面向服務的路由,簡單的說就是讓路由的path不是映射具體的url而是讓他映射到具體的服務 而具體的url則交給Eureka的服務發現機制去自動維護
舉個栗子: http://localhost:7291/manager/hello: 改url符合/manager/**規則 由manager路由負責轉發 ,該路由映射的serviceId爲trade-manager,因此最終 /hello 請求會被髮送到trade-manager服務的一個實例上去
這個服務會在實戰中介紹給你們 先附一張圖理解一下
在微服務架構中存在多個可直接調用的服務.這些服務若在調用時出現故障會致使連鎖效應,也就是可能會讓整個系統變得不可用,這種狀況咱們稱之爲服務雪崩效應,這裏咱們經過Hystrix來實現服務容錯處理.
簡單使用 添加依賴
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
複製代碼
在啓動類上添加@EnableHystrix或者@EnableCircuitBreaker
@GetMapping("/callHello")
@HystrixCommand(fallbackMethod = "defaultCallHello")
public String callHello(){
String result = restTemplate.getForObject(
"http://loan/hello",String.class);
return result;
}
複製代碼
當調用失敗觸發熔斷時會調用defaultCallHello方法來回退具體內容
public String defaultCallHello(){
return "fail";
}
複製代碼
熔斷簡單的介紹這裏 後面咱們會針對每個接口都作熔斷處理