SpringBoot 整合篇 筆記--Spring Boot與分布式
分布式應用
- 單一應用架構
- 垂直應用架構
- 分布式服務架構
- 流動計算架構
Zookeeper和Dubbo
ZooKeeper注冊中心
ZooKeeper 是一個分布式的,開放源碼的分布式應用程序協調服務。它是一個為分布式應用提供一致性服務的軟件,提供的功能包括:配置維護、域名服務、分布式同步、組服務等。
Dubbo分布式服務調用框架
Dubbo是Alibaba開源的分布式服務框架,它最大的特點是按照分層的方式來架構,使用這種方式可以使各個層之間解耦合(或者最大限度地松耦合)。從服務模型的角度來看,Dubbo采用的是一種非常簡單的模型,要么是提供方提供服務,要么是消費方消費服務,所以基於這一點可以抽象出服務提供方(Provider)和服務消費方(Consumer)兩個角色。
Dubbo分布式運行流程

具體代碼實現
1、安裝zookeeper作為注冊中心
2、編寫服務提供者
3、編寫服務消費者
4、整合dubbo
服務者:
/**
* 1、將服務提供者注冊到注冊中心
* 1、引入dubbo和zkclient相關依賴
* 2、配置dubbo的掃描包和注冊中心地址
* 3、使用@Service發布服務
*/
<?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> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.12.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.example</groupId> <artifactId>provider-ticket</artifactId> <version>0.0.1-SNAPSHOT</version> <name>provider-ticket</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> <dependency> <groupId>com.alibaba.boot</groupId> <artifactId>dubbo-spring-boot-starter</artifactId> <version>0.1.0</version> </dependency> <!--引入zookeeper的客戶端工具--> <!-- https://mvnrepository.com/artifact/com.github.sgroschupf/zkclient --> <dependency> <groupId>com.github.sgroschupf</groupId> <artifactId>zkclient</artifactId> <version>0.1</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
#application.properties
dubbo.application.name=provider-ticket dubbo.registry.address=zookeeper://10.87.3.137:2181 dubbo.scan.base-packages=com.example.providerticket.service
package com.example.providerticket.controller; import com.example.providerticket.service.TicketService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class TicketController { @Autowired TicketService ticketService; @GetMapping("/ticket") public String getTicket(){ return ticketService.getTicket(); } }
package com.example.providerticket.service; import com.alibaba.dubbo.config.annotation.Service; import org.springframework.stereotype.Component; @Component //加到容器中 @Service //將服務發布出去,是dubbo的service public class TicketServiceImpl implements TicketService { @Override public String getTicket() { return "《厲害了,我的國》"; } }
package com.example.providerticket.service; public interface TicketService { public String getTicket(); }
消費者:
<?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> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.12.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.example</groupId> <artifactId>consumer-user</artifactId> <version>0.0.1-SNAPSHOT</version> <name>consumer-user</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> <dependency> <groupId>com.alibaba.boot</groupId> <artifactId>dubbo-spring-boot-starter</artifactId> <version>0.1.0</version> </dependency> <!--引入zookeeper的客戶端工具--> <!-- https://mvnrepository.com/artifact/com.github.sgroschupf/zkclient --> <dependency> <groupId>com.github.sgroschupf</groupId> <artifactId>zkclient</artifactId> <version>0.1</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
#application.properties
dubbo.application.name=consumer-user dubbo.registry.address=zookeeper://10.87.3.137:2181
package com.example.consumeruser.service; import com.alibaba.dubbo.config.annotation.Reference; import com.example.providerticket.service.TicketService; import org.springframework.stereotype.Service; @Service//Spring的service public class UserService { @Reference//注意兩個工程的全類名相同 TicketService ticketService; public void hello(){ String ticket = ticketService.getTicket(); System.out.println("買到票了:"+ticket); } }
package com.example.providerticket.service; public interface TicketService { public String getTicket(); }

測試:
package com.example.consumeruser; import com.example.consumeruser.service.UserService; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; @RunWith(SpringRunner.class) @SpringBootTest public class ConsumerUserApplicationTests { @Autowired UserService userService; @Test public void contextLoads() { userService.hello(); } }
Spring Boot和Spring Cloud
Spring Cloud 入門
1、創建provider
2、創建consumer
3、引入Spring Cloud
4、引入Eureka注冊中心
5、引入Ribbon進行客戶端負載均衡
代碼實現
新建空工程:
創建注冊中心:eureka-server

<?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> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.14.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.example</groupId> <artifactId>eureka-server</artifactId> <version>0.0.1-SNAPSHOT</version> <name>eureka-server</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> <spring-cloud.version>Greenwich.SR6</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> </project>
server:
port: 8761
eureka:
instance:
hostname: eureka-server # eureka實例的主機名
client:
register-with-eureka: false #不把自己注冊到eureka上
fetch-registry: false #不從eureka上來獲取服務的注冊信息
service-url:
defaultZone: http://localhost:8761/eureka/
package com.example.eurekaserver; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; @EnableEurekaServer //開啟服務 @SpringBootApplication public class EurekaServerApplication { public static void main(String[] args) { SpringApplication.run(EurekaServerApplication.class, args); } }
啟動注冊中心:
踩坑1:請求是IP+端口,沒有上下文
踩坑2:啟動類要開啟 @EnableEurekaServer

創建服務者:provider-ticket

server: port: 8002 spring: application: name: provider-ticket eureka: instance: prefer-ip-address: true # 注冊服務的時候使用服務的ip地址 client: service-url: defaultZone: http://localhost:8761/eureka/ application.yml

package com.example.providerticket.service; import org.springframework.stereotype.Service; @Service public class TicketServiceImpl implements TicketService { @Override public String getTicket() { return "《厲害了,我的國》"; } }
package com.example.providerticket.controller; import com.example.providerticket.service.TicketService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class TicketController { @Autowired TicketService ticketService; @GetMapping("/ticket") public String getTicket(){ return ticketService.getTicket(); } }
創建消費者:consumer-user
spring:
application:
name: consumer-user
server:
port: 8200
eureka:
instance:
prefer-ip-address: true # 注冊服務的時候使用服務的ip地址
client:
service-url:
defaultZone: http://localhost:8761/eureka/
application.yml
package com.example.consumeruser; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; 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 @SpringBootApplication public class ConsumerUserApplication { public static void main(String[] args) { SpringApplication.run(ConsumerUserApplication.class, args); } @LoadBalanced //使用負載均衡機制 @Bean public RestTemplate restTemplate(){ return new RestTemplate(); } }
package com.example.consumeruser.cotroller; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate; @RestController public class UserController { @Autowired RestTemplate restTemplate; @GetMapping("/buy") public String buyTicket(String name){ String s = restTemplate.getForObject("http://PROVIDER-TICKET/ticket", String.class); return name+"購買了"+s; } }
測試:

SpringBoot與SpringCloud的版本對應詳細版
關於maven倉庫的版本列表spring-cloud-dependencies 版本列表可查看:
https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-dependencies
spring-boot-starter-parent 版本列表可查看:
https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-parent

關於spring cloud1.x版本和2.x版本區別
1.x版本pom.xml里幾個基本用到的jar長這樣:
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-hystrix</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-zipkin</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId> </dependency>
而在2.x版本中,比如我們需要eureka,去maven倉庫中可能會看到deprecated, please use spring-cloud-starter-netflix-eureka-client這類提示,包括使用ribbon也會有
<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-web</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency>
