微服務化的核心就是將傳統的一站式應用,根據業務拆分紅一個一個的服務,完全地去解耦合,每個微服務提供單個業務功能也服務,一個服務作一件事,從技術角度看就是一種小而獨立的處理過程,相似進程概念,可以自行單獨啓動或銷毀,擁有本身獨立的數據庫。java
Dubbo | SpringCloud | |
---|---|---|
服務註冊中心 | Zookeeper | Eureka |
服務調用方式 | RPC | RestAPI |
服務監控 | Dubbo-monitor | Spring Boot Admin |
斷路器 | 不完善 | Hystrix |
服務網關 | 無 | Zuul |
分佈式配置 | 無 | Spring Cloud Config |
服務跟蹤 | 無 | Spring Cloud Sleuth |
消息總線 | 無 | Spring Cloud Bus |
數據流 | 無 | Spring Cloud Stream |
批量任務 | 無 | Spring Cloud Task |
最大區別:SpringCloud拋棄了Dubbo的RPC通訊,採用的是基於HTTP的REST方式。 嚴格來講,這兩種方式各有優劣,雖然從必定程度上來講,後者犧牲了服務調用的性能,但也避免了上面提到的原生RPC帶來的問題。並且REST相比RPC更爲靈活,服務提供方和調用方的依賴只依靠一紙契約,不存在代碼級別的強依賴,這在強調快速演化的微服務環境下,顯得更加合適。python
項目結構mysql
microservicecloud // 父項目
|- microservicecloud-api // 存放公共接口、實體類。。
|- microservicecloud-provider-dept-8081 // 部門服務提供者
|- microservicecloud-consumer-dept-80 // 部門服務消費者
書寫pom.xml文件web
1 <?xml version="1.0" encoding="UTF-8"?> 2 <project xmlns="http://maven.apache.org/POM/4.0.0" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 5 <modelVersion>4.0.0</modelVersion> 6 7 <groupId>cn.x5456</groupId> 8 <artifactId>microservicecloud</artifactId> 9 <packaging>pom</packaging> 10 <version>1.0-SNAPSHOT</version> 11 <modules> 12 <module>microservicecloud-api</module> 13 </modules> 14 15 <properties> 16 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 17 <maven.compiler.source>1.8</maven.compiler.source> 18 <maven.compiler.target>1.8</maven.compiler.target> 19 <junit.version>4.12</junit.version> 20 <log4j.version>1.2.17</log4j.version> 21 <lombok.version>1.16.18</lombok.version> 22 </properties> 23 24 <dependencyManagement> 25 <dependencies> 26 <dependency> 27 <groupId>org.springframework.cloud</groupId> 28 <artifactId>spring-cloud-dependencies</artifactId> 29 <version>Dalston.SR1</version> 30 <type>pom</type> 31 <scope>import</scope> 32 </dependency> 33 <dependency> 34 <groupId>org.springframework.boot</groupId> 35 <artifactId>spring-boot-dependencies</artifactId> 36 <version>1.5.9.RELEASE</version> 37 <type>pom</type> 38 <scope>import</scope> 39 </dependency> 40 <dependency> 41 <groupId>mysql</groupId> 42 <artifactId>mysql-connector-java</artifactId> 43 <version>5.0.4</version> 44 </dependency> 45 <dependency> 46 <groupId>com.alibaba</groupId> 47 <artifactId>druid</artifactId> 48 <version>1.0.31</version> 49 </dependency> 50 <dependency> 51 <groupId>org.mybatis.spring.boot</groupId> 52 <artifactId>mybatis-spring-boot-starter</artifactId> 53 <version>1.3.0</version> 54 </dependency> 55 <dependency> 56 <groupId>ch.qos.logback</groupId> 57 <artifactId>logback-core</artifactId> 58 <version>1.2.3</version> 59 </dependency> 60 <dependency> 61 <groupId>junit</groupId> 62 <artifactId>junit</artifactId> 63 <version>${junit.version}</version> 64 <scope>test</scope> 65 </dependency> 66 <dependency> 67 <groupId>log4j</groupId> 68 <artifactId>log4j</artifactId> 69 <version>${log4j.version}</version> 70 </dependency> 71 </dependencies> 72 </dependencyManagement> 73 74 <build> 75 <finalName>microservicecloud</finalName> 76 <resources> 77 <resource> 78 <directory>src/main/resources</directory> 79 <filtering>true</filtering> 80 </resource> 81 </resources> 82 <plugins> 83 <plugin> 84 <groupId>org.apache.maven.plugins</groupId> 85 <artifactId>maven-resources-plugin</artifactId> 86 <configuration> 87 <delimiters> 88 <delimit>$</delimit> 89 </delimiters> 90 </configuration> 91 </plugin> 92 </plugins> 93 </build> 94 95 </project>
和上面同樣算法
1)書寫pom.xml文件spring
1 <?xml version="1.0" encoding="UTF-8"?> 2 <project xmlns="http://maven.apache.org/POM/4.0.0" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 5 <parent> 6 <artifactId>microservicecloud</artifactId> 7 <groupId>cn.x5456</groupId> 8 <version>1.0-SNAPSHOT</version> 9 </parent> 10 <modelVersion>4.0.0</modelVersion> 11 12 <artifactId>microservicecloud-api</artifactId> 13 14 <dependencies><!-- 當前Module須要用到的jar包,按本身需求添加,若是父類已經包含了,能夠不用寫版本號 --> 15 <dependency> 16 <groupId>org.springframework.cloud</groupId> 17 <artifactId>spring-cloud-starter-feign</artifactId> 18 </dependency> 19 <dependency> 20 <groupId>org.springframework.boot</groupId> 21 <artifactId>spring-boot-starter-data-jpa</artifactId> 22 </dependency> 23 </dependencies> 24 </project>
2)書寫實體類sql
// 在api中這樣寫,有一點問題 @Entity // 告訴JPA這是一個實體類(對應數據表),不是普通的javabean @Table(name = "tb_dept") // 不寫這個註解,默認爲這個類的小寫做爲名字 public class Dept implements Serializable { @Id // 標識這是主鍵 @GeneratedValue(strategy = GenerationType.AUTO) // 根據數據庫自動選則主鍵自增類型 private Long deptno; // 主鍵 private String dname; // 部門名稱 private String dbSource;// 來自那個數據庫,由於微服務架構能夠一個服務對應一個數據庫,同一個信息被存儲到不一樣數據庫
1)書寫pom.xml文件數據庫
1 <?xml version="1.0" encoding="UTF-8"?> 2 <project xmlns="http://maven.apache.org/POM/4.0.0" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 5 <parent> 6 <artifactId>microservicecloud</artifactId> 7 <groupId>cn.x5456</groupId> 8 <version>1.0-SNAPSHOT</version> 9 </parent> 10 <modelVersion>4.0.0</modelVersion> 11 12 <artifactId>microservicecloud-provider-dept-8081</artifactId> 13 <dependencies> 14 <!-- 引入本身定義的api通用包,可使用Dept部門Entity --> 15 <dependency> 16 <groupId>cn.x5456</groupId> 17 <artifactId>microservicecloud-api</artifactId> 18 <version>${project.version}</version> 19 </dependency> 20 <!-- actuator監控信息完善 --> 21 <dependency> 22 <groupId>org.springframework.boot</groupId> 23 <artifactId>spring-boot-starter-actuator</artifactId> 24 </dependency> 25 <!-- 將微服務provider側註冊進eureka --> 26 <dependency> 27 <groupId>org.springframework.cloud</groupId> 28 <artifactId>spring-cloud-starter-eureka</artifactId> 29 </dependency> 30 <dependency> 31 <groupId>org.springframework.cloud</groupId> 32 <artifactId>spring-cloud-starter-config</artifactId> 33 </dependency> 34 <dependency> 35 <groupId>junit</groupId> 36 <artifactId>junit</artifactId> 37 </dependency> 38 <!--<dependency>--> 39 <!--<groupId>mysql</groupId>--> 40 <!--<artifactId>mysql-connector-java</artifactId>--> 41 <!--</dependency>--> 42 <dependency> 43 <groupId>com.oracle</groupId> 44 <artifactId>ojdbc14</artifactId> 45 <version>10.2.0.4.0</version> 46 </dependency> 47 <dependency> 48 <groupId>com.alibaba</groupId> 49 <artifactId>druid</artifactId> 50 </dependency> 51 <dependency> 52 <groupId>ch.qos.logback</groupId> 53 <artifactId>logback-core</artifactId> 54 </dependency> 55 <dependency> 56 <groupId>org.mybatis.spring.boot</groupId> 57 <artifactId>mybatis-spring-boot-starter</artifactId> 58 </dependency> 59 <dependency> 60 <groupId>org.springframework.boot</groupId> 61 <artifactId>spring-boot-starter-jetty</artifactId> 62 </dependency> 63 <dependency> 64 <groupId>org.springframework.boot</groupId> 65 <artifactId>spring-boot-starter-web</artifactId> 66 </dependency> 67 <dependency> 68 <groupId>org.springframework.boot</groupId> 69 <artifactId>spring-boot-starter-test</artifactId> 70 </dependency> 71 <!-- 修改後當即生效,熱部署 --> 72 <dependency> 73 <groupId>org.springframework</groupId> 74 <artifactId>springloaded</artifactId> 75 </dependency> 76 <dependency> 77 <groupId>org.springframework.boot</groupId> 78 <artifactId>spring-boot-devtools</artifactId> 79 </dependency> 80 </dependencies> 81 82 </project>
2)目錄結構apache
DeptProvider8081_App編程
@SpringBootApplication public class DeptProvider8001_App { public static void main(String[] args) { SpringApplication.run(DeptProvider8001_App.class, args); } }
controller
@RestController public class DeptController { @Autowired private DeptService service; @RequestMapping(value = "/dept/add", method = RequestMethod.POST) public Dept add(Dept dept){ return service.addDept(dept); } @RequestMapping(value = "/dept/get/{id}", method = RequestMethod.GET) public Dept get(@PathVariable("id") Long id) { return service.findById(id); } @RequestMapping(value = "/dept/list", method = RequestMethod.GET) public List<Dept> list(){ return service.findAll(); } }
service
@Service public class DeptServiceImpl implements DeptService { @Resource private DeptRepository deptRepository; @Override public Dept addDept(Dept dept) { return deptRepository.save(dept); } @Override public Dept findById(Long id) { return deptRepository.findOne(id); } @Override public List<Dept> findAll() { return deptRepository.findAll(); } }
repository
public interface DeptRepository extends JpaRepository<Dept,Long> { }
3)書寫配置文件
spring: application: name: microservicecloud-dept datasource: url: jdbc:oracle:thin:@127.0.0.1:1521:orcl username: scott password: tiger driver-class-name: oracle.jdbc.OracleDriver jpa: hibernate: # 更新或建立數據表 ddl-auto: update # 控制檯打印sql show-sql: true server: context-path: /DeptProvider8001_App port: 8001
1)書寫pom.xml文件
1 <?xml version="1.0" encoding="UTF-8"?> 2 <project xmlns="http://maven.apache.org/POM/4.0.0" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 5 <parent> 6 <artifactId>microservicecloud</artifactId> 7 <groupId>cn.x5456</groupId> 8 <version>1.0-SNAPSHOT</version> 9 </parent> 10 <modelVersion>4.0.0</modelVersion> 11 12 <artifactId>microservicecloud-consumer-dept-80</artifactId> 13 14 <dependencies> 15 <dependency><!-- 本身定義的api --> 16 <groupId>cn.x5456</groupId> 17 <artifactId>microservicecloud-api</artifactId> 18 <version>${project.version}</version> 19 </dependency> 20 <!-- Ribbon相關 --> 21 <dependency> 22 <groupId>org.springframework.cloud</groupId> 23 <artifactId>spring-cloud-starter-eureka</artifactId> 24 </dependency> 25 <dependency> 26 <groupId>org.springframework.cloud</groupId> 27 <artifactId>spring-cloud-starter-ribbon</artifactId> 28 </dependency> 29 <dependency> 30 <groupId>org.springframework.cloud</groupId> 31 <artifactId>spring-cloud-starter-config</artifactId> 32 </dependency> 33 <dependency> 34 <groupId>org.springframework.boot</groupId> 35 <artifactId>spring-boot-starter-web</artifactId> 36 </dependency> 37 <!-- 修改後當即生效,熱部署 --> 38 <dependency> 39 <groupId>org.springframework</groupId> 40 <artifactId>springloaded</artifactId> 41 </dependency> 42 <dependency> 43 <groupId>org.springframework.boot</groupId> 44 <artifactId>spring-boot-devtools</artifactId> 45 </dependency> 46 <dependency> 47 <groupId>com.oracle</groupId> 48 <artifactId>ojdbc14</artifactId> 49 <version>10.2.0.4.0</version> 50 </dependency> 51 </dependencies> 52 53 </project>
2)目錄結構
DeptConsumer80_App
@SpringBootApplication public class DeptConsumer80_App { public static void main(String[] args) { SpringApplication.run(DeptConsumer80_App.class, args); } }
書寫配置類
@Configuration public class ConfigBean //boot -->spring applicationContext.xml --- @Configuration配置 ConfigBean = applicationContext.xml{ @Bean public RestTemplate getRestTemplate(){ return new RestTemplate(); } }
controller
@RestController public class DeptController_Consumer{ private static final String REST_URL_PREFIX = "http://localhost:8001/DeptProvider8001_App"; /** * 使用 使用restTemplate訪問restful接口很是的簡單粗暴無腦。 (url, requestMap, * ResponseBean.class)這三個參數分別表明 REST請求地址、請求參數、HTTP響應轉換被轉換成的對象類型。 */ @Autowired private RestTemplate restTemplate; @RequestMapping(value = "/consumer/dept/add") public boolean add(Dept dept) { return restTemplate.postForObject(REST_URL_PREFIX + "/dept/add", dept, Boolean.class); } @RequestMapping(value = "/consumer/dept/get/{id}") public Dept get(@PathVariable("id") Long id) { return restTemplate.getForObject(REST_URL_PREFIX + "/dept/get/" + id, Dept.class); } @RequestMapping(value = "/consumer/dept/list") public List<Dept> list() { return restTemplate.getForObject(REST_URL_PREFIX + "/dept/list", List.class); } }
3)配置文件
### 理論上這部分不該該有 ### spring: datasource: url: jdbc:oracle:thin:@127.0.0.1:1521:orcl username: scott password: tiger driver-class-name: oracle.jdbc.OracleDriver jpa: hibernate: # 更新或建立數據表 ddl-auto: update # 控制檯打印sql show-sql: true ################## server: port: 80 context-path: /DeptConsumer80_App
Eureka是Spring Cloud Netflix的一個子模塊,也是核心模塊之一。用於雲端服務發現,一個基於REST的服務,用於定位服務,以實現雲端中間層服務發現和故障轉移。服務的註冊與發現對應微服務架構來講是很是重要的,有了服務的發現與註冊,只須要使用服務標識符,就能夠訪問到服務,而不須要修改服務調用的配置文件了。
其功能相似與dubbo的註冊中心(zookeeper)。
SpringCloud封裝了Netflix公司開發的Eureka模塊來實現服務的註冊與發現。
Eureka採用了C-S的設計架構。Eureka Server做爲服務註冊功能的服務器,它是服務的註冊中心。而系統中其餘的微服務,使用Eureka的客戶端鏈接到Eureka Server並維持心跳鏈接,這樣系統的維護人員就能夠經過Eureka Server來監控系統中各個微服務是否正常運行。SpringCloud的一些其餘模塊(Zuul)就能夠經過Eureka來發現系統中的其餘微服務,並執行相關的邏輯。
Eureka Server提供服務註冊服務,在各個節點啓動後,會在Eureka Server中進行註冊,這樣EurekaServer中的服務註冊表中將會存儲全部可用服務節點的信息,服務階段的信息能夠在界面中直觀的看到。
EurekaClient是一個Java客戶端,用於簡化EurekaServer的交互,客戶端同時也具有一個內置的、使用輪詢負載算法的負載均衡器。在應用啓動後,將會EurekaServer發送心跳(默認週期是30s)。若是EurekaServer在多個心跳週期內沒有接收到某個節點的心跳,EurekaServer將會從服務註冊表中吧這個服務節點移除(默認30s)。
EurekaServer:提供服務的註冊和發現
Server Provider服務提供方將自身服務註冊到Eureka,從而使服務消費方能夠找到
Service Consumer服務消費方從Eureka獲取註冊服務列表,從而能夠消費服務
默認狀況下,若是EurekaServer在必定時間內沒有接收到某個微服務實例的心跳,Eureka Server將會註銷該實例(默認90秒)。可是當網絡分區發生故障時,微服務與EurekaServer之間沒法正常通訊,以上行爲可能變得很是危險了——由於微服務自己實際上是健康的,此時不該該註銷這個微服務。Eureka經過「自我保護模式」來解決這個問題——當EurekaServer節點在短期內丟失過多客戶端時(可能網絡分區發生故障),那麼這個節點就會進入自我保護模式。一旦進入改模式,EurekaServer就會保護服務註冊表中的信息,再也不刪除服務註冊表中的數據(也就是不會註銷任何微服務)。當網絡故障恢復後,改Eureka節點會自動退出自我保護模式。
綜上自我保護模式是一種應對網絡異常的安全保護措施。他的架構哲學是寧肯保留全部微服務(無論它健不健康都會保留),也不盲目註銷任何微服務。使用自我保護模式,可讓Eureka集羣更加健壯、穩定。
● 一致性(C):在分佈式系統中的全部數據備份,在同一時刻是否一樣的值。(等同於全部節點訪問同一份最新的數據副本)
● 可用性(A):在集羣中一部分節點故障後,集羣總體是否還能響應客戶端的讀寫請求。(對數據更新具有高可用性)
● 分區容錯性(P):以實際效果而言,分區至關於對通訊的時限要求。系統若是不能在時限內達成數據一致性,就意味着發生了分區的狀況,必須就當前操做在C和A之間作出選擇。
當向註冊中心查詢服務列表時,咱們能夠容忍註冊中心返回的是幾分鐘前的註冊信息,但不能接受直接down掉不可用。也就是說,服務註冊功能對可用性的要求要高於一致性。可是Zookeeper會出現這樣一種狀況,當master節點由於網絡故障與其餘節點失去聯繫時,剩餘節點會從新進行leader選舉。問題在於,選舉leader的時間太長,30 ~ 120s,且選舉期間整個zk集羣都是不可用的,這就致使在選舉期間註冊服務癱瘓。在雲部署的環境下,因網絡問題使得zk集羣失去master節點是較大機率會發生的事,雖然服務可以恢復,可是漫長的選舉時間致使的註冊長期不可用是不能容忍的。
Eureka看明白了這一點,所以在設計時就優先保證可用性。Eureka各個節點都是平等的,幾個節點掛掉不會影響正常節點的工做 ,剩餘的節點依然能夠提供註冊和查詢服務。而Eureka的客戶端在向某個Eureka註冊或時若是發現鏈接失敗,則會自動切換至其它節點,只要有一臺Eureka還在,就能保證註冊服務可用(保證可用性),只不過查到的信息可能不是最新的(不保證強一致性)。除此以外,Eureka還有一種自我保護機制,若是在15分祌內超過85%的節點都沒有正常的心跳,那麼Eureka就認爲客戶端與註冊中心出現了網絡故障,此時會出現如下幾種狀況:
Eureka再也不從註冊列表中移除由於長時間沒收到心跳而應該過時的服務
Eureka仍然可以接受新服務的註冊和查詢請求,可是不會被同步到其它節點上(即保證當前節點依然可用)
當網絡穩定時,當前實例新的註冊信息會被同步到其它節點中
所以,Eureka能夠很好的應對因網絡故障致使部分節點失去聯繫的狀況,而不會像Zookeeper那樣是整個註冊服務癱瘓。
1)新建項目
2)目錄結構
MicroservicecloudEureka7001Application
@SpringBootApplication @EnableEurekaServer // 表明eureka服務端 public class MicroservicecloudEureka7001Application { public static void main(String[] args) { SpringApplication.run(MicroservicecloudEureka7001Application.class, args); } }
書寫配置文件
# 端口號 server.port=7001 # 主機名 eureka.instance.hostname=localhost # 是否向服務註冊中心註冊本身 eureka.client.register-with-eureka=false # 是否檢索服務,false表示本身就是註冊中心,不須要去檢索服務 eureka.client.fetch-registry=false # 服務註冊中心的配置內容,指定服務註冊中心的位置 eureka.client.service-url.defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
1)修改服務提供者與消費者的主方法
@SpringBootApplication
@EnableEurekaClient // eureka客戶端
public class DeptProvider8001_App {
public static void main(String[] args) {
SpringApplication.run(DeptProvider8001_App.class, args);
}
}
2)爲服務提供者與消費者配置文件中添加配置
eureka:
client:
service-url:
defaultZone: http://localhost:7001/eureka/
3)還要在restTemplate上添加負載均衡註解,客戶端才能夠調用
此時url能夠改成提供者在Eureka中註冊的名字
將這個服務註冊到每個eureka上
Spring Cloud Ribbon是基於Netflix Ribbon實現的一套客戶端負載均衡的工具。
Ribbon是Netflix發佈的開源項目,主要功能是提供客戶端的軟件負載衡算法,將Netflix的中間層服務鏈接在一塊兒。 Ribbon客戶端組件提供一系列完善的配置項如鏈接超時,重試等。簡單的說,就是在配置文件中列出Load Balancer (負載均衡)後面全部的機器,Ribbon會自動的幫助你基於某種規則(如簡單輪詢,隨機鏈接等)去鏈接這些機器。咱們也很容易使用Ribbon實現自定義的負載均衡算法。
第一步先選擇EurekaServer,他優先選則在同一個區域內負載較少的server
第二步在根據用戶指定的策略,從server渠道的服務註冊列表中選則一個地址。
Ribbon默認是採用輪詢的方式進行負載均衡,咱們可使用irule進行指定。
首先要在(消費者)pom.xml文件中引入jar包
<!-- Ribbon相關 -->
<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.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
以前爲了可以使用微服務名稱來調用服務時,咱們已經使用過ribbon了,沒錯就是這個:
Robbon默認使用的是輪詢算法,總共有如下幾種算法:
可使用如下方法進行修改算法
Feign是一個聲明式WebService客戶端。使得編寫Web服務客戶端變得很是容易,咱們只須要建立一個接口,而後在上面添加註解便可。
Feign旨在使編寫JavaHttp客戶端變得更容易。前面在使用Ribbon+RestTemplate時,利用RestTemplate對http請求的封裝處理,造成了一套模板化的調用方法,可是在實際開發中,因爲對服務依賴的調用可能不止一處,每每一個接口會被多處調用,因此一般都會針對每一個微服務自行封裝一些客戶端類來包裝這些依賴服努的調用。因此,Feign在此基礎上作了進一步封裝,由他來幫助咱們定義和實現依賴服務接口的定義。在 Feign的實現下,咱們只需建立一個接口並使用註解的方式來配置它,便可完成對服務提供方的接口綁定,簡化了使用Spring cloud Ribbon時,自動封裝服務調用客戶端的開發量。
Feign集成了Ribbon,使用它來進行負載均衡。
pom.xml導入相應依賴
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
</dependency>
@FeignClient(value = "MICROSERVICECLOUD-DEPT/DeptConsumerDeptFeign_App") // 這個是咱們要調用的提供者在eureka中註冊的名字 public interface DeptClientService { @RequestMapping(value = "/dept/get/{id}", method = RequestMethod.GET) // 要請求 提供者 的url public Dept get(@PathVariable("id") long id); @RequestMapping(value = "/dept/list", method = RequestMethod.GET) public List<Dept> list(); @RequestMapping(value = "/dept/add", method = RequestMethod.POST) public boolean add(Dept dept); }
DeptConsumerDeptFeign_App
@SpringBootApplication @EnableEurekaClient @EnableFeignClients(basePackages= {"cn.x5456.microservicecloud"}) // 掃描全部Feign的接口 @ComponentScan("cn.x5456.springcloud") // 掃描咱們調用的controller public class DeptConsumerDeptFeign_App { public static void main(String[] args) { SpringApplication.run(DeptConsumerDeptFeign_App.class, args); } }
DeptController_Consumer(變得和咱們面向接口編程同樣了)
@RestController public class DeptController_Consumer { @Autowired private DeptClientService service; @RequestMapping(value = "/consumer/dept/get/{id}") public Dept get(@PathVariable("id") Long id) { return this.service.get(id); } @RequestMapping(value = "/consumer/dept/list") public List<Dept> list() { return this.service.list(); } @RequestMapping(value = "/consumer/dept/add") public Object add(Dept dept) { return this.service.add(dept); } }
配置文件和之前同樣
通常處某個服務故障異常引發,相似現實世界中的「保險絲「,當某個異常條件被觸發,直接熔斷整個服務,而不是一直等到此服務超時。
1)(提供者端)導入依賴
<!-- hystrix -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
2)在須要進行熔斷處理的方法上添加註解,書寫熔斷方法
@RestController public class DeptController { @Autowired private DeptService service = null; @RequestMapping(value = "/dept/get/{id}", method = RequestMethod.GET) //一旦調用服務方法失敗並拋出了錯誤信息後,會自動調用@HystrixCommand標註好的fallbackMethod調用類中的指定方法 @HystrixCommand(fallbackMethod = "processHystrix_Get") public Dept get(@PathVariable("id") Long id) { Dept dept = this.service.get(id); if (null == dept) { throw new RuntimeException("該ID:" + id + "沒有沒有對應的信息"); } return dept; } public Dept processHystrix_Get(@PathVariable("id") Long id) { return new Dept().setDeptno(id).setDname("該ID:" + id + "沒有沒有對應的信息,null--@HystrixCommand") .setDb_source("no this database in MySQL"); } }
3)在主方法上添加@EnableCircuitBreaker註解
@SpringBootApplication @EnableEurekaClient //本服務啓動後會自動註冊進eureka服務中 @EnableCircuitBreaker//對hystrixR熔斷機制的支持 public class DeptProvider8001_Hystrix_App { public static void main(String[] args) { SpringApplication.run(DeptProvider8001_Hystrix_App.class, args); } }
降級,通常是從總體負荷考慮。就是當某個服務熔斷以後,服務器將再也不被調用,此時客戶端能夠本身準備一個本地的fallback回調,返回—個缺省值。這樣作,雖然服務水平降低,但好歹可用,比直接掛掉要強。
1)在microservicecloud-api項目,根據剛剛寫的DeptClientService接口新建一個實現了FallbackFactory接口的類DeptClientServiceFallbackFactory
@Component // 不要忘記添加 public class DeptClientServiceFallbackFactory implements FallbackFactory<DeptClientService> { @Override public DeptClientService create(Throwable throwable) { return new DeptClientService() { @Override public Dept get(long id) { Dept dept = new Dept(); dept.setDname("yyy"); return dept; } @Override public List<Dept> list() { return null; } @Override public boolean add(Dept dept) { return false; } }; } }
2)爲DeptClientService的註解中添加參數
@FeignClient(value = "MICROSERVICECLOUD-DEPT",fallbackFactory=DeptClientServiceFallbackFactory.class)
3)在消費者端的配置文件中添加下面配置:
feign:
hystrix:
enabled: true
4)測試
Zuul包含了對請求的路由和過濾兩個最主要的功能: 其中路由功能負責將外部請求轉發到具體的微服務實例上,是實現外部訪問統一入口的基礎而過濾器功能則負責對請求的處理過程進行干預,是實現請求校驗、服務聚合等功能的基礎。
Zuul和Eureka進行整合,將Zuul自身註冊爲Eureka服務治理下的應用,同時從Eureka中得到其餘微服務的消息,也即之後的訪問微服務都是經過Zuul跳轉後得到。