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、端口)

微服务框架介绍文档_微服务框架介绍文档_02

入门案例
父模块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