Spring Boot與分布式
分布式系統(tǒng)
在分布式系統(tǒng)中篱竭,國內(nèi)常用zookeeper+dubbo組合力图,而Spring Boot推薦使用全棧的Spring,Spring Boot+Spring Cloud掺逼。
-
單一應(yīng)用架構(gòu)
當(dāng)網(wǎng)站流量很小時(shí)吃媒,只需一個(gè)應(yīng)用,將所有功能都部署在一起吕喘,以減少部署節(jié)點(diǎn)和成本赘那。此時(shí),用于簡(jiǎn)化增刪改查工作量的數(shù)據(jù)訪問框架(ORM)是關(guān)鍵氯质。
-
垂直應(yīng)用架構(gòu)
當(dāng)訪問量逐漸增大募舟,單一應(yīng)用增加機(jī)器帶來的加速度越來越小,將應(yīng)用拆成互不相干的幾個(gè)應(yīng)用闻察,以提升效率拱礁。此時(shí),用于加速前端頁面開發(fā)的Web框架(MVC)是關(guān)鍵辕漂。
-
分布式服務(wù)架構(gòu)
當(dāng)垂直應(yīng)用越來越多呢灶,應(yīng)用之間交互不可避免,將核心業(yè)務(wù)抽取出來钉嘹,作為獨(dú)立的服務(wù)鸯乃,逐漸形成穩(wěn)定的服務(wù)中心,使前端應(yīng)用能更快速的響應(yīng)多變的市場(chǎng)需求跋涣。此時(shí)缨睡,用于提高業(yè)務(wù)復(fù)用及整合的分布式服務(wù)框架(RPC)是關(guān)鍵鸟悴。
-
流動(dòng)計(jì)算架構(gòu)
當(dāng)服務(wù)越來越多,容量的評(píng)估宏蛉,小服務(wù)資源的浪費(fèi)等問題逐漸顯現(xiàn)遣臼,此時(shí)需增加一個(gè)調(diào)度中心基于訪問壓力實(shí)時(shí)管理集群容量,提高集群利用率拾并。此時(shí)揍堰,用于提高機(jī)器利用率的資源調(diào)度和治理中心(SOA)是關(guān)鍵。
Zookeeper和Dubbo
Zookeeper
ZooKeeper 是一個(gè)分布式的嗅义,開放源碼的分布式應(yīng)用程序協(xié)調(diào)服務(wù)屏歹。它是一個(gè)為分布式應(yīng)用提供一致性服務(wù)的軟件,提供的功能包括:配置維護(hù)之碗、域名服務(wù)蝙眶、分布式同步、組服務(wù)等褪那。
Dubbo
Dubbo是Alibaba開源的分布式服務(wù)框架幽纷,它最大的特點(diǎn)是按照分層的方式來架構(gòu),使用這種方式可以使各個(gè)層之間解耦合(或者最大限度地松耦合)博敬。從服務(wù)模型的角度來看友浸,Dubbo采用的是一種非常簡(jiǎn)單的模型,要么是提供方提供服務(wù)偏窝,要么是消費(fèi)方消費(fèi)服務(wù)收恢,所以基于這一點(diǎn)可以抽象出服務(wù)提供方(Provider)和服務(wù)消費(fèi)方(Consumer)兩個(gè)角色。
代碼
安裝zookeeper組件
- 啟動(dòng)zookeeper組件
生產(chǎn)者-provider
-
引入依賴
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- Dubbo Spring Boot Starter --> <dependency> <groupId>org.apache.dubbo</groupId> <artifactId>dubbo-spring-boot-starter</artifactId> <version>2.7.4.1</version> </dependency> <!-- https://mvnrepository.com/artifact/org.apache.zookeeper/zookeeper --> <dependency> <groupId>org.apache.zookeeper</groupId> <artifactId>zookeeper</artifactId> <version>3.4.5</version> <type>pom</type> </dependency> <!-- https://mvnrepository.com/artifact/org.apache.curator/curator-framework --> <dependency> <groupId>org.apache.curator</groupId> <artifactId>curator-framework</artifactId> <version>2.12.0</version> </dependency> <!-- https://mvnrepository.com/artifact/org.apache.curator/curator-recipes --> <dependency> <groupId>org.apache.curator</groupId> <artifactId>curator-recipes</artifactId> <version>2.12.0</version> </dependency>
-
配置
dubbo.application.name=provider dubbo.registry.address=zookeeper://192.168.1.106:2181 dubbo.scan.base-packages=cn.net.credit.ticket.service
-
代碼
編寫TicketsService接口
package cn.net.credit.ticket.service; public interface TicketsService { public String getTicker(); }
編寫TicketServiceImpl實(shí)現(xiàn)類祭往,注意@Service屬于org.apache.dubbo.config.annotation.Service
package cn.net.credit.ticket.service; import org.apache.dubbo.config.annotation.Service; import org.springframework.stereotype.Component; @Component @Service public class TicketServiceImpl implements TicketsService { @Override public String getTicker() { return "《哪吒》"; } }
消費(fèi)者-comsumer
先啟動(dòng)生產(chǎn)者伦意,生產(chǎn)者服務(wù)會(huì)自動(dòng)將生產(chǎn)者導(dǎo)入到zookeeper注冊(cè)中心去
-
引入依賴
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- Dubbo Spring Boot Starter --> <dependency> <groupId>org.apache.dubbo</groupId> <artifactId>dubbo-spring-boot-starter</artifactId> <version>2.7.4.1</version> </dependency> <!-- https://mvnrepository.com/artifact/org.apache.zookeeper/zookeeper --> <dependency> <groupId>org.apache.zookeeper</groupId> <artifactId>zookeeper</artifactId> <version>3.4.5</version> <type>pom</type> </dependency> <!-- https://mvnrepository.com/artifact/org.apache.curator/curator-framework --> <dependency> <groupId>org.apache.curator</groupId> <artifactId>curator-framework</artifactId> <version>2.12.0</version> </dependency> <!-- https://mvnrepository.com/artifact/org.apache.curator/curator-recipes --> <dependency> <groupId>org.apache.curator</groupId> <artifactId>curator-recipes</artifactId> <version>2.12.0</version> </dependency>
-
配置
dubbo.application.name=comsumer dubbo.registry.address=zookeeper://192.168.1.106:2181
-
代碼
編寫TicketsService接口,注意與生產(chǎn)者的TicketsService目錄保持一致
package cn.net.credit.ticket.service; public interface TicketsService { public String getTicker(); }
編寫UserService硼补,注意@Reference屬于org.apache.dubbo.config.annotation.Reference
package cn.net.credit.user.service; import cn.net.credit.ticket.service.TicketsService; import org.apache.dubbo.config.annotation.Reference; import org.springframework.stereotype.Service;
@Service
public class UserService {
@Reference
TicketsService ticketsService;
public String getProvideTicket() {
return ticketsService.getTicker();
}
}
> 編寫測(cè)試類
```java
@SpringBootTest
class ComsumerApplicationTests {
@Resource
UserService userService;
@Test
public void test01() {
System.out.println("買到" + userService.getProvideTicket() +"的票了M匀狻!");
}
}
Spring Cloud
Spring Cloud是一個(gè)分布式的整體解決方案已骇。Spring Cloud 為開發(fā)者提供了在分布式系統(tǒng)(配置管理离钝,服務(wù)發(fā)現(xiàn),熔斷疾捍,路由奈辰,微代理,控制總線乱豆,一次性token奖恰,全局瑣,leader選舉,分布式session瑟啃,集群狀態(tài))中快速構(gòu)建的工具论泛,使用Spring Cloud的開發(fā)者可以快速的啟動(dòng)服務(wù)或構(gòu)建應(yīng)用、同時(shí)能夠快速和云平臺(tái)資源進(jìn)行對(duì)接蛹屿。
SpringCloud分布式開發(fā)五大常用組件
- 服務(wù)發(fā)現(xiàn)——Netflix Eureka
- 客服端負(fù)載均衡——Netflix Ribbon
- 斷路器——Netflix Hystrix
- 服務(wù)網(wǎng)關(guān)——Netflix Zuul
- 分布式配置——Spring Cloud Config
代碼
創(chuàng)建Eureka注冊(cè)中心
-
引入依賴
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency>
-
Eureka配置
server: port: 8761 eureka: instance: hostname: eureka-server #Eureka實(shí)例的主機(jī)名 client: register-with-eureka: false # 不把自己注冊(cè)到Eureka上 fetch-registry: false # 不從Eureka上來獲取服務(wù)的注冊(cè)信息 service-url: defaultZone: http://localhost:8761/eureka
-
開啟Eureka服務(wù) @EnableEurekaServer
/** * 注冊(cè)中心 * 1:配置Eureka信息 * 2:使用@EnableEurekaServer開啟Eureka服務(wù) */ @EnableEurekaServer @SpringBootApplication public class EurekaServerApplication { public static void main(String[] args) { SpringApplication.run(EurekaServerApplication.class, args); } }
-
啟動(dòng)Eureka服務(wù)屁奏,訪問Eureka
創(chuàng)建生產(chǎn)者
-
引入依賴
<properties> <java.version>1.8</java.version> <spring-cloud.version>Hoxton.RELEASE</spring-cloud.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-netflix-eureka-client</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </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>
-
配置
server: port: 8001 spring: application: name: provide-server eureka: instance: prefer-ip-address: true # 注冊(cè)服務(wù)的時(shí)候使用服務(wù)的ip地址 client: service-url: defaultZone: http://localhost:8761/eureka
-
代碼
TicketController
import cn.net.provide.service.TicketService; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import javax.annotation.Resource; @RestController public class TicketController { @Resource TicketService ticketService; @GetMapping("/ticket") public String getTicket(){ System.out.println("8001"); return ticketService.getTicket(); } }
TicketService
import org.springframework.stereotype.Service; @Service public class TicketService { public String getTicket(){ return "《哪吒!4砀骸7仄啊!》"; } }
使用8001犹撒,8002端口折联,啟動(dòng)兩個(gè)生產(chǎn)者服務(wù)
創(chuàng)建消費(fèi)者
-
引入依賴
<properties> <java.version>1.8</java.version> <spring-cloud.version>Hoxton.RELEASE</spring-cloud.version> </properties> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </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>
-
配置
server: port: 8500 spring: application: name: comsumer-user eureka: instance: prefer-ip-address: true # 注冊(cè)服務(wù)的時(shí)候使用服務(wù)的ip地址 client: service-url: defaultZone: http://localhost:8761/eureka
-
使用 @EnableEurekaClient開啟發(fā)現(xiàn)服務(wù)功能,使用@LoadBalanced配置負(fù)載均衡機(jī)制
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.web.client.RestTemplateBuilder; import org.springframework.cloud.client.loadbalancer.LoadBalanced; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; import org.springframework.context.annotation.Bean; import org.springframework.web.client.RestTemplate; @EnableEurekaClient // 開啟發(fā)現(xiàn)服務(wù)功能 @SpringBootApplication public class ComsumerUserApplication { public static void main(String[] args) { SpringApplication.run(ComsumerUserApplication.class, args); } @LoadBalanced // 使用負(fù)載均衡機(jī)制 @Bean public RestTemplate restTemplate() { return new RestTemplate(); } }
-
UserControl
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate; import javax.annotation.Resource; @RestController public class UserControl { @Resource RestTemplate restTemplate; @GetMapping("/buy") public String buyTicket() { return "購買了" + restTemplate.getForObject("http://PROVIDE-SERVER/ticket", String.class); } }
-
啟動(dòng)消費(fèi)者
訪問 http://localhost:8500/buy 測(cè)試4次识颊,兩臺(tái)生產(chǎn)者服務(wù)器各被訪問2次
結(jié)果:
2-provide.png