Springboot的分布式应用
在分布式系统中,国内常用的组合有Dubbo+Zookeeper,而spring推荐使用全栈的Spring框架:Springboot与SpringCloud的组合;
dubbo的特点:
- 明确的rpc调用接口API
- 出色的负载均衡表现
- 自动服务注册和发掘
- 高扩展性
- 运行时阻塞优化
- 可视化服务管理
Dubbo&Zookeeper
Dubbo(rpc远程处理框架)+Zookeeper(分布式注册管理框架)的架构图如下:
Dubbo与Springboot的使用步骤:
1、安装Zookeeper(可以虚拟机、docker容器
、本地zk),这里建议使用docker镜像
的方式
#a.首先上docker hub上下载官方的zookeeper镜像,可以使用docker中国进行镜像加
docker pull zookeeper
#b.检查镜像
docker images
#启动zk容器
docker run --name zookeeper_mac --restart always -p 2181 -d 53bd045d4a25
docker ps 查看启动的容器
2、创建一个empty的父工程,同时创建2个springboot的子模块,同时引入相关的zookeeper依赖和dubbo的starter依赖
<!-- dubbo-starter依赖-->
<dependency>
<groupId>com.alibaba.boot</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>0.2.0</version>
</dependency>
<!-- zk依赖 -->
<dependency>
<groupId>com.github.sgroschupf</groupId>
<artifactId>zkclient</artifactId>
<version>0.1</version>
</dependency>
3、将服务提供者注册到注册中心zookeeper
# a.首先在Provider的模块添加Dubbo-starter依赖、同时配置Dubbo的基本配置:
dubbo.application.name=module_name
dubbo.registry.address=zookeeper://localhost:2181
dubbo.scan.base-package=com.shufang.providerticket
#通信规则(通信协议和接口)
dubbo.protocol.name=dubbo
dubbo.protocol.port=20880
---
# b.然后在注册中心进行注册,将服务发布出去
@Service[Dubbo的服务]
@Component
class TicketProviderService(){
....
}
#启动provider
# c.在消费者测试服务
# 引入Dubbo依赖、zk依赖
# 配置dubbo的注册中心地址
# 订阅服务
@Service
public class ConsumerService {
@Reference
ProviderService providerService;
public String hello() {
String ticket = providerService.getTicket();
return "最终得出的结论是:" + ticket;
}
}
SpringCloud一栈式分布式处理框架
- Netflix-Eureka (服务中心) 类似于注册中心
- Netflix-Ribbon (客户端负载均衡)
- Netflix-Hystrix(断路器)
- Netflix-Zuul(服务网关)过滤请求
- SpringCloudConfig(分布式配置)
SpringCloud服务分为3个角色:
1.EurekaServer服务,可以做成高可用
2.Consumer,用来在注册中心发现并调用服务
3.Provider,用来在注册中心发布服务
EurekaServer创建与启动
1.首先在springboot中添加相关的依赖
<!--Eureka Server/-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
2.然后在application.yml中配置相关的Eureka配置
# 配置页面访问接口
server:
port: 8764
eureka:
instance:
hostname: eureka-server #eureka实例的主机名
client:
register-with-eureka: false #不做高可用的话就配置为false,不把自己注册进来
fetch-registry: false #不从eureka上获取服务的注册信息
service-url: http://localhost:8764/eureka/
3.在Server的主配置类上启动Eureka服务
@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}
4.启动Eureka服务,通过配置的端口号进行访问进入UI监控界面
http://localhost:8764/
Provider的创建与启动
1.首先在创建module的时候引入相关依赖
<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>
2.创建相应的Service、Controller实例
@RestController
public class TicketProviderController {
@Autowired
TicketProviderService service;
@GetMapping("/ticket")
public String getTicket() {
return service.getTicket();
}
}
@Service
public class TicketProviderService {
public String getTicket(){
return "<摔跤吧 弟弟!>";
}
}
3.配置相关的Eureka application.yml配置用来注册服务
#provider服务的访问接口
server:
port: 8001
#定义spring应用名字
spring:
application:
name: ticket-provider
#配置相关的eureka配置
eureka:
instance:
prefer-ip-address: true #注册服务的时候使用服务的ip地址
#这个与eureka-server保持一致
client:
service-url:
defaultZone: http://localhost:8009/eureka/
4.启动provider服务(前提是eureka-server已经启动)
5.继续访问eureka的Web页面,我们可以看到
6.温馨提示:同一个应用可以在Eureka-server上注册多个实例
Consumer的创建与启动
关键类:
- RestTemplate 用来远程调用的
1.在创建module的时候引入相关依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!--引入web的模块-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
2.引入相关的配置信息
server:
port: 8003
spring:
application:
name: ticket-consumer
eureka:
instance:
prefer-ip-address: true # 注册服务的时候使用服务的ip地址
client:
service-url:
defaultZone: http://localhost:8009/eureka/
3.在主配置类中,通过@EnableDiscoveryClient
来允许在注册中心发现服务
4.同时在容器中注入一个RestTemplate
实例,开启负载均衡@LoadBalanced
@SpringBootApplication
@EnableDiscoveryClient //开放允许发现注册服务的功能
public class TicketConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(TicketConsumerApplication.class, args);
}
/**
* 用来注入一个远程调用的实例
* @return
*/
@Bean
@LoadBalanced //启动负载均衡,假如一个应用启动了多个实例了
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
5.在consumer模块中创建相应的controller
@RestController
public class ConsumerController {
//自动注入restTemplate实例,进行远程调用
@Autowired
RestTemplate restTemplate;
@GetMapping("/buy")
public String buy(String name){
/**
*http://TICKET-PROVIDER/ticket 解析
* TICKET-PROVIDER 是在eureka中注册的spring.application.name,可以在eureka的界面查看
* /ticket 是在服务中的请求头,表示得到服务提供者的/ticket请求之后的结果
* String.class 将Object对象转换成String类型的数据
*/
String ticket = restTemplate.getForObject("http://TICKET-PROVIDER/ticket", String.class);
return name + "购买了电影票:-"+ticket;
}
}
6.然后在浏览器中访问consumer的接口
http://localhost:8003/buy?name=yourfather
返回结果示例:yourfather购买了电影票:-<摔跤吧,弟弟!>