Springcloud及Git线上配置详解

Java 投稿 59900 0 评论

Springcloud及Git线上配置详解

SpringCloud这个阶段该如何学?

三层架构 + MVC
    
框架:
    Spring IOC AOP
    SpringBoot,新一代的JavaEE开发标准,自动装配
    模块化~  all in one,代码没变化~
    
微服务架构四个核心问题?
    1.服务很多,客户端该怎么访问
    2.这么多服务?服务之间如何通信?
    3.这么多服务?如何治理?
    4.服务挂了怎么办?
    
解决方案:
    SpringCloud 生态! SpringBoot
    
    1.SpringCloud NetFlix 一站式解决方案!
    	api网关,zuul组件
    	Feign --- HttpClient --- Http通信方式,同步,阻塞
    	服务注册发现:Eureka
    	熔断机制:Hystrix
    	。
    
    2.Apache Dubbo Zookeeper 半自动,需要整合别人的!
    	API:没有,找第三方组件,或者自己实现
    	Dubbo
    	Zookeeper
    	没有:借助Hystrix
    	Dubbo这个方案并不完善~
    
    3.SpringCloud Alibaba 一站式解决方案!更简单
    	
    新概念:服务网格~Server Mesh
    	istio
    
    万变不离其宗
    	1.API
    	2.HTTP,RPC
    	3.注册与发现
    	4.熔断机制

注意:这部分内容是已经停止维护的SpringCloud Netflix,可与SpringCloud Alibaba进行对比,使用方法类似。

1、常见面试题

1.2、微服务之间是如何独立通讯的?

1.4、SpringBoot和SpringCloud,请你谈谈对他们的理解

1.6、微服务的优缺点分别是什么?说下你在项目开发中遇到的坑(微服务缺点)

1.8、eureka和zookeeper都可以提供服务注册与发现的功能,请说说两个的区别?

2、微服务概述

2.1、什么是微服务

什么是微服务?微服务(Microservice Architecture)是近几年流行的一种架构思想,关于它的概念很难一言以蔽之。

通常而言,微服务架构是一种架构模式,或者说是一种架构风格,他提倡将单一的应用程序划分成一组小的服务,每个服务运行在其独立的自己的进程内,服务之间互相协调,互相配置,为用户提供最终价值。服务之间采用轻量级的通信机制互相沟通,每个服务都围绕着具体的业务进行构建,并且能够被独立的部署到生产环境中,另外,应尽量避免统一的、集中式的服务管理体制,对具体的一个服务而言,应根据业务上下文,选择合适的语言,工具对其进行构建,可以有一个非常轻量级的集中式管理来协调这些服务,可以使用不同的语言来编写服务,也可以使用不同的数据存储;

可能有人觉得官方的话太过生涩,我们从技术维度来理解下:

2.2、微服务与微服务架构

微服务

IDEA 工具里面使用Maven开发的一个个独立的小Module,它具体是使用SpringBoot开发的一个小模块,专业的事情交给专业的模块来做,一个模块就做这一件事情
强调的是一个个的个体,每个个体完成一个具体的任务或者功能!

微服务架构

微服务架构是一种架构模式,它提倡将单一应用程序划分成一组小的服务,服务之间互相协调,互相配合,为用户提供最终价值。每个服务运行在其独立的进程中,服务与服务间采用轻量级的通信机制互相协作,每个服务都围绕着具体的业务进行构建,并且能够被独立的部署到生产环境中,另外,应尽量避免统一的、集中式的服务管理机制,对具体的一个服务而言,应根据业务上下文,选择合适的语言、工具对其进行构建。

2.3、微服务优缺点

优点

  • 单一职责原则

  • 每个服务足够内聚,足够小,代码容易理解,这样能聚焦一个指定的业务功能或业务需求;

  • 开发简单,开发效率提高,一个服务可能就是专一的只干一件事;

  • 微服务能够被小团队单独开发,这个小团队是2~5人的开发人员组成;

  • 微服务是松耦合的,是有功能意义的服务,无论是在开发阶段或部署阶段都是独立的;

  • 微服务能使用不同的语言开发;

  • 易于和第三方集成,微服务允许容易且灵活的方式集成自动部署,通过持续集成工具,如jenkins,Hudson,bamboo;

  • 微服务易于被一个开发人员理解、修改和维护,这样小团队能够更关注自己的工作成果。无需通过合作才能体现价值;

  • 微服务允许你利用融合最新技术

  • 微服务只是业务逻辑的代码,不会和HTML、CSS或其他界面混合

  • 每个微服务都有自己的存储能力,可以有自己的数据库,也可以有统一的数据库

缺点:

  • 开发人员要处理分布式系统的复杂性

  • 多服务运维难度,随着服务的增加,运维的压力也在增大

  • 系统部署依赖

  • 服务间通信成本

  • 数据一致性

  • 系统集成测试

  • 性能监控..。

2.4、微服务技术栈有哪些?

微服务条目 落地技术
服务开发 SpringBoot,Spring,SpringMVC
服务配置与管理 Netflix公司的Archaius、阿里的Diamond
服务注册与发现 Eureka、Consul、Zookeeper等
服务调用 Rest、RPC、gRPC
服务熔断器 Hystrix、Envoy等
负载均衡 Ribbon、Nginx等
服务接口调用(客户端调用服务的简化工具) Feign等
消息队列 Kafka、RabbitMQ、ActiveMQ等
服务配置中心管理 SpringCloudConfig、Chef等
服务路由(API网关) Zuul等
服务监控 Zabbix、Nagios、Metrics、Specatator等
全链路追踪 Zipkin、Brave、Dapper等
服务部署 Docker、OpenStack、Kubernetes等
数据流操作开发包 SpringCloud Stream(封装与Redis,Rabbit,Kafka等发送接收消息)
事件消息总线 SpringCloud Bus

2.5、为什么选择SpringCloud作为微服务架构

1、选型依据

  • 整体解决方案和框架成熟度

  • 社区热度

  • 可维护性

  • 学习曲线

2、当前各大IT公司用的微服务架构有哪些?

  • 阿里:dubbo + HFS

  • 京东:JSF

  • 新浪:Motan

  • 当当网 DubboX

  • .....。

功能点/服务框架 Netflix/SpringCloud Motan gRPC Thrift Dubbo/DubboX
功能定位 完整的微服务框架 RPC框架,但整合了ZK或Consul,实现集群环境的基本服务注册/发现 RPC框架 RPC框架 服务框架
支持Rest 是,Ribbon支持多种可插拔的序列化选择
支持RPC 是(Hession2)
支持多语言 是(Rest形式)?
负载均衡 是(服务端zuul+客户端Ribbon),zuul-服务,动态路由,云端负载均衡,Eureka(针对中间层服务器) 是(客户端) 是(客户端)
配置服务 Netflix Archaius,SpringCloudConfig Server集中配置 是(zookeeper提供)
服务调用链监控 是(zuul),zuul提供边缘服务,API网关
高可用/容错 是(服务端Hystrix+客户端Ribbon) 是(客户端) 是(客户端)
典型应用案例 Netflix Sina Google Facebook
社区活跃程度 一般 一般 2017年后重新开始维护,之前中断了5年
学习难度 中等
文档丰富 一般 一般 一般
其他 SpringCloud Bus为我们的应用程序带来了更多管理端点 支持降级 Netflix内部在开发集成gRPC IDL定义 实践的公司比较多

3、SpringCloud入门概述

3.1、SpringCloud是什么

SpringCloud官网:https://spring.io/

SpringCloud利用SpringBoot的开发便利性,巧妙地简化了分布式系统基础设施的开发,SpringCloud为开发人员提供了快速构建分布式系统的一些工具,包括配置管理、服务发现、熔断器、路由、微代理、事件总线、全局锁、决策竞选、分布式会话等等,他们都可以用SpringBoot的开发风格做到一键启动和部署。

最终给开发者留出了一套简单易懂,易部署和易维护的分布式系统开发工具包。

3.2、SpringCloud和SpringBoot关系

  • SpringBoot专注于快速方便的开发单个个体微服务。

  • SpringCloud是关注全局的微服务协调整理治理框架,它将SpringBoot开发的一个个单体微服务整合并管理起来,为各个微服务之间提供:配置管理、服务发现、熔断器、路由、微代理、事件总线、全局锁、决策竞选、分布式会话等等集成服务。

  • SpringBoot可以离开SpringCloud独立使用,开发项目,但是SpringCloud离不开SpringBoot,属于依赖关系

  • SpringBoot专注于快速、方便的开发单个个体微服务,SpringCloud关注全局的服务治理框架

3.3、Dubbo和SpringCloud技术选型

1、分布式+服务治理Dubbo

目前成熟的互联网架构:应用服务化拆分 + 消息中间件

2、Dubbo和SpringCloud对比

https://github.com/dubbo

https://github.com/spring-cloud

结果:


Dubbo Spring
服务注册中心 Zookeeper Spring Cloud NetFlix Eureka
服务调用方式 RPC REST API
服务监控 Dubbo-monitor Spring Boot Admin
熔断器 不完善 Spring Cloud Netflix Hystrix
服务网关 Spring Cloud Netflix Zuul
分布式配置 Spring Cloud Config
服务跟踪 Spring Cloud Sleuth
消息总线 Spring Cloud Bus
数据流 Spring Cloud Stream
批量任务 Spring Cloud Task

最大区别:SpringCloud抛弃了Dubbo的RPC通信,采用的是基于HTTP的REST方式。

品牌机与组装机的区别

社区支持与更新力度

设计模式 + 微服务拆分思想

总结:

人物:Dubbo重启维护开发的刘军,主要负责人之一

解决的问题域不一样:Dubbo的定位是一款RPC框架,SpringCloud的目标是微服务架构下的一站式解决方案。

3.4、SpringCloud能干嘛

  • Distributed/versioned configuration (分布式/版本控制配置)

  • Service registration and discovery (服务注册与发现)

  • Routing (路由)

  • Service-to-service calls (服务到服务的调用)

  • Load balancing (负载均衡配置)

  • Circuit Breakers (熔断器)

  • Distributed messaging (分布式消息管理)

  • .....。

3.5、SpringCloud在哪下

https://spring.io/projects/spring-cloud

Spring Cloud是一个由众多子项目组成的大型综合项目,每个子项目有不同的发行节奏,都维护着自己的发布版本号。Spring Cloud通过一个资源清单BOM(Bill of Materials)来管理每个版本的子项目清单。为避免与子项目的发布号混淆,所有没有采用版本号的方式,而是通过命名的方式。
这些版本名称的命名方式采用了伦敦地铁站的名称,同时根据字母表的顺序来对应版本时间顺序,比如:最早的Release版本:Angel,第二个Release版本:Brixton,然后是Camden、Dalston、Edgware,目前是按时间来对应版本。

参考书:

4、SpringCloud项目学习

4.1、总体介绍

  • 我们会使用一个Dept部门模块做一个微服务通用案例Consumer消费者(Client)通过REST调用Provider提供者(Server)提供的服务。

  • 回忆Spring,SpringMVC,MyBatis等以往学习的知识。

  • Maven的分包分模块架构复习

一个简单的Maven模块结构是这样的:
    
--- app-parent:一个父项目(app-parent)聚合很多子项目(app-util,app-dao,app-web...)
    |-- pom.xml
    |
    |-- app-core
    ||----pom.xml
    |
    |-- app-web
    ||----pom.xml
    ......

一个父工程带着多个子Module子模块

  • microservicecloud-api 【封装的整体entity/接口/公共配置等】

  • microservicecloud-provider-dept-8001 【服务提供者】

  • microservicecloud-consumer-dept-80 【服务消费者】

动手开干!

4.2、SpringCloud版本选择

https://start.spring.io/actuator/info

SpringCloud中各种组件技术的选择:

SpringCloud Netflix
越下边是使用人数最多的组件技术
图片数据是2020年1月份

4.3、Rest学习环境搭建:服务提供者

    <?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
    
        <groupId>com.kuang</groupId>
        <artifactId>springcloud</artifactId>
        <version>1.0-SNAPSHOT</version>
        <modules>
            <module>springcloud-api</module>
            <module>springcloud-provider-dept-8001</module>
        </modules>
    
        <!--打包方式 pom-->
        <packaging>pom</packaging>
    
        <properties>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <maven.compiler.source>1.8</maven.compiler.source>
            <maven.compiler.target>1.8</maven.compiler.target>
            <junit.version>4.13.2</junit.version>
            <lombok.version>1.18.22</lombok.version>
        </properties>
    
        <dependencyManagement>
            <dependencies>
                <!--SpringCloud的依赖-->
                <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-dependencies -->
                <dependency>
                    <groupId>org.springframework.cloud</groupId>
                    <artifactId>spring-cloud-dependencies</artifactId>
                    <version>2021.0.2</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
                <!--SpringBoot-->
                <dependency>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-dependencies</artifactId>
                    <version>2.6.7</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
                <!--数据库-->
                <dependency>
                    <groupId>mysql</groupId>
                    <artifactId>mysql-connector-java</artifactId>
                    <version>8.0.28</version>
                </dependency>
                <!--数据源-->
                <dependency>
                    <groupId>com.alibaba</groupId>
                    <artifactId>druid</artifactId>
                    <version>1.2.9</version>
                </dependency>
                <!--SpringBoot启动器-->
                <!--mybatis启动器-->
                <dependency>
                    <groupId>org.mybatis.spring.boot</groupId>
                    <artifactId>mybatis-spring-boot-starter</artifactId>
                    <version>2.2.2</version>
                </dependency>
                <!--日志和测试-->
                <dependency>
                    <groupId>ch.qos.logback</groupId>
                    <artifactId>logback-core</artifactId>
                    <version>1.2.11</version>
                </dependency>
                <!--junit-->
                <dependency>
                    <groupId>junit</groupId>
                    <artifactId>junit</artifactId>
                    <version>${junit.version}</version>
                </dependency>
                <!--lombok-->
                <dependency>
                    <groupId>org.projectlombok</groupId>
                    <artifactId>lombok</artifactId>
                    <version>${lombok.version}</version>
                </dependency>
                <!--Log4j-->
                <dependency>
                    <groupId>log4j</groupId>
                    <artifactId>log4j</artifactId>
                    <version>1.2.17</version>
                </dependency>
            </dependencies>
        </dependencyManagement>
    
    </project>
  1. 在父项目中新建一个子模块springcloud-api,导入子模块依赖

    <?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <parent>
            <artifactId>springcloud</artifactId>
            <groupId>com.kuang</groupId>
            <version>1.0-SNAPSHOT</version>
        </parent>
        <modelVersion>4.0.0</modelVersion>
    
        <artifactId>springcloud-api</artifactId>
    
        <properties>
            <maven.compiler.source>8</maven.compiler.source>
            <maven.compiler.target>8</maven.compiler.target>
        </properties>
    
        <!--当前的Module自己需要的依赖,如果父依赖中已经配置了版本,这里就不用写了-->
        <dependencies>
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
            </dependency>
        </dependencies>
    
    </project>
  2. 新建数据库db01,新建表dept如下图

  3. @Data
    @NoArgsConstructor
    @Accessors(chain = true) //链式写法
    public class Dept implements Serializable { //Dept 实体类, orm mysql--dept 类表关系映射
    
        private Long deptno; //主键
        private String dname;
    
        //这个数据是存在哪个数据库的字段~ 微服务,一个服务对应一个数据库,同一个信息可能存在不同的数据库
        private String db_source;
    
        public Dept(String dname){ //构造器
            this.dname = dname;
        }
    
        /*
        链式写法:
            Dept dept = new Dept();
    
            dept.setDeptNo(11).setDname('ssss').setDb_source('001');
    
         */
    
    }
  4. 在父项目中新建一个子模块springcloud-provider-dept-8001,导入依赖

    <?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <parent>
            <artifactId>springcloud</artifactId>
            <groupId>com.kuang</groupId>
            <version>1.0-SNAPSHOT</version>
        </parent>
        <modelVersion>4.0.0</modelVersion>
    
        <artifactId>springcloud-provider-dept-8001</artifactId>
    
        <properties>
            <maven.compiler.source>8</maven.compiler.source>
            <maven.compiler.target>8</maven.compiler.target>
        </properties>
    
        <dependencies>
            <!--我们需要拿到实体类,所以要配置api module-->
            <dependency>
                <groupId>com.kuang</groupId>
                <artifactId>springcloud-api</artifactId>
                <version>1.0-SNAPSHOT</version>
            </dependency>
            <!--junit-->
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
            </dependency>
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
            </dependency>
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid</artifactId>
            </dependency>
            <dependency>
                <groupId>ch.qos.logback</groupId>
                <artifactId>logback-core</artifactId>
            </dependency>
            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
            </dependency>
            <!--test-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-test</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <!--jetty-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-jetty</artifactId>
            </dependency>
            <!--热部署工具-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-devtools</artifactId>
            </dependency>
    
        </dependencies>
    
    </project>
  5. 新建spring配置文件,mybaits配置文件,mapper配置文件结构如下

  6. application.yml

    server:
      port: 8001
    
    #mybatis配置
    mybatis:
      type-aliases-package: com.kuang.springcloud.pojo
      config-location: classpath:mybatis/mybatis-config.xml
      mapper-locations: classpath:mybatis/mapper/*.xml
    
    #spring的配置
    spring:
      application:
        name: springcloud-provider-dept
      datasource:
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://localhost:3306/db01?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT
        username: root
        password: 123456

    mybatis-config.xml

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE configuration
            PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-config.dtd">
    
    <configuration>
        <settings>
            <!--开启二级缓存-->
            <setting name="cacheEnabled" value="true"/>
        </settings>
    </configuration>

    DeptMapper.xml

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    
    <mapper namespace="com.kuang.springcloud.dao.DeptDao">
    
        <insert id="addDept" parameterType="Dept">
            insert into db01.dept (dname, db_source)
            values (#{dname},DATABASE());
        </insert>
    
        <select id="queryDeptById" resultType="Dept" parameterType="Long">
            select * from db01.dept where deptno = #{deptno};
        </select>
    
        <select id="queryAll" resultType="Dept">
            select * from db01.dept;
        </select>
    
    </mapper>
  7. 新建mapper(dao)层,service层,controller层结构如下

  8. DeptDao

    @Mapper
    @Repository
    public interface DeptDao {
    
        public boolean addDept(Dept dept);
    
        public Dept queryDeptById(Long id);
    
        public List<Dept> queryAll();
    
    }

    DeptService

    public interface DeptService {
    
        public boolean addDept(Dept dept);
    
        public Dept queryDeptById(Long id);
    
        public List<Dept> queryAll();
    
    }

    DeptServiceImpl

    @Service
    public class DeptServiceImpl implements DeptService{
    
        @Autowired
        private DeptDao deptDao;
    
        @Override
        public boolean addDept(Dept dept) {
            return deptDao.addDept(dept);
        }
    
        @Override
        public Dept queryDeptById(Long id) {
            return deptDao.queryDeptById(id);
        }
    
        @Override
        public List<Dept> queryAll() {
            return deptDao.queryAll();
        }
    }

    DeptController

    //提供Restful服务!
    @RestController
    public class DeptController {
    
        @Autowired
        private DeptService deptService;
    
        @PostMapping("/dept/add")
        public boolean addDept(Dept dept){
            return deptService.addDept(dept);
        }
    
        @GetMapping("/dept/get/{id}")
        public Dept get(@PathVariable("id") Long id){
            return deptService.queryDeptById(id);
        }
    
        @GetMapping("/dept/list")
        public List<Dept> queryAll(){
            return deptService.queryAll();
        }
    }
  9. 编写启动类,与controller,service,dao文件夹位于同一级

    //启动类
    @SpringBootApplication
    public class DeptProvider_8001 {
        public static void main(String[] args) {
            SpringApplication.run(DeptProvider_8001.class,args);
        }
    }

4.4、Rest学习环境搭建:服务消费者

    在父项目中新建一个子模块springcloud-consumer-dept-80,导入依赖

    <?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <parent>
            <artifactId>springcloud</artifactId>
            <groupId>com.kuang</groupId>
            <version>1.0-SNAPSHOT</version>
        </parent>
        <modelVersion>4.0.0</modelVersion>
    
        <artifactId>springcloud-consumer-dept-80</artifactId>
    
        <properties>
            <maven.compiler.source>8</maven.compiler.source>
            <maven.compiler.target>8</maven.compiler.target>
        </properties>
    
        <!--实体类+web-->
        <dependencies>
            <dependency>
                <groupId>com.kuang</groupId>
                <artifactId>springcloud-api</artifactId>
                <version>1.0-SNAPSHOT</version>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <!--热部署工具-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-devtools</artifactId>
            </dependency>
        </dependencies>
    
    </project>
  1. 新建配置文件application.yml

    server:
      port: 80
  2. 新建一个配置类ConfigBean.java,获取RestTemplate并注入Bean中

    @Configuration
    public class ConfigBean { //@Configuration -- spring applicationContext.xml
    
        @Bean
        public RestTemplate getRestTemplate(){
            return new RestTemplate();
        }
    
    }
  3. 新建一个消费者接口DeptConsumerController.java

    @RestController
    public class DeptConsumerController {
    
        //理解:消费者,不应该有service层~
        //RestFul RestTemplate... 供我们直接调用就可以了!注册到Spring中
        //(url, 实体: Map, Class<T> responseType)
        @Autowired
        private RestTemplate restTemplate;//提供多种便捷访问远程http服务的方法,简单的restful服务模板~
    
        private static final String REST_URL_PREFIX = "http://localhost:8001";
    
        @RequestMapping("/consumer/dept/add")
        public boolean add(Dept dept){
            return restTemplate.postForObject(REST_URL_PREFIX+"/dept/add",dept,Boolean.class);
        }
    
        @RequestMapping("/consumer/dept/get/{id}")
        public Dept get(@PathVariable("id") Long id){
            return restTemplate.getForObject(REST_URL_PREFIX+"/dept/get/"+id,Dept.class);
        }
    
        @RequestMapping("/consumer/dept/list")
        public List<Dept> list(){
            return restTemplate.getForObject(REST_URL_PREFIX+"/dept/list",List.class);
        }
    
    }
  4. 新建一个消费者启动类DeptConsumer_80.java

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

4.5、SpringCloud中不同技术使用的大体流程

1、导入依赖
2、编写配置文件
3、开启这个功能 @Enable...
4、配置类

5、Eureka服务注册与发现

5.1、什么是Eureka

  • Eureka:怎么读?

  • Netflix在设计Eureka时,遵循的就是AP原则

  • Eureka是Netflix的一个子模块,也就是核心模块之一。Eureka是一个基于REST的服务,用于定位服务,以实现云端中间层服务发现和故障转移,服务注册与发现对于微服务来说是非常重要的,有了服务注册与发现,只需要使用服务的标识符,就可以访问到服务,而不需要修改服务调用的配置文件了,功能类似于Dubbo的注册中心,比如Zookeeper;

5.2、原理讲解

  • Eureka的基本结构

    • SpringCloud封装了NetFlix公司开发的Eureka模块来实现服务注册和发现(对比Zookeeper)

    • Eureka采用了C-S的架构设计,EurekaServer作为服务注册功能的服务器,他是服务注册中心

    • 而系统中的其他微服务。使用Eureka的客户端连接到EurekaServer并维持心跳连接。这样系统的维护人员就可以通过EurekaServer来监控系统中各个微服务是否正常运行,SpringCloud的一些其他模块(比如Zuul)就可以通过EurekaServer来发现系统中的其他微服务,并执行相关的逻辑操作;

    • 和Dubbo架构对比

    • Eureka包含两个组件:Eureka ServerEureka Client

    • Eureka Server提供服务注册服务,各个节点启动后,会在Eureka Server中进行注册,这样Eureka Server中的服务注册表中将会存储所有可用服务节点的信息,服务节点的信息可以在界面中直观的看到。

    • Eureka Client是一个Java客户端,用于简化Eureka Server的交互,客户端同时也具备一个内置的,使用轮询负载算法的负载均衡器。在应用启动后,将会向Eureka Server发送心跳(默认周期为30秒)。如果Eureka Server在多个心跳周期内没有接收到某个节点的心跳,Eureka Server将会从服务注册表中把这个服务节点移除掉(默认周期为90秒)

  • 三大角色

    • Eureka Server:提供服务的注册与发现。zookeeper

  • Service Provider:将自身服务注册到Eureka中,从而使消费方能够找到。

  • Service Consumer:服务消费方从Eureka中获取注册服务列表,从而找到消费服务。

自我保护机制:好死不如赖活着

  • 当EurekaServer节点在短时间内丢失过多客户端时(可能发生了网络分区故障),那么这个节点就会进入自我保护模式。一旦进入该模式,EurekaServer就会保护服务注册表中的信息,不再删除服务注册表中的数据(也就是不会注销任何微服务)。当网络故障恢复后,EurekaServer节点会自动退出自我保护模式。

5.3、Eureka实现代码

    <!--EUREKA依赖-->
    <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-eureka -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-eureka</artifactId>
        <version>1.4.7.RELEASE</version>
    </dependency>
    <!--actuator完善监控信息-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
  1. 新建配置文件application.yml

    server:
      port: 7001
    
    #Eureka配置
    eureka:
      instance:
        hostname: localhost #Eureka服务端的实例名称
      client:
        register-with-eureka: false #表示是否向eureka注册中心注册自己
        fetch-registry: false #fetch-registry如果为false,则表示自己为注册中心
        service-url: #监控页面~
          defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
  2. 新建启动类EurekaServer_7001.java,设置EurakeServer注解

    //启动之后,访问http://localhost:7001/
    @SpringBootApplication
    @EnableEurekaServer //EnableEurekaServer 服务端的启动类,可以接受别人注册进来~
    public class EurekaServer_7001 {
        public static void main(String[] args) {
            SpringApplication.run(EurekaServer_7001.class,args);
        }
    }
  3. 在父依赖中添加build代码,解决info无效的问题

    <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                    <executions>
                        <execution>
                            <goals>
                                <goal>build-info</goal>
                            </goals>
                        </execution>
                    </executions>
                </plugin>
            </plugins>
        </build>
  4. 在服务者模块springcloud-provider-dept-8001中导入Eureka依赖

    <!--EUREKA依赖-->
    <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-eureka -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-eureka</artifactId>
        <version>1.4.7.RELEASE</version>
    </dependency>
    <!--actuator完善监控信息-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
  5. 新建配置文件application.yml

    server:
      port: 8001
    
    #mybatis配置
    mybatis:
      type-aliases-package: com.kuang.springcloud.pojo
      config-location: classpath:mybatis/mybatis-config.xml
      mapper-locations: classpath:mybatis/mapper/*.xml
    
    #spring的配置
    spring:
      application:
        name: springcloud-provider-dept
      datasource:
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://localhost:3306/db01?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT
        username: root
        password: 123456
    
    #Eureka的配置,服务注册到哪里
    eureka:
      client:
        service-url:
          defaultZone: http://localhost:7001/eureka/
    
      instance:
        instance-id: springcloud-provider-dept-8001 #修改eureka上的默认描述信息!
        hostname: localhost #修改主机名称
    
    #解决url过滤问题
    management:
      endpoints:
        web:
          exposure:
            include: "*"
    
    #info配置,无效,创建单独的build-info.properties解决,注意格式
    info:
      app-name: kuangshen-springcloud
      company-name: blog.kuangstudy.com
  6. 新建info配置文件META-INF/build-info.properties

    build.app_name=kuangshen-springcloud
    build.company_name=blog.kuangstudy.com
  7. 在服务者的controller文件DeptController.java中配置新的方法获取注册的微服务的具体信息

    //提供Restful服务!
    @RestController
    public class DeptController {
    
        @Autowired
        private DeptService deptService;
    
        //获取一些配置的信息,得到具体的微服务!
        @Autowired
        private DiscoveryClient client;
    
        @PostMapping("/dept/add")
        public boolean addDept(Dept dept){
            return deptService.addDept(dept);
        }
    
        @GetMapping("/dept/get/{id}")
        public Dept get(@PathVariable("id") Long id){
            return deptService.queryDeptById(id);
        }
    
        @GetMapping("/dept/list")
        public List<Dept> queryAll(){
            return deptService.queryAll();
        }
    
        //注册进来的微服务,获取一些消息
        @GetMapping("/dept/discovery")
        public Object Discovery(){
            //获取微服务列表的清单
            List<String> services = client.getServices();
            System.out.println("discovery=>services:"+services);
    
            //得到一个具体的微服务信息,通过具体的微服务id,applicationName
            List<ServiceInstance> instances = client.getInstances("SPRINGCLOUD-PROVIDER-DEPT");
    
            for (ServiceInstance instance : instances) {
                System.out.println(
                        instance.getHost()+"\t"+
                        instance.getPort()+"\t"+
                        instance.getUri()+"\t"+
                        instance.getServiceId()
                );
            }
    
            return this.client;
        }
    }
  8. 在服务者的启动类中添加EurekaClient及DiscoveryClient注解

    //启动类
    @SpringBootApplication
    @EnableEurekaClient //在服务启动后自动注册到Eureka中!
    @EnableDiscoveryClient //服务发现~
    public class DeptProvider_8001 {
        public static void main(String[] args) {
            SpringApplication.run(DeptProvider_8001.class,args);
        }
    }
  9. 先运行springcloud-eureka-7001,再运行springcloud-provider-dept-8001,主界面如下,可点击查看服务者相关信息

5.3、Eureka集群环境配置

    在C盘下修改接口配置,进入文件夹C:\Windows\System32\drivers\etc\hosts,在文件末尾添加不同url映射到localhost接口

  1. 启动类

    //启动之后,访问http://localhost:7001/
    @SpringBootApplication
    @EnableEurekaServer //EnableEurekaServer 服务端的启动类,可以接受别人注册进来~
    public class EurekaServer_7001 {
        public static void main(String[] args) {
            SpringApplication.run(EurekaServer_7001.class,args);
        }
    }
    =======================================
    //启动之后,访问http://localhost:7002/
    @SpringBootApplication
    @EnableEurekaServer //EnableEurekaServer 服务端的启动类,可以接受别人注册进来~
    public class EurekaServer_7002 {
        public static void main(String[] args) {
            SpringApplication.run(EurekaServer_7002.class,args);
        }
    }
    =======================================
    //启动之后,访问http://localhost:7003/
    @SpringBootApplication
    @EnableEurekaServer //EnableEurekaServer 服务端的启动类,可以接受别人注册进来~
    public class EurekaServer_7003 {
        public static void main(String[] args) {
            SpringApplication.run(EurekaServer_7003.class,args);
        }
    }

    配置文件

    server:
      port: 7001
    
    #Eureka配置
    eureka:
      instance:
        hostname: eureka7001.com #Eureka服务端的实例名称
      client:
        register-with-eureka: false #表示是否向eureka注册中心注册自己
        fetch-registry: false #fetch-registry如果为false,则表示自己为注册中心
        service-url: #监控页面~
          defaultZone: http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
    #######################################
    server:
      port: 7002
    
    #Eureka配置
    eureka:
      instance:
        hostname: eureka7002.com #Eureka服务端的实例名称
      client:
        register-with-eureka: false #表示是否向eureka注册中心注册自己
        fetch-registry: false #fetch-registry如果为false,则表示自己为注册中心
        service-url: #监控页面~
          defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7003.com:7003/eureka/
    #######################################
    server:
      port: 7003
    
    #Eureka配置
    eureka:
      instance:
        hostname: eureka7003.com #Eureka服务端的实例名称
      client:
        register-with-eureka: false #表示是否向eureka注册中心注册自己
        fetch-registry: false #fetch-registry如果为false,则表示自己为注册中心
        service-url: #监控页面~
          defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/

    依赖与springcloud-eureka-7001相同

    <!--导包-->
    <dependencies>
        <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-eureka-server -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka-server</artifactId>
            <version>1.4.7.RELEASE</version>
        </dependency>
    
    </dependencies>
  2. 修改服务提供者的配置文件,使其向三个Eureka发布

    server:
      port: 8001
    
    #mybatis配置
    mybatis:
      type-aliases-package: com.kuang.springcloud.pojo
      config-location: classpath:mybatis/mybatis-config.xml
      mapper-locations: classpath:mybatis/mapper/*.xml
    
    #spring的配置
    spring:
      application:
        name: springcloud-provider-dept
      datasource:
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://localhost:3306/db01?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT
        username: root
        password: 123456
    
    #Eureka的配置,服务注册到哪里
    eureka:
      client:
        service-url:
          defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
    
      instance:
        instance-id: springcloud-provider-dept-8001 #修改eureka上的默认描述信息!
        hostname: localhost #修改主机名称
    
    #解决url过滤问题
    management:
      endpoints:
        web:
          exposure:
            include: "*"
    
    #info配置,无效,创建单独的build-info.properties解决,注意格式
    info:
      app-name: kuangshen-springcloud
      company-name: blog.kuangstudy.com
  3. 运行三个Eureka及一个服务提供者,其中两个Eureka界面如下,可见每个Eureka都可见其他两个Eureka

5.4、对比Zookeeper

回顾CAP原则

NoSQL(redis、mongdb)===> CAP

ACID是什么?

  • A(Atomicity)原子性

  • C(Consistency)一致性

  • I(Isolation)隔离性

  • D(Durability)持久性

CAP是什么?

  • C(Consistency)强一致性

  • A(Availability)可用性

  • P(Partition tolerance)分区容错性

CAP理论的核心

  • 一个分布式系统不可能同时很好的满足一致性、可用性和分区容错性这三个需求

  • 根据CAP原理,将NoSQL数据库分成了满足CA原则,满足CP原则和满足AP原则三大类:

    • CA:单点集群,满足一致性,可用的系统,通常可扩展性较差(P分区容错性差)

    • CP:满足一致性,分区容错性的系统,通常性能不是特别高(A可用性差)

    • AP:满足可用性,分区容错性的系统,通常可能对一致性要求低一些(C一致性差)

作为服务注册中心,Eureka比Zookeeper好在哪里?

由于分区容错性P在分布式系统中是必须要保证的,因此我们只能在A和C之间进行权衡。

  • Zookeeper保证的是CP;

  • Eureka保证的是AP;

Zookeeper保证的是CP

Eureka保证的是AP

Eureka各个节点都是平等的,几个节点挂掉不会影响正常节点的工作,剩余的节点依然可以提供注册和查询服务。而Eureka的客户端在向某个Eureka注册时,如果发现连接失败,则会自动切换至其他节点,只要有一台Eureka还在,就能保证注册服务的可用性,只不过查到的

  1. Eureka不再从注册列表中移除因为长时间没收到心跳而应该过期的服务

  2. Eureka仍然能够接受新服务的注册和查询请求,但是不会被同步到其他节点上(即保证当前节点依然可用)

  3. 当网络稳定时,当前实例新的注册信息会被同步到其他节点中

因此,Eureka可以很好地应对因网络故障导致部分节点失去联系的情况,而不会像zookeeper那样使整个注册服务瘫痪。

6、Ribbon

spring-cloud-starter-netflix-eureka-client中已经内置了Ribbon,再导入Ribbon依赖会冲突。

6.1、Ribbon简介

简单地说,Ribbon是Netflix发布的开源项目,主要功能是提供客户端的软件负载均衡算法和服务调用。Ribbon客户端组件提供一系列完善的配置项如连接超时,重试等。简单地说,就是在配置文件中列出Load Balancer(简称LB)后面所有机器,Ribbon会自动的帮助你基于某种规则(如简单轮询,随机连接等)去连接这些机器。我们很容易使用Ribbon实现自定义的负载均衡算法

https://github.com/Netflix/ribbon

Ribbon的职能:LB负载均衡,简单地说就是将用户的请求平均分摊到多个服务上,从而达到系统的HA(高可用)。

Ribbon本地负载均衡客户端和Nginx服务端负载均衡区别:

Ribbon是本地(客户端)负载均衡,在调用微服务接口时候,会在注册中心上获取注册信息服务列表之后缓存到JVM本地,从而在本地实现RPC远程服务调用技术

集中式LB

进程内LB

Ribbon就属于进程内LB,它只是一个类库,集成于消费方进程,消费方通过它来获取到服务提供方的地址。

示意图:

6.2、Ribbon初体验

    <!--Eureka-->
    <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-eureka -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-eureka</artifactId>
        <version>1.4.7.RELEASE</version>
    </dependency>
  1. 在该模块中增加Eureka的配置

    server:
      port: 80
    
    #Eureka配置
    eureka:
      client:
        register-with-eureka: false #不向Eureka注册自己
        service-url:
          defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
  2. 在配置类中,增加@LoadBalanced注解,以使用配置负载均衡实现RestTemplate

    @Configuration
    public class ConfigBean { //@Configuration -- spring applicationContext.xml
    
        //配置负载均衡实现RestTemplate
        @Bean
        @LoadBalanced //Ribbon
        public RestTemplate getRestTemplate(){
            return new RestTemplate();
        }
    
    }
  3. 在controller层中DeptConsumerController.java中将访问地址改为服务名

    @RestController
    public class DeptConsumerController {
    
        //理解:消费者,不应该有service层~
        //RestFul RestTemplate... 供我们直接调用就可以了!注册到Spring中
        //(url, 实体: Map, Class<T> responseType)
        @Autowired
        private RestTemplate restTemplate;//提供多种便捷访问远程http服务的方法,简单的restful服务模板~
    
        //Ribbon 我们这里的地址,应该是一个变量,通过服务名来访问
        //private static final String REST_URL_PREFIX = "http://localhost:8001";
        private static final String REST_URL_PREFIX = "http://SPRINGCLOUD-PROVIDER-DEPT";
    
        @RequestMapping("/consumer/dept/add")
        public boolean add(Dept dept){
            return restTemplate.postForObject(REST_URL_PREFIX+"/dept/add",dept,Boolean.class);
        }
    
        @RequestMapping("/consumer/dept/get/{id}")
        public Dept get(@PathVariable("id") Long id){
            return restTemplate.getForObject(REST_URL_PREFIX+"/dept/get/"+id,Dept.class);
        }
    
        @RequestMapping("/consumer/dept/list")
        public List<Dept> list(){
            return restTemplate.getForObject(REST_URL_PREFIX+"/dept/list",List.class);
        }
    
    }
  4. 运行三个Eureka集群,服务提供者与消费者进行测试

6.3、使用Ribbon实现负载均衡

    CREATE DATABASE /*!32312 IF NOT EXISTS*/`db02` /*!40100 DEFAULT CHARACTER SET utf8 */;
    
    USE `db02`;
    
    /*Table structure for table `dept` */
    
    DROP TABLE IF EXISTS `dept`;
    
    CREATE TABLE `dept` (
      `deptno` bigint(20) NOT NULL AUTO_INCREMENT,
      `dname` varchar(60) DEFAULT NULL,
      `db_source` varchar(60) DEFAULT NULL,
      PRIMARY KEY (`deptno`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='部门表';
    
    /*Data for the table `dept` */
    
    insert  into `dept`(`deptno`,`dname`,`db_source`) 
    values (1,'开发部','db02'),(2,'人事部','db02'),(3,'财务部','db02'),(4,'市场部','db02'),(5,'运维部','db02');
    
    #######################################
    
    CREATE DATABASE /*!32312 IF NOT EXISTS*/`db03` /*!40100 DEFAULT CHARACTER SET utf8 */;
    
    USE `db03`;
    
    /*Table structure for table `dept` */
    
    DROP TABLE IF EXISTS `dept`;
    
    CREATE TABLE `dept` (
      `deptno` bigint(20) NOT NULL AUTO_INCREMENT,
      `dname` varchar(60) DEFAULT NULL,
      `db_source` varchar(60) DEFAULT NULL,
      PRIMARY KEY (`deptno`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='部门表';
    
    /*Data for the table `dept` */
    
    insert  into `dept`(`deptno`,`dname`,`db_source`) 
    values (1,'开发部','db03'),(2,'人事部','db03'),(3,'财务部','db03'),(4,'市场部','db03'),(5,'运维部','db03');
  1. 新疆两个服务提供者模块,springcloud-eureka-8002,springcloud-eureka-8003,与springcloud-eureka-8001相同,导入相同的依赖,并修改配置文件为对应的数据库及接口

    <dependencies>
        <!--EUREKA依赖-->
        <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-eureka -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka</artifactId>
            <version>1.4.7.RELEASE</version>
        </dependency>
        <!--actuator完善监控信息-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
    
        <!--我们需要拿到实体类,所以要配置api module-->
        <dependency>
            <groupId>com.kuang</groupId>
            <artifactId>springcloud-api</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <!--junit-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-core</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
        </dependency>
        <!--test-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-test</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--jetty-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jetty</artifactId>
        </dependency>
        <!--热部署工具-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
        </dependency>
    
    </dependencies>

    application.yml

    server:
      port: 8002
    
    #mybatis配置
    mybatis:
      type-aliases-package: com.kuang.springcloud.pojo
      config-location: classpath:mybatis/mybatis-config.xml
      mapper-locations: classpath:mybatis/mapper/*.xml
    
    #spring的配置
    spring:
      application:
        name: springcloud-provider-dept #三个服务名称一致
      datasource:
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://localhost:3306/db02?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT
        username: root
        password: 123456
    
    #Eureka的配置,服务注册到哪里
    eureka:
      client:
        service-url:
          defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
    
      instance:
        instance-id: springcloud-provider-dept-8002 #修改eureka上的默认描述信息!
        hostname: localhost #修改主机名称
    
    #解决url过滤问题
    management:
      endpoints:
        web:
          exposure:
            include: "*"
    
    #info配置,无效,创建单独的build-info.properties解决,注意格式
    info:
      app-name: kuangshen-springcloud
      company-name: blog.kuangstudy.com

    DeptMapper.xml

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    
    <mapper namespace="com.kuang.springcloud.dao.DeptDao">
    
        <insert id="addDept" parameterType="Dept">
            insert into db02.dept (dname, db_source)
            values (#{dname},DATABASE());
        </insert>
    
        <select id="queryDeptById" resultType="Dept" parameterType="Long">
            select * from db02.dept where deptno = #{deptno};
        </select>
    
        <select id="queryAll" resultType="Dept">
            select * from db02.dept;
        </select>
    
    </mapper>

    其余文件与springcloud-provider-dept-8001模块相同,名字不同

7、Feign负载均衡

7.1、简介

feign是声明式的web service客户端,它让微服务之间的调用变得更简单了,类似controller调用service。SpringCloud继承了Ribbon和Eureka,可在使用Feign时提供负载均衡的http客户端。

feign,主要是社区,大家都习惯面向接口编程。这个是很多开发人员的规范。调用微服务访问两种方法

  1. 微服务名字 【ribbon】

  2. 接口和注解 【feign】

Feign能干什么?

  • Feign旨在使编写Java Http客户端变得更容易

  • 前面在使用Ribbon + RestTemplate时,利用RestTemplate对Http请求的封装处理,形成了一套模板化的调用方法。但是在实际开发中,由于对服务依赖的调用可能不止一处,往往一个接口会被多处调用,所以通常都会针对每个微服务自行封装一些客户端类来包装这些依赖服务的调用。所以,Feign在此基础上做了进一步封装,由他来帮助我们定义和实现依赖服务接口的定义,

    在Feign的实现下,我们只需要创建一个接口并使用注解的方式来配置它(类似于以前Dao接口上标注Mapper注解,现在是一个微服务接口上面标注一个Feign注解即可。)

    即可完成对服务提供方的接口绑定,简化了使用SpringCloud Ribbon时,自动封装服务调用客户端的开发量。

Feign集成了Ribbon

  • 利用Ribbon维护了MicroServiceCloud-Dept的服务列表信息,并且通过轮询实现了客户端的负载均衡,而与Ribbon不同的是,通过Feign只需要定义服务绑定接口且以声明式的方法,优雅而且简单的实现了服务调用。

7.2、代码实现

    <!--feign-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-feign</artifactId>
        <version>1.4.7.RELEASE</version>
    </dependency>
  1. 在实体类模块springcloud-api新建一个service层接口DeptClientService,添加FeignClient注解,其值为服务提供者

    @Component
    @FeignClient(value = "SPRINGCLOUD-PROVIDER-DEPT")
    public interface DeptClientService {
    
        @GetMapping("/dept/get/{id}")
        public Dept queryById(@PathVariable("id") Long id);
    
        @GetMapping("/dept/list")
        public List<Dept> queryAll();
    
        @PostMapping("/dept/add")
        public boolean addDept(Dept dept);
    
    }
  2. 新建feign消费者模块springcloud-consumer-dept-feign,与消费者模块springcloud-consumer-dept-80模块类似,仅改动controller层及启动类。

    <!--feign-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-feign</artifactId>
        <version>1.4.7.RELEASE</version>
    </dependency>

    创建controller文件DeptConsumerController.java

    @RestController
    public class DeptConsumerController {
    
        @Autowired
        private DeptClientService deptClientService;
    
        @RequestMapping("/consumer/dept/add")
        public boolean add(Dept dept){
            return this.deptClientService.addDept(dept);
        }
    
        @RequestMapping("/consumer/dept/get/{id}")
        public Dept get(@PathVariable("id") Long id){
            return this.deptClientService.queryById(id);
        }
    
        @RequestMapping("/consumer/dept/list")
        public List<Dept> list(){
            return this.deptClientService.queryAll();
        }
    
    }

    启动类FeignDeptConsumer_80.java

    @SpringBootApplication
    @EnableEurekaClient
    @EnableFeignClients(basePackages = {"com.kuang.springcloud"})
    public class FeignDeptConsumer_80 {
        public static void main(String[] args) {
            SpringApplication.run(FeignDeptConsumer_80.class,args);
        }
    }
  3. 启动eureka集群,服务提供者及feign消费者进行测试,同样可以实现查询

8、Hystrix

分布式系统面临的问题

服务雪崩

对于高流量的应用来说,单一的后端依赖可能会导致所有服务器上的所有资源都在几秒钟内饱和。比失败更糟糕的是,这些应用程序还可能导致服务之间的延迟增加,备份队列、线程和其他系统资源紧张,导致整个系统发生更多的级联故障,这些都表示需要对故障和延迟进行隔离和管理,以便单个依赖关系的失败,不能取消整个应用程序或系统。

什么是Hystrix

“断路器”本身是一种开关装置,当某个服务单元发生故障之后,通过断路器的故障监控(类似熔断保险丝),向调用方返回一个服务预期的,可处理的备选响应(FallBack),而不是长时间的等待或者抛出调用方法无法处理的异常,这样就可以保证了服务调用方的线程不会被长时间,不必要的占用,从而避免了故障在分布式系统中的蔓延,乃至雪崩。

能干嘛

  • 服务降级

  • 服务熔断

  • 服务限流

  • 接近实时的监控

  • .....。

官网资料

http://github.com/Netflix/Hystrix/wiki

示意图:

8.1、服务熔断

是什么

当扇出链路的某个微服务不可用或者响应时间太长,会进行服务的降级,进而熔断该节点微服务的调用,快速返回错误的响应信息。当检测到该节点微服务调用响应正常后恢复调用链路。在SpringCloud框架里熔断机制通过Hystrix实现。Hystrix会监控微服务间调用的情况,当失败的调用到一定阈值,缺省是5秒内20次调用失败就会启动熔断机制。熔断机制的注解是@HystrixCommand。

代码实现:

    <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-netflix-hystrix -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        <version>2.2.10.RELEASE</version>
    </dependency>

    修改配置文件

    #Eureka的配置,服务注册到哪里
    eureka:
      client:
        service-url:
          defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
    
      instance:
        instance-id: springcloud-provider-dept-hystrix-8001 #修改eureka上的默认描述信息!
        hostname: localhost #修改主机名称
        prefer-ip-address: true # true,可以显示服务的ip地址~
  1. 重写controller层DeptController.java实现Hystrix服务熔断

    //提供Restful服务!
    @RestController
    public class DeptController {
    
        @Autowired
        private DeptService deptService;
    
        @GetMapping("/dept/get/{id}")
        @HystrixCommand(fallbackMethod = "hystrixGet")
        public Dept get(@PathVariable("id") Long id){
            Dept dept = deptService.queryDeptById(id);
    
            if (dept==null){
                throw new RuntimeException("id=>"+id+",不存在该用户,或者信息无法找到~");
            }
    
            return dept;
        }
    
        //备选方法
        public Dept hystrixGet(@PathVariable("id") Long id){
            return new Dept()
                    .setDeptno(id)
                    .setDname("id=>"+id+"没有对应的信息,null--@Hystrix")
                    .setDb_source("no this database in MySQL");
        }
    
    }
  2. 启动类添加对Hystrix的支持@EnableHystrix

    //启动类
    @SpringBootApplication
    @EnableEurekaClient //在服务启动后自动注册到Eureka中!
    @EnableDiscoveryClient //服务发现~
    @EnableHystrix //添加对熔断的支持,新版包含EnableCircuitBreaker
    public class DeptProviderHystrix_8001 {
        public static void main(String[] args) {
            SpringApplication.run(DeptProviderHystrix_8001.class,args);
        }
    }
  3. 启动Eureka集群,hystrix服务提供者及消费者,先访问Eureka,可以指定服务提供者显示ip地址

8.2、服务降级

什么是服务降级
服务降级,就是对不怎么重要的服务进行低优先级的处理。说白了,就是尽可能的把系统资源让给优先级高的服务。资源有限,而请求是无限的。如果在并发高峰期,不做服务降级处理,一方面肯定会影响整体服务的性能,严重的话可能会导致宕机某些重要的服务不可用。所以,一般在高峰期,为了保证网站核心功能服务的可用性,都要对某些服务降级处理。

是消费者使用的一种应对服务提供者无响应的策略。

代码实现:

    //降级~
    @Component
    public class DeptClientServiceFallbackFactory implements FallbackFactory {
        @Override
        public DeptClientService create(Throwable cause) {
            return new DeptClientService() {
                @Override
                public Dept queryById(Long id) {
                    return new Dept()
                            .setDeptno(id)
                            .setDname("id=>"+id+"没有对应的信息,客户端提供了降级的信息,这个服务现在已经被关闭了")
                            .setDb_source("没有数据~");
                }
    
                @Override
                public List<Dept> queryAll() {
                    return null;
                }
    
                @Override
                public boolean addDept(Dept dept) {
                    return false;
                }
            };
        }
    }
  1. 在实体类模块springcloud-api中service层的DeptClientService接口中指定fallbackFactory所指向的类

    @Component
    @FeignClient(value = "SPRINGCLOUD-PROVIDER-DEPT",fallbackFactory = DeptClientServiceFallbackFactory.class)
    public interface DeptClientService {
    
        @GetMapping("/dept/get/{id}")
        public Dept queryById(@PathVariable("id") Long id);
    
        @GetMapping("/dept/list")
        public List<Dept> queryAll();
    
        @PostMapping("/dept/add")
        public boolean addDept(Dept dept);
    
    }
  2. 在消费者springcloud-consumer-dept-feign中导入依赖

    <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-netflix-hystrix -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        <version>2.2.10.RELEASE</version>
    </dependency>
  3. 在配置文件application.yml中开启降级feign.hystrix(新版配置不同)

    server:
      port: 80
    
    #开启降级feign.hystrix(新版配置不同)
    feign:
      circuitbreaker:
        enabled: true
    
    #Eureka配置
    eureka:
      client:
        register-with-eureka: false #不向Eureka注册自己
        service-url:
          defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
  4. 启动Eureka集群及消费者springcloud-consumer-dept-feign,使用消费者进行访问,找不到服务则显示预定内容不会报错。

8.3、服务熔断与服务降级简单对比

,某个服务超时或者异常,引起熔断,保险丝~。

8.4、Dashboard流监控

控制面板信息:

    • 七色

    • 实心圈:共有两种含义,它通过颜色的变化代表了实例的健康程度

      该实心圆除了颜色的变化之外,它的大小也会根据实例的请求流量发生变化,流量越大,该实心圆就越大,所以通过该实心圆的展示,就可以在大量的实例中快速发现故障实例和高压力实例。

    • 曲线:用来记录2分钟内流量的相对变化,可以通过它来观察到流量的上升和下降趋势!

代码实现:

    <!--Hystrix依赖-->
    <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-netflix-hystrix -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        <version>2.2.10.RELEASE</version>
    </dependency>
    <!--Dashboard依赖-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
        <version>2.2.10.RELEASE</version>
    </dependency>
  1. 新建配置文件application.yml

    server:
      port: 9001
    
    hystrix:
      dashboard:
        proxy-stream-allow-list: "localhost"
  2. 新建一个启动类DeptConsumerDashboard_9001.java

    @SpringBootApplication
    @EnableHystrixDashboard //开启监控
    public class DeptConsumerDashboard_9001 {
        public static void main(String[] args) {
            SpringApplication.run(DeptConsumerDashboard_9001.class,args);
        }
    }
  3. 将服务提供者springcloud-provider-dept-hystrix-8001放入监控面板,导入hystrix和监控依赖,在启动类增加一个Servlet

    <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-netflix-hystrix -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        <version>2.2.10.RELEASE</version>
    </dependency>
    <!--actuator完善监控信息-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
    //启动类
    @SpringBootApplication
    @EnableEurekaClient //在服务启动后自动注册到Eureka中!
    @EnableDiscoveryClient //服务发现~
    @EnableHystrix //添加对熔断的支持,新版包含EnableCircuitBreaker
    public class DeptProviderHystrix_8001 {
        public static void main(String[] args) {
            SpringApplication.run(DeptProviderHystrix_8001.class,args);
        }
    
        //增加一个Servlet
        public ServletRegistrationBean hystrixMetricsStreamServlet(){
            ServletRegistrationBean registrationBean = new ServletRegistrationBean(new HystrixMetricsStreamServlet());
            registrationBean.addUrlMappings("/actuator/hystrix.stream");
            return registrationBean;
        }
    }
  4. 启动EurekaServer_7001,DeptProviderHystrix_8001及DeptConsumerDashboard_9001进行测试

  • 访问Hystrix Dashboard面板

  • 使用服务提供者进行查询后,查看/actuator/hystrix页面

  • 根据查询页面填写Dashboard页面信息进行监视

  • 最后查看监视页面

9、Zuul路由网关

9.1、概述

什么是Zuul?

其中路由功能负责将外部请求转发到具体的微服务实例上,是实现外部访问统一入口的基础,而过滤器功能则负责对请求的处理过程进行干预,是实现请求校验、服务聚合等功能的基础。Zuul和Eureka进行整合,将Zuul自身注册为Eureka服务治理下的应用,同时从Eureka中获得其他微服务的消息,也即以后的访问微服务都是通过Zuul跳转后获得。

提供:代理 + 路由 + 过滤 三大功能!

Zuul能干嘛?

  • 路由

  • 过滤

https://github.com/Netflix/zuul

Zuul示意图:

9.2、代码实现:

    <!--实体类+web-->
    <dependencies>
    
        <!--zuul依赖-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
            <version>2.2.10.RELEASE</version>
        </dependency>
    
        <!--Hystrix依赖-->
        <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-netflix-hystrix -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
            <version>2.2.10.RELEASE</version>
        </dependency>
        <!--Dashboard依赖-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
            <version>2.2.10.RELEASE</version>
        </dependency>
    
        <!--feign-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-feign</artifactId>
            <version>1.4.7.RELEASE</version>
        </dependency>
    
        <!--Eureka-->
        <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-eureka -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka</artifactId>
            <version>1.4.7.RELEASE</version>
        </dependency>
    
        <dependency>
            <groupId>com.kuang</groupId>
            <artifactId>springcloud-api</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--热部署工具-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
        </dependency>
    </dependencies>
  1. 新建配置文件application.yml,对Zuul进行配置

    server:
      port: 9527
    
    spring:
      application:
        name: springcloud-zuul
    
    #Eureka的配置,服务注册到哪里
    eureka:
      client:
        service-url:
          defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
    
      instance:
        instance-id: zuul9527.com #修改eureka上的默认描述信息!
        hostname: "localhost" #修改主机名称
        prefer-ip-address: true # true,可以显示服务的ip地址~
    
    #解决url过滤问题
    management:
      endpoints:
        web:
          exposure:
            include: "*"
    
    
    #info配置,无效,创建单独的build-info.properties解决,注意格式
    info:
      app-name: kuangshen-springcloud
      company-name: blog.kuangstudy.com
    
    zuul:
      routes:
        mydept:
          serviceId: springcloud-provider-dept
          path: /mydept/**
      ignored-services: "*" #不能再使用这个路径访问了,ignored : 忽略,隐藏全部的
      prefix: /kuang #设置访问时统一的前缀
  2. 新建启动类,开启Zuul

    @SpringBootApplication
    @EnableEurekaClient
    @EnableZuulProxy //开启Zuul
    public class ZuulApplication_9527 {
        public static void main(String[] args) {
            SpringApplication.run(ZuulApplication_9527.class,args);
        }
    }
  3. 启动Eureka,provider8001,及zuul9527进行测试

警告:该部分经反复尝试debug,修改springboot及springcloud版本、加拦截器配置类、增加ribbon时间、修改配置文件等操作,均不能解决不能通过Zuul访问其他服务的问题,只能实现将Zuul加入eureka并且访问Zuul服务。在该版本中尚未找到可用的解决方案,目前只能使用其他方法实现网关的功能。

10、SpringCloud config分布式配置(Git)

10.1、概述

分布式系统面临的--配置文件的问题

什么是SpringCloud config分布式配置中心

各个不同微服务应用的所有环节提供了一个中心化的外部配置

服务端和客户端两部分;

客户端则是通过指定的配置中心来管理应用资源,以及与业务相关的配置内容,并在启动的时候从配置中心获取和加载配置信息。配置服务器默认采用git来存储配置信息,这样就有助于对环境配置进行版本管理。并且可以通过git客户端工具来方便的管理和访问配置内容。

SpringCloud Config分布式配置中心能干嘛

  • 集中管理配置文件

  • 不同环境,不同配置,动态化的配置更新,分环境部署,比如 /dev /test /prod /beta /release

  • 运行期间动态调整配置,不再需要在每个服务部署的机器上编写配置文件,服务会向配置中心统一拉取配置自己的信息。

  • 当配置发生变动时,服务不需要重启,即可感知到配置的变化,并应用新的配置

  • 将配置信息以REST接口的形式暴露

SpringCloud Config分布式配置中心与github整合

10.2、Git环境搭建

    注册码云Gitee账号,登录,新建仓库springcloud-config,设置如下图

  1. ~/.ssh
  2. 在git中输入以下命令并连续三次回车,以生成ssh公开密钥(邮箱可随意输入,只是密钥名称,习惯输入邮箱)

    ssh-keygen -t ed25519 -C "406623380@qq.com"
  3. cat ~/.ssh/id_ed25519.pub
  4. git clone git@gitee.com:wydilearn/springcloud-config.git

    输入yes继续clone

  5. git add .
    git status #可以查看到新建的文件
    git commit -m "first commit" #提交新文件,本次提交的名字可以随便取
    git push origin master #将文件上传至master分支

10.3、服务端连接Git配置

    <dependencies>
        <!--config-->
        <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-config-server -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-config-server</artifactId>
            <version>3.1.2</version>
        </dependency>
    
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--Eureka-->
        <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-eureka -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka</artifactId>
            <version>1.4.7.RELEASE</version>
        </dependency>
    </dependencies>
  1. 新建配置文件application.yml连接远程仓库,获取Gitee中仓库的https地址作为uri

    server:
      port: 3344
    spring:
      application:
        name: springcloud-config-server
        # 连接远程仓库
      cloud:
        config:
          server:
            git:
              uri: https://gitee.com/wydilearn/springcloud-config.git # https,不是git
  2. 新建一个启动类Config_Server_3344.java,启用服务端配置

    @SpringBootApplication
    @EnableConfigServer //
    public class Config_Server_3344 {
        public static void main(String[] args) {
            SpringApplication.run(Config_Server_3344.class,args);
        }
    }
  3. 启动该模块进行测试,访问以下三个路径可访问到Gitee仓库的文件

10.4、客户端连接服务端访问远程

    spring:
      profiles:
        active: dev
        
    ---
    server:
      port: 8201
    #spring的配置
    spring:
      profiles: dev
      application:
        name: springcloud-provider-dept
    
    #Eureka的配置,服务注册到哪里
    eureka:
      client:
        service-url:
          defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
    
    ---
    server:
      port: 8202
    #spring的配置
    spring:
      profiles: test
      application:
        name: springcloud-provider-dept
    
    #Eureka的配置,服务注册到哪里
    eureka:
      client:
        service-url:
          defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
  1. 使用Git上传该配置文件到Gitee项目中,与之前文件上传操作类似

  2. <dependencies>
        <!--config-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-config</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-bootstrap</artifactId>
        </dependency>
    
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--Eureka-->
        <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-eureka -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka</artifactId>
            <version>1.4.7.RELEASE</version>
        </dependency>
    </dependencies>
  3. 新建两个配置文件application.yml与bootstrap.yml

    # 系统级的配置
    spring:
      cloud:
        config:
          uri: http://localhost:3344 #连接本地服务,通过本地服务到Gitee获取
          name: config-client #需要从git上读取的资源名称,不要后缀
          profile: dev #拿到文件中的哪个生产环境
          label: master #哪个分支  http://localhost:3344/master/config-client-dev.yml

    application.yml

    # 用户级的配置
    spring:
      application:
        name: springcloud-config-client-3355

    此时未配置端口,默认为dev端口8201,可自行设置端口

  4. @RestController
    public class ConfigClientController {
    
        @Value("${spring.application.name}")
        private String applicationName;
        @Value("${eureka.client.service-url.defaultZone}")
        private String eurekaServer;
        @Value("${server.port}")
        private String port;
        @RequestMapping("/config")
        public String getConfig(){
            return "applicationName:" + applicationName +
                   "eurekaServer:" + eurekaServer +
                   "port:" + port;
        }
    }
  5. 新建启动类ConfigClient_3355.java

    @SpringBootApplication
    public class ConfigClient_3355 {
        public static void main(String[] args) {
            SpringApplication.run(ConfigClient_3355.class,args);
        }
    }
  6. 同时启动服务端配置模块与客户端配置模块进行测试,可通过客户端模块读取配置信息

10.5、远程配置实战测试

    config-dept.yml

    spring:
      profiles:
        active: dev
    
    ---
    
    server:
      port: 8001
    
    #mybatis配置
    mybatis:
      type-aliases-package: com.kuang.springcloud.pojo
      config-location: classpath:mybatis/mybatis-config.xml
      mapper-locations: classpath:mybatis/mapper/*.xml
    
    #spring的配置
    spring:
      profiles: dev
      application:
        name: springcloud-config-dept
      datasource:
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://localhost:3306/db02?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT
        username: root
        password: 123456
    
    #Eureka的配置,服务注册到哪里
    eureka:
      client:
        service-url:
          defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
    
      instance:
        instance-id: springcloud-provider-dept-8001 #修改eureka上的默认描述信息!
        hostname: localhost #修改主机名称
    
    #解决url过滤问题
    management:
      endpoints:
        web:
          exposure:
            include: "*"
            
    ---
    
    server:
      port: 8001
    
    #mybatis配置
    mybatis:
      type-aliases-package: com.kuang.springcloud.pojo
      config-location: classpath:mybatis/mybatis-config.xml
      mapper-locations: classpath:mybatis/mapper/*.xml
    
    #spring的配置
    spring:
      profiles: test
      application:
        name: springcloud-config-dept
      datasource:
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://localhost:3306/db01?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT
        username: root
        password: 123456
    
    #Eureka的配置,服务注册到哪里
    eureka:
      client:
        service-url:
          defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
    
      instance:
        instance-id: springcloud-provider-dept-8001 #修改eureka上的默认描述信息!
        hostname: localhost #修改主机名称
    
    #解决url过滤问题
    management:
      endpoints:
        web:
          exposure:
            include: "*"

    config-eureka.yml

    spring:
      profiles:
        active: dev
    
    ---
    
    server:
      port: 7001
    
    #spring的配置
    spring:
      profiles: dev
      application:
        name: springcloud-config-eureka
    
    #Eureka配置
    eureka:
      instance:
        hostname: eureka7001.com #Eureka服务端的实例名称
      client:
        register-with-eureka: false #表示是否向eureka注册中心注册自己
        fetch-registry: false #fetch-registry如果为false,则表示自己为注册中心
        service-url: #监控页面~
          # 单机: defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
          # 集群(关联):
          defaultZone: http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
          
    ---
    
    server:
      port: 7001
    
    #spring的配置
    spring:
      profiles: test
      application:
        name: springcloud-config-eureka
    
    #Eureka配置
    eureka:
      instance:
        hostname: eureka7001.com #Eureka服务端的实例名称
      client:
        register-with-eureka: false #表示是否向eureka注册中心注册自己
        fetch-registry: false #fetch-registry如果为false,则表示自己为注册中心
        service-url: #监控页面~
          # 单机: defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
          # 集群(关联):
          defaultZone: http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
          
    ---
    
    server:
      port: 7001
    
    #Eureka配置
    eureka:
      instance:
        hostname: eureka7001.com #Eureka服务端的实例名称
      client:
        register-with-eureka: false #表示是否向eureka注册中心注册自己
        fetch-registry: false #fetch-registry如果为false,则表示自己为注册中心
        service-url: #监控页面~
          # 单机: defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
          # 集群(关联):
          defaultZone: http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
  1. 新建springcloud-config-eureka-7001模块,内容与springcloud-eureka-7001相同,导入依赖,新建配置文件application.yml及bootstrap.yml

    <!--导包-->
    <dependencies>
        <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-eureka-server -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka-server</artifactId>
            <version>1.4.7.RELEASE</version>
        </dependency>
        <!--热部署工具-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
        </dependency>
        <!--config-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-config</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-bootstrap</artifactId>
        </dependency>
    
    </dependencies>

    application.yml

    spring:
      application:
        name: springcloud-config-eureka-7001

    bootstrap.yml

    spring:
      cloud:
        config:
          name: config-eureka
          label: master
          profile: dev
          uri: http://localhost:3344
  2. 新建springcloud-config-dept-8001模块,内容与springcloud-provider-dept-8001相同,导入依赖,新建application.yml及bootstrap.yml

    <dependencies>
    
        <!--Hystrix依赖-->
        <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-netflix-hystrix -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
            <version>2.2.10.RELEASE</version>
        </dependency>
    
        <!--EUREKA依赖-->
        <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-eureka -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka</artifactId>
            <version>1.4.7.RELEASE</version>
        </dependency>
        <!--actuator完善监控信息-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
    
        <!--我们需要拿到实体类,所以要配置api module-->
        <dependency>
            <groupId>com.kuang</groupId>
            <artifactId>springcloud-api</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <!--junit-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-core</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
        </dependency>
        <!--test-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-test</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--jetty-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jetty</artifactId>
        </dependency>
        <!--热部署工具-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
        </dependency>
    
        <!--config-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-config</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-bootstrap</artifactId>
        </dependency>
    
    </dependencies>

    application.yml

    spring:
      application:
        name: springcloud-config-dept-8001

    bootstrap.yml

    spring:
      cloud:
        config:
          name: config-dept
          label: master
          profile: test
          uri: http://localhost:3344
  3. 启动springcloud-config-server-3344,springcloud-config-eureka-7001,springcloud-config-dept-8001三个模块进行测试,发现服务在eureka中注册,并且可以通过服务查询数据库

编程笔记 » Springcloud及Git线上配置详解

赞同 (67) or 分享 (0)
游客 发表我的评论   换个身份
取消评论

表情
(0)个小伙伴在吐槽