spring cloud + nacos入门案列

一:简介

   Spring Cloud是一系列框架的有序集合。它利用Spring Boot的开发便利性巧妙地简化了分布式系统基础设施的开发,如服务发现注册、配置中心、消息总线、负载均衡、断路器、数据监控等,都可以用Spring Boot的开发风格做到一键启动和部署。Spring Cloud并没有重复制造轮子,它只是将各家公司开发的比较成熟、经得起实际考验的服务框架组合起来,通过Spring Boot风格进行再封装屏蔽掉了复杂的配置和实现原理,最终给开发者留出了一套简单易懂、易部署和易维护的分布式系统开发工具包。

   spring cloud  五大核心组件(后续使用讲解)

服务发现 - Eureka

客服端负载均衡 -  Ribbon/Feign

断路器 - Hystrix

服务网关 -  Zuul / Gateway

分布式配置 - Spring Cloud Config

二:nacos(阿里的一款注册中心) 与 eureka的区别

1:提到注册中心,那么 必定遵循CAP原则

1、C (强一致性):  在分布式系统中的所有数据备份,在同一时刻是否同样的值。(等同于所有节点访问同一份最新的数据副本)

2、A (高可用性):  在集群中一部分节点故障后,集群整体是否还能响应客户端的读写请求。(对数据更新具备高可用性)

3、P (分区容错性):以实际效果而言,分区相当于对通信的时限要求。系统如果不能在时限内达成数据一致性,就意味着发生了分区的情况,必须就当前操作在C和A之间做出选择。

CAP原则的精髓就是要么AP,要么CP,要么AC,但是不存在CAP。如果在某个分布式系统中数据无副本, 那么系统必然满足强一致性条件, 因为只有独一数据,不会出现数据不一致的情况,此时C和P两要素具备,但是如果系统发生了网络分区状况或者宕机,必然导致某些数据不可以访问,此时可用性条件就不能被满足,即在此情况下获得了CP系统,但是CAP不可同时满足

2:eureka+spring cloud config: 

   eureka: 可以做注册中心,完全AP,支持注册中心之间的节点复制,同时支持服务端同时注册多个注册中心节点,

                  所以不存节点信息不一致的情况

  config: 单独服务,是从git仓库拉取配置信息,然后服务端从config服务里面拉取配置信息缓存到本地仓库

              这里配置的变更比较麻烦,他需要结合bus组件,同时约束了只能用rabbitmq和kafka来进行通知服务端进行配置变更

              但是保证了数据的一致性,因为他的配置信息在git仓库上,git仓库只有一个,就会数据一致

注:对于服务数量小于上千台来说,性能没有问题

3:nacos

     他同时支持AP和CP模式,他根据服务注册选择临时和永久来决定走AP模式还是CP模式,

    他这里支持CP模式对于我的理解来说,应该是为了配置中心集群,因为nacos可以同时作为注册中心和配置中心,

    因为他的配置中心信息是保存在nacos里面的,假如因为nacos其中一台挂掉后,还没有同步配置信息,

    就可能发生配置不一致的情况., 配置中心的配置变更是服务端有监听器,配置中心发生配置变化,

    然后服务端会监听到配置发生变化,从而做出改变


三:入门案列

  1:安装nacos到本地

首先 nacos工具包下载 提取码:hqrd   下载好后直接解压即可,

到官网下载的话  记得找到对应 /bin/startup.cmd 文件  右键编辑 --server.port=9090 为设置nacos端口 默认端口为8848

"%JAVA%" %JAVA_OPT% nacos.nacos %* --server.port=9090

双击执行.cmd文件 出现如下图 即可

可以直接 访问nacos的可视化界面 在网页地址栏输入 http://127.0.0.1:9090/nacos/index.html 用户名密码默认均为:nacos

2:创建测试项目  (项目目录结构如下)

2.1:创建项目父工程(spring-cloud-demo) 修改 pom.xml文件

<?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.2.2.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.zjw</groupId>
    <artifactId>spring-cloud-demo</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <name>spring-cloud-demo</name>
    <packaging>pom</packaging>
    <description>Demo project for Spring Boot</description>

    <modules>
        <module>provider</module>
        <module>consumer</module>
    </modules>

    <properties>
        <spring-boot.version>2.2.2.RELEASE</spring-boot.version>
        <spring-cloud.version>Greenwich.SR2</spring-cloud.version>
        <nacos.version>0.2.2.RELEASE</nacos.version>
        <openfeign.version>2.1.2.RELEASE</openfeign.version>
        <nacos-discovery.version>0.9.0.RELEASE</nacos-discovery.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
            <version>${openfeign.version}</version>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-alibaba-nacos-discovery</artifactId>
                <version>${nacos-discovery.version}</version>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring-boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>${nacos.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
</project>

2.2:添加服务提供者 provider

2.2.1:在父工程中添加一个module,作为服务的提供者(provider) pom.xml文件如下

<?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>com.zjw</groupId>
        <artifactId>spring-cloud-demo</artifactId>
        <version>1.0.0-SNAPSHOT</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <artifactId>provider</artifactId>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-alibaba-nacos-discovery</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

2.2.2:配置提供者application.yml


#################   cloud 初始化参数   ############################
oa:
  application: provider-server #应用名
  port: 8081 #项目端口号
  # nacos-ip: 100.168.1.151 #注册中心ip地址
  nacos-ip: 127.0.0.1  #注册中心ip地址
  nacos-port: 9090 #注册中心端口号
#################   cloud 初始化参数 end  ############################
server:
  port: ${oa.port}
  tomcat:
    uri-encoding: UTF-8
spring:
  application:
    name: ${oa.application}
  cloud:
    nacos:
      discovery:
        server-addr: ${oa.nacos-ip}:${oa.nacos-port}

2.2.3:在启动类上添加@EnableDiscoveryClient注解

package com.zjw.provider;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

@SpringBootApplication
@EnableDiscoveryClient
public class ProviderApplication {

    public static void main(String[] args) {
        SpringApplication.run(ProviderApplication.class, args);
    }

}

2.2.4:服务提供者写一个对外访问的接口

package com.zjw.provider.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class TestController {

    private final String name = "刚正青";

    private final String sex  = "男";



    @GetMapping("/test")
    public String test(){
        String temp = "服务注册-->" + "\r" +  "姓名:" + name + " 性别:" + sex;
        return temp;
    }
}

2.3:添加一个服务消费者 consumer

2.3.1:服务消费者添加 Fegin 与 熔断机制 hystrix 和提供者关联  (pom.xml)

<?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>com.zjw</groupId>
        <artifactId>spring-cloud-demo</artifactId>
        <version>1.0.0-SNAPSHOT</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <artifactId>consumer</artifactId>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-alibaba-nacos-discovery</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

2.3.2:配置消费者application.yml

oa:
  application: consumer-server
  prot: 8082
  nacos-ip: 127.0.0.1
  nacos-prot: 9090

server:
  port: ${oa.prot}
  tomcat:
    uri-encoding: UTF-8
spring:
  application:
    name: ${oa.application}
  cloud:
    nacos:
      discovery:
        server-addr: ${oa.nacos-ip}:${oa.nacos-prot}
feign:
  hystrix:
    enabled: true

2.3.3:消费者 核心启动类   需要添加@EnableDiscovery 和 @EnableFeignClients

package com.zjw.consumer;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;

@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class ConsumerApplication {

    public static void main(String[] args) {
        SpringApplication.run(ConsumerApplication.class, args);
    }

}

2.3.4:rpc远程调用 服务提供者 service接口 和 serviceImpl实现

package com.zjw.consumer.service;

import com.zjw.consumer.service.impl.TestServiceImpl;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;

@FeignClient(name = "provider-server",fallback = TestServiceImpl.class)
public interface ITestService {

    @GetMapping("/test")
    String test();
}
package com.zjw.consumer.service.impl;

import com.zjw.consumer.service.ITestService;
import org.springframework.stereotype.Component;


@Component
public class TestServiceImpl implements ITestService {

    @Override
    public String test(){
        return "远程调用服务失败";
    }
}

2.3.5:消费者服务添加一个对外访问接口 

package com.zjw.consumer.controller;

import com.zjw.consumer.service.ITestService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;

@RestController
public class TestController {

    @Resource
    ITestService testService;

    @GetMapping("/hello")
    public String test(){
        String temp = "服务发现-->";
        return temp + testService.test();
    }
}

3.启动服务

编译器出现如下样式:则服务注册成功

在nacos中 服务->列表 查看 健康实例数为1则说明服务注册成功

4.访问服务

这里可以直接访问 提供者 -->在访问 消费者

四:总结

这里可能有小伙伴不明白

1.访问消费者服务是为啥直接去掉了消费者  回来后有不走自己本身实现呢,那你自己写一个实现有什么有呢?

@FeignClient(name = "provider-server",fallback = TestServiceImpl.class)

其实只要理解这句就好,当外部调用消费者接口时到service层  通过spring cloud Feign远程调用到另一服务上 也就是provider,在那边完成调用返回自然不会 在回到本身再次执行本身实现了。

2.那你自己写一个实现有什么有呢?

在任何时候都可能出现 服务宕机,为了以防万一,方便查找。

当provider宕机时,也就是消费者找不到提供者,这时候 4-5秒 nacos发现异常 provider的健康实例就会变成0;

这时就会触发 fallback = TestServiceImpl.class 变换到 应用本身实现

(我这里先把 provider服务关闭  后再页面访问消费者接口  如图下)

3.分析流程

1.当外部访问消费者consumer接口时,服务调用到service层,通过rpc远程服务调用到 服务提供者provider中

我这边写的比较简单

但是第一:consumer中 实现其实是远程调用失败后 自动变换 到原先定义好的实现 (实际的业务操作是在 provider上的)

       第二:provider才是 业务处理方。实际业务中 这里会发生 service  dao等的 数据操作

   应用场景:consumer 要去那一条数据 但是这条数据在test2数据库中,而consumer是绑定了 test1数据库

                      假如不配置动态数据源 切换 

                   我们可以provider上绑定数据库test2  然后只要consumer远程调用到 provider上操作 test2数据即可

2.不用纠结 消费者 和 提供者 这两个概念

其实在这里  provider及是消费者  也是 提供者 

可以说是 A 服务要调用 B 服务 这是,我们就对AB关系,定义成A是B的消费者,B是A的提供者

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值