注:此隨筆爲讀書筆記。《Spring Cloud微服務實戰》,想學習Spring Cloud的同伴們能夠去看看此書,裏面對源碼有詳細的解讀。java
什麼是微服務?程序員
微服務是將一個本來獨立的系統拆分紅若干個小型服務(通常按照功能模塊拆分),這些小型服務都在各自獨立的進程中運行,服務之間經過基於HTTP的RESTful API進行通訊協做。每一個微服務維護自身的數據存儲、業務開發、自動化測試案例以及獨立部署機制。維護自身的數據存儲稱爲數據管理的去中心化。因爲數據管理的去中心化,各個微服務的數據一致性成爲一個難題,所以,須要強調的是各個服務之間進行無「事務」的調用。web
微服務架構中針對不一樣應用場景和出現的各類問題出現了各類解決方案和開源框架。服務治理:阿里的Dubbo、噹噹網擴展的Dubbox、Netflix的Eureka、Apache的Consul等;分佈式配置管理:百度的Disconf、Spring cloud的Config、淘寶的Diamond等;批量任務:噹噹網的Elastic-Job、Spring Cloud的Task等;服務跟蹤:京東的Hydra、Spring Cloud的Sleuth等;等等。算法
Spring Cloud不僅是解決微服務中的某一個問題,而是一個解決微服務架構實施的綜合性解決框架,它整合了諸多被普遍實踐和證實過的框架做爲實施的基礎部件,又在該體系基礎上建立了一些優秀的邊緣組件。如Spring Cloud Eureka、Spring Cloud Ribbon、Spring Cloud Hytrix、Spring Cloud Feign等針對微服務的解決方案。spring
Spring Cloud是一個基於Spring Boot實現的微服務框架,針對微服務應用的不一樣場景,產生了各類技術架構:apache
1.Spring Cloud Config:配置管理工具;瀏覽器
2.Spring Cloud Netflix:Spring Cloud的核心組件,對多個Netflix OSS開源套件進行整合;架構
a.Eureka:服務治理組件,包含服務註冊中心、服務註冊、服務發現和消費機制的實現;app
b.Hystrix:容錯管理組件,實現斷路由器模式,幫助服務依賴中出現的延遲和故障提供強大的容錯能力;負載均衡
c.Ribbon:客戶端負載均衡的服務調用組件;
d.Feign:基於Ribbon和Hystrix的聲明式服務調用組件,是對二者的整合;
e.Zuul:網關組件,提供智能路由、訪問過濾等功能。
f.Archaius:外部化配置組件。
3.Spring Cloud Bus:事件、消息總線,用於傳播集羣中的狀態變化或事件,以觸發後續的處理,好比用來動態刷新配置等;
4.Spring Cloud Cluster:針對Zookeeper、Redis、Hazelcast、Consul的選舉算法和通用狀態模式的實現;
5.Spring Cloud Stream:經過Redis、Rabbit和Kafka實現的消費服務,能夠經過簡單的聲明式模型來發送和接收消息;
6.Spring Cloud Sleuth:Spring Cloud應用的分佈式跟蹤實現,能夠完美整合Zipkin;
7.Spring Cloud Zookeeper:基於Zookeeper的服務發現與配置管理組件。等等。
Spring Cloud Eureka主要負責微服務架構當中的微服務治裏工做,是微服務架構當中最爲核心和基礎的模塊,用來實現各個微服務的服務註冊和服務發現。
Spring Cloud Eureka,使用Netflix Eureka來實現微服務的註冊和發現,包括服務端組件和客戶端組件,服務端和客戶端組件均有java語言編寫的,因此Eureka主要使用於java語言的分佈式系統。可是,它也支持非java語言的微服務架構,只是,須要程序員本身來實現Eureka的客戶端程序。一些開放平臺上有一些客戶端框架,例如,.NET平臺的Steeltoe、Node.js的eureka-js-client等。這裏說的服務端就是註冊中心,客戶端就是一些微服務。
Eureka服務治理體系有三大核心角色:服務註冊中心、服務提供者以及服務消費者。服務註冊中心通常稱爲Eureka服務端,服務提供者和服務消費者稱爲Eureka客戶端。
本隨筆涉及的開發工具:IDEA,技術框架:Spring Boot和Spring Cloud
1.建立一個基礎的Spring Boot項目,命名:eureka-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>4.0.0</modelVersion> <groupId>com.example</groupId> <artifactId>demo</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>demo-eureka</name> <description>Demo project for Spring Boot</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.3.7.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> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Camden.SR4</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>
2.Spring Boot啓動類中添加註解@EnableEurekaServer
package com.example.eurekaserver; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; @EnableEurekaServer @SpringBootApplication public class Application { public static void main(String[] args) { new SpringApplicationBuilder(Application.class).web(true).run(args); } }
3.Spring Boot配置文件信息,裏面有兩點須要注意
server:
port: 1111
eureka:
instance:
hostname: localhost
client:
register-with-eureka: false #1. false:表明不讓註冊中心註冊本身
fetch-registry: false #2. false:註冊中心職責是維護服務實例,不須要去檢索服務
serviceUrl:
default: http://${eureka.instance.hostname}:${server.port}/eureka/
採用yml文件,只需將application.properties文件後綴改爲application.yml便可。
4.項目結構:
5.瀏覽器輸入http://localhost:1111/,便可看到Eureka信息面板。
提供服務的應用能夠是Spring Boot應用,也能夠是其餘技術平臺且遵循Eureka通訊機制的應用。將本身的應用註冊到註冊中心Eureka,以供其餘應用使用。
1.建立一個Spring Boot項目,命名:demo-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>4.0.0</modelVersion> <groupId>com.example</groupId> <artifactId>demo</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>demo-server</name> <description>Demo project for Spring Boot</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.7.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> <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.SR4</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>
2.測試Controller
@RestController public class HelloController { @Autowired private DiscoveryClient discoveryClient; @RequestMapping(value = "/hello", method = RequestMethod.GET) public String index() { ServiceInstance instance = discoveryClient.getLocalServiceInstance(); return "hello world! host:" + instance.getHost() + ", service_id" + instance.getServiceId(); } }
3.啓動類添加註解@EnableDiscoverClient
@EnableDiscoveryClient @SpringBootApplication public class DemoServerApplication { public static void main(String[] args) { SpringApplication.run(DemoServerApplication.class, args); } }
4.配置文件信息 application.yml
spring:
application:
name: demo-service
eureka:
client:
serviceUrl:
defaultZone: http://localhost:1111/eureka/ #指定註冊中心
5.啓動項目,能夠看到微服務已經註冊到註冊中心
服務消費者,會作兩件事,服務發現和服務消費,服務發現由Eureka的客戶端完成,服務消費由Ribbon完成。Ribbon是一個基於Http和Tcp的負載均衡器,它能夠根據客戶端(通常指服務消費者)中配置的ribbonServerList服務列表以輪詢的方式訪問,以達到負載均衡的做用。
1.建立一個ribbon-consumer項目,pom.xml中添加 spring-cloud-starter-ribbon包
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.example</groupId> <artifactId>demo</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>ribbon-consumer</name> <description>Demo project for Spring Boot</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.3.7.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> <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> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Camden.SR4</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>
2.啓動類
package com.example.demo; 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; @EnableDiscoveryClient @SpringBootApplication public class RibbonConsumerApplication { @Bean @LoadBalanced RestTemplate restTemplate() { return new RestTemplate(); } public static void main(String[] args) { SpringApplication.run(RibbonConsumerApplication.class, args); } }
3.controller
@RestController public class ConsumerController { @Autowired private RestTemplate restTemplate; @RequestMapping(value = "/ribbon-consumer", method = RequestMethod.GET) public String helloConsumer() { return restTemplate.getForEntity("http://DEMO-SERVICE/hello", String.class).getBody(); } }
4.配置文件
server:
port: 9001
spring:
application:
name: ribbon-consumer
eureka:
client:
serviceUrl:
defaultZone: http://localhost:1111/eureka/
4.測試
用不一樣端口啓動兩個demo-server服務,用來測試ribbon的負載均衡(在demo-server中的接口添加打印日誌,能夠在控制檯看出那個服務被調用)
java -jar demo-0.0.1-SNAPSHOT.jar --server.port=8081
java -jar demo-0.0.1-SNAPSHOT.jar --server.port=8082
啓動ribbon-consumer項目
註冊中心
訪問http://localhost:9001/ribbon-consumer
兩個註冊服務互相註冊便可實現高可用。
1.在第一個搭建的服務註冊中心項目eureka-server上,將原來的application.yml註釋,新建兩個application-peer1.yml和application-peer2.yml
server:
port: 1111
spring:
profiles: peer1
eureka:
instance:
hostname: peer1
client:
serviceUrl:
defaultZone: http://peer2:1112/eureka/
server:
port: 1112
spring:
profiles: peer2
eureka:
instance:
hostname: peer2
client:
serviceUrl:
defaultZone: http://peer1:1111/eureka/
2.啓動項目便可
3.修改demo-server項目中的配置文件,添加信息以下
spring:
application:
name: demo-service
eureka:
client:
serviceUrl:
defaultZone: http://peer1:1111/eureka/,http://peer2:1112/eureka/
而後啓動該項目,即該服務皆註冊到兩個註冊中心。
此時,若其中一個註冊中心掛掉,那麼另一個註冊中心能夠繼續使用。