分布式
一、分布式应用
在分布式系统中,国内常用Zookeeper+dubbo组合,而SpringBoot推荐使用全栈的spring、SpringBoot + SpringCloud。
二、Zookeeper和dubbo
1. Zookeeper
Zookeeper是一个分布式的,开放源代码的分布式应用程序协调服务。他是一个为分布式应用提供一致性服务的软件,提供的功能包括:配置维护、域名服务、分布式同步、组服务等;
1.Zookeeper docker 安装
#docker 搜索
docker search zookeeper
# 拉取镜像
docker pull zookeeper:lastest
# 查看镜像
docker images
# 启动镜像
docker run --name zk01 -p 2181:2181 --restart always -d zookeeper:3.8.0
2. Dubbo
Dubbo是Alibaba开源的分布式服务框架,她最大的特点是按照分层的方式来架构,使用这种方式可以使各个层之间解耦合。从服务模型的角度看,Dubbo采用的是一种非常简单的模型,要么是提供方提供服务,要么是消费方消费服务,所以基于这一点可以抽象出服务提供方(Provider)和服消费方(Consumer)两个角色。
3. dubbo 案例
1. 编写公共模块
- 创建普通的maven模块,命名dubbo-common;
- 编写公共类供provider和consumer调用;
package cn.hymll.springboot.provider.service.impl; public interface TicketService { String getTicket(); }
2.创建provider服务提供者SpringBoot工程
将服务提供者注册到注册中信:
- 引入maven依赖
<!-- https://mvnrepository.com/artifact/org.apache.dubbo/dubbo-spring-boot-starter --> <dependency> <groupId>org.apache.dubbo</groupId> <artifactId>dubbo-spring-boot-starter</artifactId> <version>2.7.15</version> </dependency> <!-- https://mvnrepository.com/artifact/org.apache.curator/curator-recipes --> <dependency> <groupId>org.apache.curator</groupId> <artifactId>curator-recipes</artifactId> <version>4.2.0</version> </dependency> <!-- https://mvnrepository.com/artifact/org.apache.zookeeper/zookeeper --> <dependency> <groupId>org.apache.zookeeper</groupId> <artifactId>zookeeper</artifactId> <version>3.8.0</version> </dependency>
- 引入自己编写的dubbo-common模块
- 编写配置文件
# 配置dubbo的扫描包和注册地址 dubbo.application.name=springboot-06-provider-ticket dubbo.registry.address=zookeeper://192.168.1.132:2181 #服务扫描包是dubbo-common中公共接口的包 dubbo.scan.base-packages=cn.hymll.springboot.provider.service
- 编写服务实现(使用@DubboService注解将服务发布出去)
package cn.hymll.springboot.provider.service.impl; @Component @DubboService//将服务发布出去 public class TicketServiceImpl implements TicketService { @Override public String getTicket() { return "<<厉害了,我的国>>"; } }
- 启动SpringBoot,可以看到服务已经注册成功;
@EnableDubbo//开启dubbo服务 @SpringBootApplication public class Springbot06ConsumerUserApplication { public static void main(String[] args) { SpringApplication.run(Springbot06ConsumerUserApplication.class, args); } }
注意:Linux需要配置/etc/hostname,并将host那么映射到/etc/hosts文件中,windows本地环境也要配置host映射,相应位置在C:\Windows\System32\drivers\etc\hosts,否则会报zookeeper连接不上;
3. 创建consumer消费者的SpringBoot工程
- 引入依赖(和dubbo-provider模块一样):
<!-- https://mvnrepository.com/artifact/org.apache.dubbo/dubbo-spring-boot-starter --> <dependency> <groupId>org.apache.dubbo</groupId> <artifactId>dubbo-spring-boot-starter</artifactId> <version>2.7.15</version> </dependency> <!-- https://mvnrepository.com/artifact/org.apache.curator/curator-recipes --> <dependency> <groupId>org.apache.curator</groupId> <artifactId>curator-recipes</artifactId> <version>4.2.0</version> </dependency> <!-- https://mvnrepository.com/artifact/org.apache.zookeeper/zookeeper --> <dependency> <groupId>org.apache.zookeeper</groupId> <artifactId>zookeeper</artifactId> <version>3.8.0</version> </dependency>
- 引入自己编写的dubbo-common模块
- 编写配置文件
#配置dubbo的注册中心地址 dubbo.application.name=springboot-06-consumer-user dubbo.registry.address=zookeeper://192.168.1.132:2181
- 引用服务
@Service public class UserService { @DubboReference//引用dubbo服务 private TicketService ticket; public void hello(){ final String ticket = this.ticket.getTicket(); System.out.println("买到票了,买了 " + ticket); } }
- 测试
@Autowired UserService userService; @Test void contextLoads() { userService.hello(); }
三、SpringBoot和SpringCloud
1. SpringCloud简介:
Springcloud是一个分布式的整体解决方案。Spring Cloud 为开发者提供了在分布式系统(配置管理、服务发现、熔断、路由、微代理、控制总线、一次性token、全局锁、leader选举、分布式session、集群状态)中快速构建的工具,使用SpringCloud的开发者可以快速的启动服务或构建应用、同时能够快速的和云平台资源进行对接。
2. SpringCloud分布式开发五大常用组件
- 服务发现:Netflix Eureka
- 客户端负载均衡:Netflix Ribbon
- 断路器: Netflix Hystrix
- 服务网关: Netflix Zuul
- 分布式配置: Spring Cloud Config
3. Eureka 服务配置启动
- 创建 springboot-06-eureka-server 模块,添加maven依赖:
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency>
- 构建配置文件
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/ #注册中信服务注册的地址
- 配置启动类
/** * 注册中心 */ @EnableEurekaServer @SpringBootApplication public class Springboot06EurekaServerApplication { public static void main(String[] args) { SpringApplication.run(Springboot06EurekaServerApplication.class, args); } }
- 启动并访问配置中心
4. Eureka 注册服务(Provider)
- 导入配置文件,创建工程
<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>
- 编写配置文件
server: port: 8001 spring: application: name: provider-ticket eureka: instance: prefer-ip-address: true #注册服务的时候使用ip地址 client: service-url: defaultZone: http://localhost:8761/eureka/ #注册中信服务注册的地址
- 编写服务类(Service)
@Service public class TicketService { public String getTicket(){ return "《误杀2》"; } }
- 编写Controller
@RestController public class TicketController { @Autowired private TicketService ticketService; @GetMapping("/ticket") public String getTicket(){ return ticketService.getTicket(); } }
- 启动Provider,会看到注册中心已经注册了provider-ticket服务
注意:Provider服务打成多个jar包后启动,多个服务都可以注册到Eureka,单机启动多个jar包要修改端口号,以免端口冲突报错;
5. Eureka 消费服务(Consumer)
- 创建maven工程,导入jar包
<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>
- 编写配置文件
spring: application: name: springboot-06-eureka-consumer server: port: 8200 eureka: instance: prefer-ip-address: true #注册服务的时候使用ip地址 client: service-url: defaultZone: http://localhost:8761/eureka/ #注册中信服务注册的地址
- 开启服务发现功能
@EnableDiscoveryClient//开启发现服务功能 @SpringBootApplication public class Springboot06EurekaConsumerApplication { public static void main(String[] args) { SpringApplication.run(Springboot06EurekaConsumerApplication.class, args); } @LoadBalanced//使用负载均衡请求机制 @Bean//使用 RestTemplate 动态请求到服务 public RestTemplate restTemplate(){ return new RestTemplate(); } }
- Controller实现功能
@RestController public class UserController { @Autowired private RestTemplate restTemplate; @GetMapping("/buy") public String buyTicket(String name){ //http请求地址不写具体的地址,而是写提供请求的服务名称,以便于向Eureka获取Provider final String object = restTemplate.getForObject("http://PROVIDER-TICKET/ticket", String.class); return name + "购买了" + object; } }
- 启动Consumer服务,访问:http://localhost:8200/buy 查看结果;