zoukankan      html  css  js  c++  java
  • 狂神说springcloud笔记1_p1-p13

    参考博文:(5条消息) [狂神说Java]SpringCloud笔记_笶生的博客-CSDN博客

    (5条消息) 狂神说SpringCloud学习笔记(附带源码和笔记)_学不死就往死里学-CSDN博客

    1、SpringCloud入门概述

    1.1 SpringCloud是什么

    springcloud官网: https://spring.io/projects/spring-cloud#learn

     

     

    1.3 Dubbo 和 SpringCloud技术选型

    1、分布式+服务治理Dubbo

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

    2、Dubbo 和 SpringCloud对比

    可以看一下社区活跃度

    https://github.com/dubbo

    https://github.com/springcloud

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    1.4 SpringCloud能干什么

    在这里插入图片描述

    1.5 SpringCloud在哪下

    官网 : https://spring.io/projects/spring-cloud/
    在这里插入图片描述
    在这里插入图片描述

    2、总体介绍

    在这里插入图片描述
    在这里插入图片描述

    2.1SpringCloud版本选择

    在这里插入图片描述

    3、创建父工程

    直接创建一个名为SpringCloud的Maven空项目即可

    然后后面全部的项目都是父工程的一个子模块,并且都是maven的空项目

    建立一个数据库:db01
    在这里插入图片描述

    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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
    
        <groupId>com.bupt</groupId>
        <artifactId>springcloudLast</artifactId>
        <packaging>pom</packaging>
        <version>1.0-SNAPSHOT</version>
        <modules>
            <module>springcloud-api</module>
            <module>springcloud-consumer-dept-80</module>
            <module>springcloud-eureka-7001</module>
            <module>springcloud-provider-dept-8001</module>
            <module>springcloud-provider-dept-8002</module>
            <module>springcloud-provider-dept-8003</module>
        </modules>
    
        <properties>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <maven.compiler.source>8</maven.compiler.source>
            <maven.compiler.target>8</maven.compiler.target>
            <junit.version>4.12</junit.version>
            <log4j.version>1.2.17</log4j.version>
            <lombok.version>1.16.18</lombok.version>
        </properties>
    
        <dependencyManagement>
            <dependencies>
                <dependency>
                    <groupId>org.springframework.cloud</groupId>
                    <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                    <version>0.2.0.RELEASE</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
                <!--springCloud的依赖-->
                <dependency>
                    <groupId>org.springframework.cloud</groupId>
                    <artifactId>spring-cloud-dependencies</artifactId>
                    <version>Greenwich.SR1</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
                <!--SpringBoot-->
                <dependency>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-dependencies</artifactId>
                    <version>2.1.4.RELEASE</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
                <!--数据库-->
                <dependency>
                    <groupId>com.alibaba</groupId>
                    <artifactId>druid</artifactId>
                    <version>1.1.10</version>
                </dependency>
                <!--SpringBoot 启动器-->
                <dependency>
                    <groupId>org.mybatis.spring.boot</groupId>
                    <artifactId>mybatis-spring-boot-starter</artifactId>
                    <version>1.3.2</version>
                </dependency>
                <!--日志测试~-->
                <dependency>
                    <groupId>ch.qos.logback</groupId>
                    <artifactId>logback-core</artifactId>
                    <version>1.2.3</version>
                </dependency>
                <dependency>
                    <groupId>junit</groupId>
                    <artifactId>junit</artifactId>
                    <version>${junit.version}</version>
                </dependency>
                <dependency>
                    <groupId>log4j</groupId>
                    <artifactId>log4j</artifactId>
                    <version>${log4j.version}</version>
                </dependency>
                <dependency>
                    <groupId>org.projectlombok</groupId>
                    <artifactId>lombok</artifactId>
                    <version>${lombok.version}</version>
                </dependency>
            </dependencies>
        </dependencyManagement>
    
    
    </project>

     同理springbootdependency和springclouddependy管理了所有spring-cloud-xxx-xxx和spring-boot-xxx-xxx的版本

    注意是注意springboot的版本和springcloud版本的对应关系。

    pom.xml

    <!--当前的Module自己需要的依赖,如果父依赖中已经配置了,这里就不用写了-->
    <dependencies>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
    </dependencies> 

    Dept.java

    @Data
    @NoArgsConstructor
    @Accessors(chain = true)  //链式写法
    //所有的实体类务必实现序列化,通讯需求
    public class Dept implements Serializable {//Dept,实体类 orm 类表关系映射
        private static final long serialVersionUID = 708560364349809174L;
        private Long deptno; //主键
        private String dname;
    
        //看下这个数据存在哪个数据库的字段~ 微服务 ,一个服务对应一个数据库
        //同一个信息可能存在不同的数据库
        private String db_source;
    
        public Dept(String dname) {
            this.dname = dname;
        }
    }

    5、服务提供者:springcloud-provider-dept-8001

    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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
    <artifactId>springcloudLast</artifactId>
    <groupId>com.bupt</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>
    <dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    </dependency>
    <dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-eureka</artifactId>
    <version>1.4.6.RELEASE</version>
    </dependency>
    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jetty</artifactId>
    </dependency>
    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
    <groupId>com.bupt</groupId>
    <artifactId>springcloud-api</artifactId>
    <version>1.0-SNAPSHOT</version>
    </dependency>
    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
    <dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-netflix-ribbon</artifactId>
    </dependency>
    <dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    </dependency>
    <dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    </dependency>
    <dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.21</version>
    </dependency>
    </dependencies>
    </project>

    DeptMapper.xml

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

    DeptMapper

    @Mapper
    @Repository
    public interface DeptMapper {
        //添加部门
        boolean addDept(Dept dept);
    
        //根据ID查询部门
        Dept queryById(@Param("deptno") long id);
    
        //查询全部部门
        List<Dept> queryall();
    }

    DeptService

    public interface DeptService {
        boolean addDept(Dept dept);
    
        Dept queryById(long id);
    
        List<Dept> queryall();
    
    }

    DeptServiceImpl

    @Service
    public class DeptServiceImpl implements DeptService {
    
        @Autowired
        private DeptMapper deptMapper;
    
        @Override
        public boolean addDept(Dept dept) {
            return deptMapper.addDept(dept);
        }
    
        @Override
        public Dept queryById(long id) {
            return deptMapper.queryById(id);
        }
    
        @Override
        public List<Dept> queryall() {
            return deptMapper.queryall();
        }
    }

    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核心配置文件 -->
    <configuration>
        <settings>
            <!--开启二级缓存-->
            <setting name="cacheEnabled" value="true"/>
        </settings>
    </configuration>

    application.yml

    server:
      port: 8001
    
    mybatis:
      mapper-locations: classpath:mybatis/mapper/*.xml
      type-aliases-package: com.bupt.pojo
      configuration-properties: classpath:mybatis/mybatis-config.xml
    
    spring:
      application:
        name: springcloud-provider-dept
      datasource:
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://127.0.0.1:3306/db01?useUnicode=true&characterEncoding=UTF-8&useSSL=true&serverTimezone=UTC
        username: root
        password: root
    eureka:
      client:
        service-url:
          defaultZone: http://localhost:7001/eureka/

    DeptController

    package com.bupt.Controller;
    
    import com.bupt.DeptService.DeptServiceImpl;
    import com.bupt.pojo.Dept;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.*;
    
    import java.util.List;
    
    //提供Restfull服务!!
    @RestController
    public class DeptController {
    
        @Autowired
        private DeptServiceImpl deptService;
    
        @RequestMapping("/dept/add")
    
        public boolean addDept(@RequestBody Dept dept) {
            System.out.println(dept);
            return deptService.addDept(dept);
        }
    
    
        @GetMapping("/dept/get/{id}")
        public Dept getDept(@PathVariable("id") Long id) {
            Dept dept = deptService.queryById(id);
            if (dept == null) {
                throw new RuntimeException("Fail");
            }
            return dept;
        }
    
        @GetMapping("/dept/list")
        public List<Dept> queryAll() {
            return deptService.queryall();
        }
    
    }

    DeptProvider_8001

    package com.bupt;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    
    //@EnableEurekaClient
    @SpringBootApplication
    
    public class DeptProvider_8001 {
        public static void main(String[] args) {
            SpringApplication.run(DeptProvider_8001.class,args);
        }
    }

    最后启动项目访问Controller里面的接口测试即可,这个pojo类在别的项目里面,我们照样可以拿到,这就是微服务的简单拆分的一个小例子

    6、服务消费者:springcloud-consumer-dept-80

    在这里插入图片描述

    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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <parent>
            <artifactId>springcloudLast</artifactId>
            <groupId>com.bupt</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>
        <dependencies>
            <dependency>
                <groupId>com.bupt</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>

    这里要用到 RestTemplate ,但是它的类中没有Bean,所以我们要把它注册到Bean中

    ConfigBean

    package com.bupt.config;
    
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.client.RestTemplate;
    
    @Configuration
    public class ConfigBean {
        @Bean
        public RestTemplate getRestTemplate(){
            return new RestTemplate();
        }
    }

    DeptConsumerController

    package com.bupt.controller;
    
    import com.bupt.pojo.Dept;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.ResponseBody;
    import org.springframework.web.client.RestTemplate;
    
    import java.util.HashMap;
    import java.util.List;
    
    @Controller
    public class DeptConsumerController {
    
        @Autowired
        private RestTemplate restTemplate;
    
        private static final  String REST_URL_PREFIX = "http://localhost:8001";
    
        @RequestMapping("/consumer/dept/get/{id}")
        @ResponseBody
        public Dept getDept(@PathVariable("id") long id)
        {
            return restTemplate.getForObject(REST_URL_PREFIX + "/dept/get/" + id,Dept.class);
        }
    
        @RequestMapping("/consumer/dept/add")
        @ResponseBody
        public boolean add(Dept dept){
    
            HashMap<String, Object> map = new HashMap<>();
            map.put("dname",dept.getDname());
            map.put("deptNo",dept.getDeptno());
            map.put("db_source",dept.getDb_source());
            System.out.println(map);
            return restTemplate.postForObject(REST_URL_PREFIX + "/dept/add", map, Boolean.class);
        }
    
        @RequestMapping("/consumer/dept/list")
        @ResponseBody
        public List<Dept> queryAll(){
            return restTemplate.getForObject(REST_URL_PREFIX + "/dept/list",List.class);
        }
    
    
    
    
    
    }

    然后你会发现,原来远程的post请求直接在url是拒绝访问的,但是在这个里面可以访问,只是结果为null

    application.yml

    server:
      port: 80

    主启动类DeptConsumer_80

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

    最后启动服务提供者 springcloud-provider-dept-8001

    然后启动服务消费者 springcloud-consumer-dept-80

    通过服务消费者的url请求去获取服务提供者对应的请求,照样可以拿到

    7、Eureka服务注册与发现
    7.1、什么是Eureka

    7.2、原理讲解

     

     

    7.3、springcloud-eureka-7001

    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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <parent>
            <artifactId>springcloudLast</artifactId>
            <groupId>com.bupt</groupId>
            <version>1.0-SNAPSHOT</version>
        </parent>
        <modelVersion>4.0.0</modelVersion>
    
        <artifactId>springcloud-eureka-7001</artifactId>
    
        <properties>
            <maven.compiler.source>8</maven.compiler.source>
            <maven.compiler.target>8</maven.compiler.target>
        </properties>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
            </dependency>
        </dependencies>
    
    </project>

    application.yml

    server:
      port: 7001
    
    # Eureka配置
    eureka:
      instance:
        # Eureka服务端的实例名字
        hostname: 127.0.0.1
      client:
        # 表示是否向 Eureka 注册中心注册自己(这个模块本身是服务器,所以不需要)
        register-with-eureka: false
        # fetch-registry如果为false,则表示自己为注册中心,客户端的化为 ture
        fetch-registry: false
        # Eureka监控页面~
        service-url:
          defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/

    主启动类:EurekaServer_7001

    @SpringBootApplication
    @EnableEurekaServer //EnableEurekaServer表示服务端的启动类,可以接收别人注册进来
    public class EurekaServer_7001 {
        public static void main(String[] args) {
            SpringApplication.run(ConfigEurekaServer_7001.class, args);
        }
    }

    启动之后访问 http://localhost:7001/
    在这里插入图片描述

    Eureka的自我保护机制

    在这里插入图片描述

    7.4、8001服务注册与发现

    springcloud-provider-dept-8001

    首先肯定是要导入对应的依赖

    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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <parent>
            <artifactId>springcloudLast</artifactId>
            <groupId>com.bupt</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>
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-eureka</artifactId>
                <version>1.4.6.RELEASE</version>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-jetty</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <dependency>
                <groupId>com.bupt</groupId>
                <artifactId>springcloud-api</artifactId>
                <version>1.0-SNAPSHOT</version>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-actuator</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-netflix-ribbon</artifactId>
            </dependency>
            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
            </dependency>
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid</artifactId>
            </dependency>
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>8.0.21</version>
            </dependency>
        </dependencies>
    </project>

    主要是spring-cloud-starter-eureka依赖,注意版本

    然后在配置文件中添加对应的Eureka注册配置

    application.yml

    server:
      port: 8001
    
    mybatis:
      mapper-locations: classpath:mybatis/mapper/*.xml
      type-aliases-package: com.bupt.pojo
      configuration-properties: classpath:mybatis/mybatis-config.xml
    
    spring:
      application:
        name: springcloud-provider-dept
      datasource:
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://127.0.0.1:3306/db01?useUnicode=true&characterEncoding=UTF-8&useSSL=true&serverTimezone=UTC
        username: root
        password: root
    eureka:
      client:
        service-url:
          defaultZone: http://localhost:7001/eureka/

    最后在主启动类上添加注解

    @EnableEurekaClient //在服务启动后自动注册到Eureka中
    1
    启动springcloud-config-eureka-7001,启动完毕后再启动下面的服务

    启动springcloud-provider-dept-8001,等一会再次访问 http://localhost:7001/

    actuator完善监控信息

    所以这个时候我们应该是少了什么东西,然后我们继续在 8001 里面添加依赖

    <!--actuator完善监控信息-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>

    重启8001项目再次点击服务状态信息,跳到了一个页面,但是里面什么都没有,这个时候我们就要配置一些信息了,这个信息只是在团队开发的时候别人会通过这个信息来了解这个服务是谁写的

    现在我们在8001项目的配置文件中添加一些配置

    #eureka 的配置,服务注册到哪里
    eureka:
      client:
        service-url:
          defaultZone: http://localhost:7001/eureka/
      instance:
        instance-id: springcloud-provider-dept8001  #修改Eureka上的默认的状态名字
    
    #info配置(点击状态信息会返回的东西,可以百度)
    info:
      app.name: wulei-springcloud    
      company.name: blog.wulei2921625957.com

    然后你重启8001项目,再次点击项目状态信息会返回你在上面添加的信息

    那如何通过代码来让别人发现自己呢?

    服务发现

    在8001项目的controller里面添加

    import org.springframework.cloud.client.discovery.DiscoveryClient;
    
    //获取一些配置的信息,得到一些具体微服务
    @Autowired
    private DiscoveryClient client;
    
    //注册进来的微服务~ ,获取一些信息
    @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() + "	" +
                instance.getPort() + "	" +
                instance.getUri() + "	" +
                instance.getServiceId()
            );
        }
        return instances;
    }

    然后在8001项目主启动类上添加服务发现注解即可

    这个注解我试了一下,不加也可以访问上面的接口返回信息

    @EnableDiscoveryClient //服务发现
    
    • 1

    重启8001项目并访问 http://localhost:8001/dept/discovery

    在这里插入图片描述

     @EnableDiscoveryClient和@EnableEurekaClient的区别

     

     为啥在客户端EnableEurekaClient可以省略不写呢?

    https://www.pianshen.com/article/22731105426/

    server.servlet.context-path配置的作用和springboot2.0变革后的配置区别

     

    8、Eureka集群的搭建


    8.1、修改域名映射
    为了体验集群搭载在不同的电脑上,我们进入C:WindowsSystem32driversetc里面修改hosts文件,在文件的末尾添加下面几行

    127.0.0.1 eureka7001.com
    127.0.0.1 eureka7002.com
    127.0.0.1 eureka7003.com
    8.2、修改7001配置文件
    application.yml

    server:
      port: 7001
    
    #Eureka配置
    eureka:
      instance:
        hostname: eureka7001.com #Eureka服务端的实例名字
      client:
        register-with-eureka: false #表示是否向 Eureka 注册中心注册自己(这个模块本身是服务器,所以不需要)
        fetch-registry: false #fetch-registry如果为false,则表示自己为注册中心
        service-url: #监控页面~
          #重写Eureka的默认端口以及访问路径 --->http://localhost:7001/eureka/
          # 单机: defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
          # 集群(关联):7001关联7002、7003
          defaultZone: http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/

    8.3 、springcloud-eureka-7002

    创建Eureka注册中心7002项目(和7001一模一样)

    pom.xml

    依赖和7001一样

    EurekaServer_7002

    主启动类

    package com.bupt;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
    
    @SpringBootApplication
    @EnableEurekaServer //EnableEurekaServer表示服务端的启动类,可以接收别人注册进来
    public class EurekaServer_7002 {
        public static void main(String[] args) {
            SpringApplication.run(EurekaServer_7002.class, args);
        }
    }

    application.yml

    server:
      port: 7002
    
    #Eureka配置
    eureka:
      instance:
        hostname: eureka7002.com #Eureka服务端的实例名字
      client:
        register-with-eureka: false #表示是否向 Eureka 注册中心注册自己(这个模块本身是服务器,所以不需要)
        fetch-registry: false #fetch-registry如果为false,则表示自己为注册中心
        service-url: #监控页面~
          #重写Eureka的默认端口以及访问路径 --->http://localhost:7001/eureka/
          # 单机: defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
          # 集群(关联):7002关联7001、7003
          defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7003.com:7003/eureka/

    8.4 、springcloud-eureka-7003

    创建Eureka注册中心7003项目(和7001一模一样)

    pom.xml

    依赖和7001一样

    EurekaServer_7003

    主启动类

    package com.bupt;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
    
    @SpringBootApplication
    @EnableEurekaServer //EnableEurekaServer表示服务端的启动类,可以接收别人注册进来
    public class EurekaServer_7003 {
        public static void main(String[] args) {
            SpringApplication.run(EurekaServer_7003.class, args);
        }
    }

    application.yml

    server:
      port: 7003
    
    #Eureka配置
    eureka:
      instance:
        hostname: eureka7003.com #Eureka服务端的实例名字
      client:
        register-with-eureka: false #表示是否向 Eureka 注册中心注册自己(这个模块本身是服务器,所以不需要)
        fetch-registry: false #fetch-registry如果为false,则表示自己为注册中心
        service-url: #监控页面~
          #重写Eureka的默认端口以及访问路径 --->http://localhost:7001/eureka/
          # 单机: defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
          # 集群(关联):7002关联7001、7003
          defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/

    然后启动7001、7002、7003项目

    然后访问:http://localhost:7001/ 、http://localhost:7002/ 、http://localhost:7003/

    8.5、8001项目注册多个注册中心
    要把8001项目注册到多个注册中心上去,其实很简单,只需要改动配置文件即可

    application.yml(8001)

    server:
      port: 8001
    
    mybatis:
      mapper-locations: classpath:mybatis/mapper/*.xml
      type-aliases-package: com.bupt.pojo
      configuration-properties: classpath:mybatis/mybatis-config.xml
    
    spring:
      application:
        name: springcloud-provider-dept
      datasource:
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://127.0.0.1:3306/db01?useUnicode=true&characterEncoding=UTF-8&useSSL=true&serverTimezone=UTC
        username: root
        password: root
    # Eureka配置:配置服务注册中心地址
    eureka:
      client:
        service-url:
          # 注册中心地址7001-7003
          defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
      instance:
        instance-id: springcloud-provider-dept-8001 #修改Eureka上的默认描述信息
    
    info:
      app.name: wulei-springcloud
      company.name: blog.wulei2921625957.com

    然后启动8001项目,刷新http://localhost:7001/ 、http://localhost:7002/ 、http://localhost:7003/ 即可发现

    9、CAP原则及对比Zookeeper

    在这里插入图片描述

    在这里插入图片描述

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

    在这里插入图片描述
    在这里插入图片描述

    10、Ribbon负载均衡

    ribbon是什么?

    在这里插入图片描述

    ribbon能干什么?

    在这里插入图片描述

    10.1、springcloud-consumer-dept-80使用Ribbon

    首先80项目要添加两个依赖

    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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <parent>
            <artifactId>springcloudLast</artifactId>
            <groupId>com.bupt</groupId>
            <version>1.0-SNAPSHOT</version>
        </parent>
        <modelVersion>4.0.0</modelVersion>
    
        <artifactId>springcloud-consumer-fdept-feign</artifactId>
    
        <properties>
            <maven.compiler.source>8</maven.compiler.source>
            <maven.compiler.target>8</maven.compiler.target>
        </properties>
        <dependencies>
            <dependency>
                <groupId>com.bupt</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>
            <!--Ribbon-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-ribbon</artifactId>
                <version>1.4.6.RELEASE</version>
            </dependency>
            <!--Eureka: Ribbon需要从Eureka服务中心获取要拿什么-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-eureka</artifactId>
                <version>1.4.6.RELEASE</version>
            </dependency>
            <!--Feign的依赖-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-feign</artifactId>
                <version>1.4.6.RELEASE</version>
            </dependency>
    
        </dependencies>
    </project>

    由于我们消费者客户端是利用RestTemplate来进行服务的读取,所以我们让RestTemplate实现负载均衡,只需要加一个注解即可@LoadBalanced

    ConfigBean

     @LoadBalanced
        @Bean
        public RestTemplate getRestTemplate(){
            return new RestTemplate();
        }

    由于我们导入了Eureka,所以我们要配置Eureka

    application.yml

    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/
    #spring:
    #  application:
    #    name: SpringBoot_easyPOI
    #  main:
    #    allow-bean-definition-overriding: true

    DeptConsumer_80

    package com.bupt;
    
    //import com.bupt.MyRule.MyRule;
    import com.MyRule.MyRules;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
    import org.springframework.cloud.netflix.ribbon.RibbonClient;
    
    @EnableEurekaClient
    @SpringBootApplication
    @RibbonClient(name = "SPRINGCLOUD-PROVIDER-DEPT", configuration = MyRules.class)
    public class DeptConsumer_80 {
        public static void main(String[] args) {
            SpringApplication.run(DeptConsumer_80.class,args);
        }
    }
    最后还有一个问题,就是我们的RestTemplate实现了负载均衡,那么怎么体现它呢?我们现在就只是在它身上加了一个注解,那肯定是不行的,我们还要改变RestTemplate的请求路径,让其自动选择,而不是写死

    DeptConsumerController
    //private static final String REST_URL_PREFIX = "http://localhost:8001";
    //用Ribbon做负载均衡的时候不应该写它,不应该写死,地址应该是一个变量,通过服务名来访问
    private static final String REST_URL_PREFIX = "http://SPRINGCLOUD-PROVIDER-DEPT";

    最后启动7001、7002、7003项目后再启动8001项目,等8001项目注册到它们3个中后启动80项目

    然后访问 http://localhost/consumer/dept/list 可以看到正常返回结果,当然了,在这里也看不出负载均衡,所以下面会配置多个服务提供者和多个数据库,来测试负载均衡的效果。

    10.2、使用Ribbon实现负载均衡


    创建另外两个数据库:db02、db03

     

    创建另外两个服务提供者:8002、8003

    直接新建两个子model,然后把8001的所有文件全部拷贝(提供相同的服务),一摸一样的,然后更改一下配置文件即可

    pom.xml依赖

    application.yml的端口号,对应的数据库,还有instance-id,例如:instance-id: springcloud-provider-dept8002

    注意:下面的这个服务ID不要改

    spring:
      application:
        name: springcloud-provider-dept  # 3个服务名称一致是前提

    现在的项目预览


    然后,启动

    springcloud-config-eureka-7001
    springcloud-config-eureka-7002
    springcloud-config-eureka-7003
    springcloud-provider-dept-8001
    springcloud-provider-dept-8002
    springcloud-provider-dept-8003
    springcloud-consumer-dept-80

    然后访问http://localhost/consumer/dept/list ,多访问几次,查询的数据没变,但是数据库变了

    你会发现是轮询,就是每个服务轮流来,这也Ribbon的默认算法

    Ribbon自定义均衡算法
    里面有个接口非常重要:IRule,基本上全部的均衡算法都实现了这个接口

    里面有这么多均衡算法,因为默认是轮询算法,也就是RoundRobinRule,那我们要怎么使用别的算法呢?

    只需要在80项目的config类里面注册Bean即可

    //IRule
    //RoundRobinRule:轮询
    //RandomRule:随机
    //AvailabilityFilteringRule:会先过滤掉跳闸、访问故障的服务~,对剩下的进行轮询
    //RetryRule:会先按照轮询获取服务,如果服务获取失败,则会在指定的时间内进行重试
    @Bean
    public IRule myRule() {
        return new RandomRule(); //默认为轮询,现在我们使用随机的
    }

    然后启动80项目,访问http://localhost/consumer/dept/list,多访问几次,发现每次出现的数据库都没规律可循

    我们要学会自定义负载均衡算法,为了体现我们使用了自定义的负载均衡算法,我们建包不建在主启动类的同级目录(官方建议)

     当两个Irule在同一个文件夹下,此时会冲突报错

     把刚刚写在ConfigBean里面的Bean注释掉(不能在扫描包下出现两个Irule),我们来模仿它的算法写一个自己的算法

    自定义类MyRandomRule

    package com.MyRule;
    
    import com.netflix.client.config.IClientConfig;
    import com.netflix.loadbalancer.AbstractLoadBalancer;
    import com.netflix.loadbalancer.AbstractLoadBalancerRule;
    import com.netflix.loadbalancer.ILoadBalancer;
    import com.netflix.loadbalancer.Server;
    
    import java.util.List;
    import java.util.concurrent.ThreadLocalRandom;
    
    
    public class MyRandomRule extends AbstractLoadBalancerRule {
    
        //每个机器,访问5次,换下一个服务(总共3个)
        //total = 0 默认=0,如果=5,我们指向下一个服务结点
        //index = 0 默认=0,如果total=5,那么index+1,
    
        private int total = 0; //被调用的次数
        private int currentIndex = 0; //当前是谁在提供服务
    
        public Server choose(ILoadBalancer lb, Object key) {
            if (lb == null) {
                return null;
            }
            Server server = null;
    
            while (server == null) {
                if (Thread.interrupted()) {
                    return null;
                }
                List<Server> upList = lb.getReachableServers(); //获得还活着的服务
                List<Server> allList = lb.getAllServers();  //获得全部的服务
    
                int serverCount = allList.size();
                if (serverCount == 0) {
                    return null;
                }
    
                //=============================================================
    
                if (total < 5) {
                    total++;
                } else {
                    total = 0;
                    currentIndex++;
                    if (currentIndex >= serverCount) {
                        currentIndex = 0;
                    }
                }
                server = upList.get(currentIndex);
                //=============================================================
                if (server == null) {
                    Thread.yield();
                    continue;
                }
    
                if (server.isAlive()) {
                    return (server);
                }
                server = null;
                Thread.yield();
            }
    
            return server;
    
        }
    
        protected int chooseRandomInt(int serverCount) {
            return ThreadLocalRandom.current().nextInt(serverCount);
        }
    
        @Override
        public Server choose(Object key) {
            return choose(getLoadBalancer(), key);
        }
    
        @Override
        public void initWithNiwsConfig(IClientConfig clientConfig) {
    
        }
    }

    MyRules

    package com.MyRule;
    
    import com.netflix.loadbalancer.IRule;
    import com.netflix.loadbalancer.RandomRule;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    @Configuration
    public class MyRules {
    
        @Bean
        public IRule testRule(){
            return new MyRandomRule();
        }
    
    }

    最后还要在主启动类添加扫描注解,在微服务启动的时候就能去加载我们自定义的Ribbon类

    DeptConsumer_80

    package com.bupt;
    
    //import com.bupt.MyRule.MyRule;
    import com.MyRule.MyRules;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
    import org.springframework.cloud.netflix.ribbon.RibbonClient;
    
    @EnableEurekaClient
    @SpringBootApplication
    @RibbonClient(name = "SPRINGCLOUD-PROVIDER-DEPT", configuration = MyRules.class)
    public class DeptConsumer_80 {
        public static void main(String[] args) {
            SpringApplication.run(DeptConsumer_80.class,args);
        }
    }

    然后重启80项目,访问http://localhost/consumer/dept/list,多访问几次,可以发现访问的服务每5次切换一下

    11、Feign负载均衡

    11.1、简介

    在这里插入图片描述

    11.2、Feign能干什么?

    在这里插入图片描述

    11.3、Feign集成了Ribbon

    在这里插入图片描述

    11.4 springcloud-consumer-dept-feign

    在这里插入图片描述

    创建一个springcloud-consumer-dept-feign空maven的空项目,这也是一个消费者,端口也是80,只是这个消费者使用Feign实现的负载均衡

    在这里插入图片描述

    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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <parent>
            <artifactId>springcloudLast</artifactId>
            <groupId>com.bupt</groupId>
            <version>1.0-SNAPSHOT</version>
        </parent>
        <modelVersion>4.0.0</modelVersion>
    
        <artifactId>springcloud-consumer-fdept-feign</artifactId>
    
        <properties>
            <maven.compiler.source>8</maven.compiler.source>
            <maven.compiler.target>8</maven.compiler.target>
        </properties>
        <dependencies>
            <dependency>
                <groupId>com.bupt</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>
            <!--Ribbon-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-ribbon</artifactId>
                <version>1.4.6.RELEASE</version>
            </dependency>
            <!--Eureka: Ribbon需要从Eureka服务中心获取要拿什么-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-eureka</artifactId>
                <version>1.4.6.RELEASE</version>
            </dependency>
            <!--Feign的依赖-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-feign</artifactId>
                <version>1.4.6.RELEASE</version>
            </dependency>
    
        </dependencies>
    </project>

    application.yml

    和springcloud-consumer-dept-80项目的一摸一样

    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/
    #spring:
    #  application:
    #    name: SpringBoot_easyPOI
    #  main:
    #    allow-bean-definition-overriding: true

    修改springcloud-api

    • 添加依赖

    • 并写上几个注解

    • feign注解实现的服务请求接口是和provider的controller请求路由保持一致,但是没有方法体
    package com.bupt.service;
    
    import com.bupt.pojo.Dept;
    import org.springframework.cloud.openfeign.FeignClient;
    import org.springframework.stereotype.Component;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.RequestBody;
    import org.springframework.web.bind.annotation.RequestMapping;
    
    import java.util.List;
    
    @Component
    @FeignClient(value = "SPRINGCLOUD-PROVIDER-DEPT")
    public interface DeptClientService {
    
        @RequestMapping("/dept/add")
        public boolean addDept(@RequestBody Dept dept) ;
    
    
        @GetMapping("/dept/get/{id}")
        public Dept getDept(@PathVariable("id") Long id) ;
    
        @GetMapping("/dept/list")
        public List<Dept> queryAll() ;
    }

    然后在springcloud-consumer-dept-feign项目的controller也要做相应的修改

    DeptConsumerController

    package com.bupt.controller;
    
    import com.bupt.pojo.Dept;
    import com.bupt.service.DeptClientService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.*;
    
    import java.util.List;
    
    @RestController
    public class DeptConsumerController {
    
        @Autowired
        private DeptClientService deptClientService = null;
    
        @RequestMapping("/consumer/dept/get/{id}")
        public Dept queryById(@PathVariable("id") long id){
            return this.deptClientService.getDept(id);
        }
    
        @RequestMapping("/consumer/dept/add")
        public boolean add(@RequestBody Dept dept){
            return this.deptClientService.addDept(dept);
        }
    
        @RequestMapping("/consumer/dept/list")
        public List<Dept> queryAll(){
            return this.deptClientService.queryAll();
        }
    
    }

    最后还要在启动类上添加FeignClient注解

    FeignDeptConsumer_80

    package com.bupt;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.openfeign.EnableFeignClients;
    import org.springframework.cloud.openfeign.FeignClient;
    
    @SpringBootApplication
    @EnableFeignClients(basePackages = {"com.bupt"})
    public class FeignDeptConsumer_80 {
        public static void main(String[] args) {
            SpringApplication.run(FeignDeptConsumer_80.class,args);
        }
    
    }

    最后启动7001、… 、8001、… 、feign的80项目,测试

    作者:你的雷哥
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须在文章页面给出原文连接,否则保留追究法律责任的权利。
  • 相关阅读:
    开源工作流 Bonita BPM (JAVA)
    java怎么样判断一个进程是否已近结束
    struts2 Annotation 实现文件下载功能 文件名中文乱码问题
    struts2中s:radio标签的使用 Map
    Win7下声音由小逐渐变大
    JSTL EL 详解
    CHM格式 打开后不显示内容的解决办法
    jquery radio 判断是否被选中的例子
    火狐的funmoods都已经清除了,config里怎么还有他它的项目
    由MyEclipse内存不足谈谈JVM内存
  • 原文地址:https://www.cnblogs.com/henuliulei/p/14833686.html
Copyright © 2011-2022 走看看