SpringCloud01_微服务架构、服务治理(Eureka组件、Consul组件、Nacos组件)
微服务架构
- 定义:把一个独立的服务拆分为多个功能独立可运行的服务,这些小型服务都在各自独立的进程中运行,服务之间一般通过 HTTP 的 RESTful API 进行通信协作。
- 优点:
- 降低耦合度
- 便于服务的横向扩容
SpringCloud概念
- 是一系列框架的集合
- 它只是将目前各家公司开发的比较成熟、经得起实际考验的服务框架组合起来。
- 通过 Spring Boot 风格进行再封装屏蔽掉了复杂的配置和实现原理,最终给开发者留出了一套简单易懂、易部署和易维护的分布式系统开发工具包
- 利用Spring Boot的开发便利性巧妙地简化了分布式系统基础设施的开发,如服务发现注册、配置中心、消息总线、负载均衡、 断路器、数据监控等,都可以用Spring Boot的开发风格做到一键启动和部署。
- Spring Cloud项目官方网址:https://spring.io/projects/spring-cloud
SpringCloud与dubbo区别
- SpringCloud 与 Dubbo 都是实现微服务有效的工具
- Dubbo是基于RPC协议实现远程调用的,同时要求所用语言必须是Java, 只是实现了服务治理
- SpringCloud规定服务之间通过http协议RESTful进行通信,子项目分别覆盖了微服务架构下的众多部件
- Dubbo性能较好,SpringCloud功能全
Eureka组件
- Eureka 包含两个组件:Eureka Server (注册中心) 和 Eureka Client (服务提供者、服务消费者)。
- 作用:服务的注册与发现(在微服务之间降低了服务之间的耦合度)
- 服务提供者注册服务到注册中心
- 服务消费者从注册中心获取服务信息(IP、端口)
入门案例
父模块spring-cloud-parent,
pom.xml
<groupId>com.it</groupId>
<artifactId>spring-cloud-parent</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
<modules>
<module>eureka-provider</module>
<module>eureka-consumer</module>
<module>eureka-server</module>
</modules>
<!--spring boot 环境 -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.0.RELEASE</version>
<relativePath/>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<!--spring cloud 版本-->
<spring-cloud.version>Greenwich.RELEASE</spring-cloud.version>
</properties>
<!--引入Spring Cloud 依赖-->
<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>
子模块eureka服务端,eureka-server
pom.xml
<parent>
<artifactId>spring-cloud-parent</artifactId>
<groupId>com.it</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>eureka-server</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- eureka-server -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
</dependencies>
application.yml
server:
port: 8761
# eureka 配置
# eureka 一共有4部分 配置
# 1. dashboard:eureka的web控制台配置
# 2. server:eureka的服务端配置
# 3. client:eureka的客户端配置
# 4. instance:eureka的实例配置
eureka:
instance:
hostname: localhost # 主机名
client:
service-url:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka # eureka服务端地址,将来客户端使用该地址和eureka进行通信
register-with-eureka: false # 是否将自己的路径 注册到eureka上。eureka server 不需要的,eureka provider client 需要
fetch-registry: false # 是否需要从eureka中抓取路径。eureka server 不需要的,eureka consumer client 需要
eurekaApp.java
@SpringBootApplication
// 启用EurekaServer
@EnableEurekaServer
public class EurekaApp {
public static void main(String[] args) {
SpringApplication.run(EurekaApp.class,args);
}
}
子模块eureka-provider
pom.xml
<parent>
<artifactId>spring-cloud-parent</artifactId>
<groupId>com.it</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>eureka-provider</artifactId>
<dependencies>
<!--spring boot web-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- eureka-client -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
</dependencies>
application.yml
server:
port: 8001
eureka:
instance:
hostname: localhost # 主机名
client:
service-url:
defaultZone: http://localhost:8761/eureka # eureka服务端地址,将来客户端使用该地址和eureka进行通信
spring:
application:
name: eureka-provider # 设置当前应用的名称。将来会在eureka中Application显示。将来需要使用该名称来获取路径
启动类ProviderApp.java
/**
* 启动类
*/
@EnableEurekaClient //该注解 在新版本中可以省略
@SpringBootApplication
public class ProviderApp {
public static void main(String[] args) {
SpringApplication.run(ProviderApp.class,args);
}
}
实体类Goods.java
public class Goods {
private int id;
private String title;//商品标题
private double price;//商品价格
private int count;//商品库存
全参和无参构造方法,getter和setter....
}
控制层ProviderController.java
@RestController
@RequestMapping("/goods")
public class GoodsController {
@Autowired
private GoodsService goodsService;
@GetMapping("/findOne/{id}")
public Goods findOne(@PathVariable("id") int id){
return new Goods(id,"华为手机",3999,10000);
}
}
子模块eureka-consumer
pom.xml
<parent>
<artifactId>spring-cloud-parent</artifactId>
<groupId>com.it</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>eureka-consumer</artifactId>
<dependencies>
<!--spring boot web-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- eureka-client -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
</dependencies>
application.yml
server:
port: 9000
eureka:
instance:
hostname: localhost # 主机名
client:
service-url:
defaultZone: http://localhost:8761/eureka # eureka服务端地址,将来客户端使用该地址和eureka进行通信
spring:
application:
name: eureka-consumer # 设置当前应用的名称。将来会在eureka中Application显示。将来需要使用该名称来获取路径
启动类ConsumerApp.java
@EnableDiscoveryClient // 激活DiscoveryClient
@EnableEurekaClient
@SpringBootApplication
public class ConsumerApp {
public static void main(String[] args) {
SpringApplication.run(ConsumerApp.class,args);
}
}
实体类Goods.java
public class Goods {
private int id;
private String title;//商品标题
private double price;//商品价格
private int count;//商品库存
全参和无参构造方法,getter和setter....
}
定义RestTemplate远程调用Bean
@Configuration
public class RestTemplateConfig {
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
控制层ConsumerController
@RestController
@RequestMapping("/order")
public class OrderController {
@Autowired
private RestTemplate restTemplate;
@Autowired
private DiscoveryClient discoveryClient;
@GetMapping("/goods/{id}")
public Goods findGoodsById(@PathVariable("id") int id){
System.out.println("findGoodsById..."+id);
/*
//远程调用Goods服务中的findOne接口
使用RestTemplate
1. 定义Bean restTemplate
2. 注入Bean
3. 调用方法
String url = "http://localhost:8000/goods/findOne/"+id;
Goods goods = restTemplate.getForObject(url, Goods.class);
*/
/*
动态从Eureka Server 中获取 provider 的 ip 和端口
1. 注入 DiscoveryClient 对象.激活
2. 调用方法
*/
//演示discoveryClient 使用
List<ServiceInstance> instances = discoveryClient.getInstances("EUREKA-PROVIDER");
//判断集合是否有数据
if(instances == null || instances.size() == 0){
//集合没有数据
return null;
}
ServiceInstance instance = instances.get(0);
String host = instance.getHost();//获取ip
int port = instance.getPort();//获取端口
System.out.println(host);
System.out.println(port);
String url = "http://"+host+":"+port+"/goods/findOne/"+id;
// 3. 调用方法
Goods goods = restTemplate.getForObject(url, Goods.class);
return goods;
}
}
Eureka高可用
- Eureka服务端相互注册即可组成集群
- server1
eureka:
client:
register-with-eureka: true #开启客户端功能
service-url:
defaultZone: http://localhost:8762/eureka,http://localhost:8763/eureka #注册服务到其它集群阶段,多台则逗号分隔
- server2
eureka:
client:
register-with-eureka: true #开启客户端功能
service-url:
defaultZone: http://localhost:8761/eureka,http://localhost:8763/eureka #注册服务到其它集群阶段,多台则逗号分隔
- client
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka,http://localhost:8762/eureka,http://localhost:8763/eureka #集群所有服务器的地址,逗号分隔
Consul组件
- 概述
- Consul 是由 HashiCorp 基于 Go 语言开发的,支持多数据中心,分布式高可用的服务发布和注册服务软件。用于实现分布式系统的服务发现与配置。
- 使用起来也较 为简单。具有天然可移植性(支持Linux、windows和Mac OS X);安装包仅包含一个可执行文件,方便部署 。
- 官网地址: https://www.consul.io
- 开发模式打开consul.exe: ./consul agent -dev
- 导入依赖
<!--consul 客户端-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>
<!--springboot监控,使用Consul必须导入-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
- application.yml配置
spring:
cloud:
consul:
host: localhost # consul 服务端的 ip
port: 8500 # consul 服务端的端口 默认8500
discovery:
service-name: ${spring.application.name} # 当前应用注册到consul的名称
prefer-ip-address: true # 注册ip
application:
name: consul-provider # 应用名称
#name: consul-consumer
Nacos组件
- 概述
- Nacos(Dynamic Naming and Configuration Service) 是阿里巴巴2018年7月开源的项目。
- Nacos = Spring Cloud注册中心 + Spring Cloud配置中心。
- 官网:https://nacos.io/
- 下载地址: https://github.com/alibaba/nacos/releases
- localhost:8848/nacos
- application.yml配置
server:
port: 8000
spring:
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848 # 配置nacos 服务端地址
application:
name: nacos-consumer # 服务名称
#name: nacos-provider
- 概述
- Nacos(Dynamic Naming and Configuration Service) 是阿里巴巴2018年7月开源的项目。
- Nacos = Spring Cloud注册中心 + Spring Cloud配置中心。
- 官网:https://nacos.io/
- 下载地址: https://github.com/alibaba/nacos/releases
- localhost:8848/nacos
- 导入依赖
<!--nacos-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<version>0.2.2.RELEASE</version>
</dependency>
<dependency>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-client</artifactId>
<version>1.1.0</version>
</dependency>
<!--springboot监控,使用Nacos必须导入-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
- application.yml配置
server:
port: 8000
spring:
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848 # 配置nacos 服务端地址
application:
name: nacos-consumer # 服务名称
#name: nacos-provider