springcloud简单使用

新版本笔记SpringCloud/Alibaba
https://www.yuque.com/docs/share/2052cf75-a1ac-436e-b12d-2293397ba413?#

环境搭建

  • 新建 maven 项目,管理依赖
    <!--打包方式  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.12</junit.version>
        <log4j.version>1.2.17</log4j.version>
        <lombok.version>1.16.18</lombok.version>
    </properties>
    
    <dependencyManagement>
        <dependencies>
            <!--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>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>5.1.47</version>
            </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>
    
  • 新建 maven 项目,springcloud-api,导入依赖
    <!-- 因为我们在父项目中做了依赖的管理,不用指定版本号 -->
    <dependencies>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
    </dependencies>
    
  • 编写实体类 Dept
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    @Accessors(chain = true) //链式编程
    public class Dept implements Serializable {
    
        // 部门编号
        private Long deptno;
        // 部门名称
        private String dname;
        // 数据库名
        private String db_source;
    
    }
    

服务提供方

  • 新建 maven 项目, springcloud-dept-provider-8001,导入依赖
    
    <dependencies>
        <dependency>
            <groupId>com.starry</groupId>
            <artifactId>springcloud-api</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
        </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>
    
  • 编写 springboot 配置文件 application.yml
    server:
      port: 8001
    
    mybatis:
      type-aliases-package: com.starry.pojo
      mapper-locations: classpath:mybatis/mapper/*.xml
    
    spring:
      application:
        name: springcloud-dept-provider
      datasource:
        driver-class-name: com.mysql.jdbc.Driver
        url: jdbc:mysql:///springcloud?useUnicode=true&characterEncoding=utf-8
        username: root
        password: root
        type: com.alibaba.druid.pool.DruidDataSource
    
  • 编写 mapper
    @Mapper
    @Repository
    public interface DeptMapper {
    
        boolean addDept(Dept dept);
    
        Dept queryById(Long id);
    
        List<Dept> queryAll();
    }
    
  • 编写 mapper 对应的 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.starry.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>
    
  • 编写 service
    public interface DeptService {
    
    boolean addDept(Dept dept);
    
    Dept queryById(Long id);
    
    List<Dept> queryAll();
    }
    
  • service实现类
    @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();
        }
    }
    
  • 编写 controller
    @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){
            Dept dept = deptService.queryById(id);
            return dept;
        }
    
        @GetMapping("/dept/list")
        public List<Dept> queryAll(){
            return deptService.queryAll();
        }
    }
    
  • 编写启动类
    @SpringBootApplication
    public class DeptProviderApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(DeptProviderApplication.class, args);
        }
    }
    
  • 运行启动类,访问对应的controller,正常访问

服务消费方

  • 新建 maven 项目,springcloud-dept-consumer-80,导入依赖
    <dependencies>
        <dependency>
            <groupId>com.starry</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>
    
  • 编写配置文件 application.yml
    server:
      port: 80
    
  • 将 RestTemplate 注入到容器
    /**
     * 将 RestTemplate 注入到spring容器
     */
    @Configuration
    public class ConfigBean {
    
        @Bean
        public RestTemplate getRestTemplate(){
            return new RestTemplate();
        }
    }
    
  • 编写 controller
    @RestController
    public class DeptConsumerController {
    
    
        /**
         * 使用 RestTemplate 访问远程http服务
         * getForObject get请求获取对象
         * postForObject post请求获取对象
         * (String url, Class<T> responseType, Object... uriVariables)
         * url地址,返回值类型,传递参数
         */
        @Autowired
        private RestTemplate restTemplate;
    
        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);
        }
    }
    
  • 编写启动类
    @SpringBootApplication
    public class DeptConsumerApplication {
        public static void main(String[] args) {
            SpringApplication.run(DeptConsumerApplication.class, args);
        }
    }
    
  • 运行启动类,访问对应的controller,正常访问

Eureka(注册中心)

eureka server

  • 新建 maven 项目,导入依赖
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka-server</artifactId>
            <version>1.4.6.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
        </dependency>
    </dependencies>
    
  • 编写 springboot 配置文件 application.yml
    server:
      port: 7001
    eureka:
      instance:
        hostname: localhost
      client:
        register-with-eureka: false # 实例是否在eureka服务器上注册自己的信息以供其他服务发现,默认为true
        fetch-registry: false # 此客户端是否获取eureka服务器注册表上的注册信息,默认为true
        service-url:
          defaultZone: http://localhost:7001/eureka # 注册地址
    
  • 编写启动类 在启动类上加上 @EnableEurekaServer 注解激活 eureka-server 的配置
    @SpringBootApplication
    @EnableEurekaServer
    public class EurekaServerApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(EurekaServerApplication.class, args);
        }
    }
    
  • 运行启动类,访问 http://localhost:7001/,出现eureka的界面
    在这里插入图片描述

总结:

  • 导入依赖
  • 编写配置文件
  • 启动类添加 @EnableEurekaServer 注解

eureka client

springcloud-dept-provider-8001 注册到 eureka

  • 添加依赖

    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-eureka</artifactId>
        <version>1.4.6.RELEASE</version>
    </dependency>
    
  • 添加Eureka的配置,服务注册到哪里

    eureka:
      client:
        service-url:
          defaultZone: http://localhost:7001/eureka
    
  • 在启动类上加上 @EnableEurekaClient 注解

    @SpringBootApplication
    @EnableEurekaClient
    public class DeptProviderApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(DeptProviderApplication.class, args);
        }
    }
    
  • 先启动 EurekaServerApplication ,再启动 DeptProviderApplication, 访问 http://localhost:7001/ ,可以看见 springcloud-dept-provider 成功注册到eureka了
    在这里插入图片描述

  • 修改默认描述信息

    eureka:
      client:
        service-url:
          defaultZone: http://localhost:7001/eureka
      instance:
        instance-id: springcloud-dept-provider-8001 # 修改eureka上的默认描述信息
        prefer-ip-address: true # 显示服务的ip地址
    

    修改成功
    在这里插入图片描述

  • 监控信息,导入依赖

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

    info:
      app.name: dept-provider
      company.name: starry
    
  • 点击 链接
    在这里插入图片描述
    跳转到信息页
    在这里插入图片描述

  • 获取微服务信息, DeptController,添加方法

    @Autowired
    private DiscoveryClient client;
    
    @GetMapping("/dept/discovery")
    public DiscoveryClient getClient(){
       // 获取微服务列表
       List<String> services = client.getServices();
       System.out.println(services);
    
       // 根据id获取具体的微服务 applicaioinName
       List<ServiceInstance> instances = client.getInstances("springcloud-dept-provider");
       for (ServiceInstance instance : instances) {
           System.out.println(instance.getHost());
           System.out.println(instance.getPort());
           System.out.println(instance.getUri());
           System.out.println(instance.getServiceId());
       }
       return this.client;
    }
    
  • DeptProviderApplication 启动类添加注解 @EnableDiscoveryClient

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

    访问controller http://localhost:8001/dept/discovery
    在这里插入图片描述
    控制台输出结果

    [springcloud-dept-provider]
    
    MagicBookPro
    8001
    http://MagicBookPro:8001
    SPRINGCLOUD-DEPT-PROVIDER
    

总结:

  • 导入依赖
  • 编写配置文件
  • 启动类添加 @EnableEurekaClient 注解

eureka自我保护机制

  默认情况下,如果Eureka Server在一定时间内(默认90秒)没有接收到某个微服务实例的心跳,Eureka Server将会移除该实例。但是当网络分区故障发生时,微服务与Eureka Server之间无法正常通信,而微服务本身是正常运行的,此时不应该移除这个微服务,所以引入了自我保护机制。

在这里插入图片描述

  如果在15分钟内超过85%的客户端节点都没有正常的心跳,那么Eureka就认为客户端与注册中心出现了网络故障,Eureka Server自动进入自我保护机制,此时会出现以下几种情况:

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

  • Eureka Server仍然能够接受新服务的注册和查询请求,但是不会被同步到其它节点上,保证当前节点依然可用。

  • 当网络稳定时,当前Eureka Server新的注册信息会被同步到其它节点中。

eureka server

eureka:
  server:
     enable-self-preservation: false # 是否启用自我保护
     eviction-interval-timer-in-ms: 3000 # #清理间隔(单位毫秒,默认是60*1000)

eureka client

eureka: 
  instance:
    #eureka客户端需要多长时间发送心跳给eureka服务器,表明他仍然活着,默认30秒
    lease-renewal-interval-in-seconds: 5
    #eureka服务器在接收到实例的最后一次发出的心跳后,需要等待多久才可以将此实例删除
    lease-expiration-duration-in-seconds: 10
  client: 
    #表示eureka client间隔多久去拉取服务器注册信息,默认为30秒
    registry-fetch-interval-seconds: 30
    #表示eureka client间隔多久去拉取服务器注册信息,默认为30秒
    registry-fetch-interval-seconds: 30

eureka集群配置

更改本地的 hosts 配置文件 c:\windows\system32\drivers\etc

# eureka
127.0.0.1 eureka7001.com
127.0.0.1 eureka7002.com
127.0.0.1 eureka7003.com
  • 新建 maven 项目 springcloud-eureka-7002和springcloud-eureka-7003
  • 复制 springcloud-eureka-7001 的 application.yml 和 启动类
  • 修改配置文件
    • springcloud-eureka-7001
      server:
        port: 7001
      eureka:
        instance:
          hostname: eureka7001.com
        client:
          register-with-eureka: false # 实例是否在eureka服务器上注册自己的信息以供其他服务发现,默认为true
          fetch-registry: false # 此客户端是否获取eureka服务器注册表上的注册信息,默认为true
          service-url:
            defaultZone: http://eureka7002.com:7002/eureka,http://eureka7003.com:7003/eureka # 注册地址
      
    • springcloud-eureka-7002
      server:
        port: 7002
      eureka:
        instance:
          hostname: eureka7002.com
        client:
          register-with-eureka: false # 实例是否在eureka服务器上注册自己的信息以供其他服务发现,默认为true
          fetch-registry: false # 此客户端是否获取eureka服务器注册表上的注册信息,默认为true
          service-url:
            defaultZone: http://eureka7001.com:7001/eureka,http://eureka7003.com:7003/eureka # 注册地址
      
    • springcloud-eureka-7003
      server:
        port: 7003
      eureka:
        instance:
          hostname: eureka7003.com
        client:
          register-with-eureka: false # 实例是否在eureka服务器上注册自己的信息以供其他服务发现,默认为true
          fetch-registry: false # 此客户端是否获取eureka服务器注册表上的注册信息,默认为true
          service-url:
            defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka # 注册地址
      
    • 修改 springcloud-dept-provider-8001 的服务注册地址
      eureka:
        client:
          service-url:
            defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka,http://eureka7003.com:7003/eureka
        instance:
          instance-id: springcloud-dept-provider-8001 # 修改eureka上的默认描述信息
      
  • 分别启动, springcloud-eureka-7001,springcloud-eureka-7002,springcloud-eureka-7003,springcloud-dept-provider-8001
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
  • 关闭一个服务,其他2个服务还是正常

Ribbon(负载均衡)

  • springcloud-dept-consumer-80 导入依赖

    <!--Ribbon-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-ribbon</artifactId>
        <version>1.4.6.RELEASE</version>
    </dependency>
    <!--erueka-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-eureka</artifactId>
        <version>1.4.6.RELEASE</version>
    </dependency>
    
  • 添加配置

    server:
      port: 80
    eureka:
      client:
        register-with-eureka: false
        service-url:
          defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka,http://eureka7003.com:7003/eureka
    
  • 启动类加上 @EnableEurekaClient 注解

    @SpringBootApplication
    @EnableEurekaClient
    public class DeptConsumerApplication {
        public static void main(String[] args) {
            SpringApplication.run(DeptConsumerApplication.class, args);
        }
    }
    
  • 配置类上加上 @LoadBalanced 注解

    @Configuration
    public class ConfigBean {
    
        @Bean
        @LoadBalanced // 标记这个RestTemplate要做负载均衡
        public RestTemplate getRestTemplate(){
            return new RestTemplate();
        }
    }
    
  • 修改controller中restTemplate的请求地址

    /**
     * 由于我们做了负载均衡,每次请求的地址不能固定,根据服务名来访问
     */
    private static final String REST_URL_PREFIX = "http://springcloud-dept-provider";
    
  • 服务全部启动,集群正常访问,controller也正常访问,但是返回的数据都是一样的,看不出负载均匀效果

  • 新建2个数据库

    • 在这里插入图片描述

    • 在这里插入图片描述

    • 在这里插入图片描述

    • 在这里插入图片描述

  • 新建 maven 项目 springcloud-dept-provider-8002springcloud-dept-provider-8003,复制 springcloud-dept-provider-8001 的文件,修改 application.yml ,只需修改 端口号,连接的数据库实例id ; 应用名称不用改,因为我们负载均衡是根据应用名来获取服务的

    springcloud-dept-provider-8002

    server:
      port: 8002
    
    mybatis:
      type-aliases-package: com.starry.pojo
      mapper-locations: classpath:mybatis/mapper/*.xml
    
    spring:
      application:
        name: springcloud-dept-provider
      datasource:
        driver-class-name: com.mysql.jdbc.Driver
        url: jdbc:mysql:///springcloud2?useUnicode=true&characterEncoding=utf-8
        username: root
        password: root
        type: com.alibaba.druid.pool.DruidDataSource
    
    eureka:
      client:
        service-url:
          defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka,http://eureka7003.com:7003/eureka
      instance:
        instance-id: springcloud-dept-provider-8002 # 修改eureka上的默认描述信息
        prefer-ip-address: true # 显示服务的ip地址
    
    
    info:
      app.name: dept-provider
      company.name: starry
    

    springcloud-dept-provider-8003

    server:
      port: 8003
    
    mybatis:
      type-aliases-package: com.starry.pojo
      mapper-locations: classpath:mybatis/mapper/*.xml
    
    spring:
      application:
        name: springcloud-dept-provider
      datasource:
        driver-class-name: com.mysql.jdbc.Driver
        url: jdbc:mysql:///springcloud3?useUnicode=true&characterEncoding=utf-8
        username: root
        password: root
        type: com.alibaba.druid.pool.DruidDataSource
    
    eureka:
      client:
        service-url:
          defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka,http://eureka7003.com:7003/eureka
      instance:
        instance-id: springcloud-dept-provider-8003 # 修改eureka上的默认描述信息
        prefer-ip-address: true # 显示服务的ip地址
    
    
    info:
      app.name: dept-provider
      company.name: starry
    
  • 启动全部服务,集群正常访问,controller正常访问,访问 http://localhost/consumer/dept/list ,出现不同的结果,成功实现负载均衡

    1. 在这里插入图片描述
    2. 在这里插入图片描述
    3. 在这里插入图片描述

修改负载均衡规则

  • 编写自定义规则
  1. @Configuration 注解
  2. @Bean 注解
  3. 返回 IRule 的实现
    @Configuration
    public class MyRule {
    
        @Bean
        public IRule getRule(){
            return new RandomRule();
        }
    }
    
  • 在启动类上加上 @RibbonClient 注解
    @SpringBootApplication
    @EnableEurekaClient
    /**
     * 使用自定义的负载均衡规则,自定义的负载均衡类不能放在启动类同级目录及子目录,不然会被所有@RibbonClients共享
     * name 服务提供方的名称
     * configuration 自定义的IRule类
     */
    @RibbonClient(name = "springcloud-dept-provider",configuration = MyRule.class)
    public class DeptConsumerApplication {
        public static void main(String[] args) {
            SpringApplication.run(DeptConsumerApplication.class, args);
        }
    }
    
  • 启动服务,访问 http://localhost/consumer/dept/list ,随机访问不同微服务,返回的数据也不用

总结:

  • 导入依赖
  • 编写配置文件,从哪获取服务
  • RestTemplate 上加上 @LoadBalanced 注解
  • 如果要修改负载均衡算法,自定义算法,在启动类加上 @RibbonClient 注解

Feign(服务调用)

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

  1. 微服务名字[ ribbon ]
  2. 接口和注解[ feign ]

使用 Feign 只需要创建一个接口并使用一个注解来配置它即可,这就类似于我们在 dao 层的接口上标注 @Mapper 注解一样。

feign集成了ribbon

  • springcloud-api 导入依赖

    <dependencies>
        <!--feign-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-feign</artifactId>
            <version>1.4.6.RELEASE</version>
        </dependency>
    
        <!--erueka-->
        <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-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
        </dependency>
    
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
    </dependencies>
    
  • 新建服务接口,请求 url 要和提供方的 url 一样

    /**
     * 要使用的微服务的名称(服务提供方)
     */
    @FeignClient(name = "springcloud-dept-provider")
    @Service
    public interface DeptClientService {
    
    
        @RequestMapping("/dept/add")
        public boolean add(Dept dept);
    
        @RequestMapping("/dept/get/{id}")
        public Dept get(@PathVariable("id")Long id);
    
        @RequestMapping("/dept/list")
        public List<Dept> list();
    
    }
    
  • 新建 maven 项目 springcloud-dept-consumer-feign,导入依赖

    <dependencies>
        <!--feign-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-feign</artifactId>
            <version>1.4.6.RELEASE</version>
        </dependency>
        <!--ribbon-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-ribbon</artifactId>
            <version>1.4.6.RELEASE</version>
        </dependency>
        <!--erueka-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka</artifactId>
            <version>1.4.6.RELEASE</version>
        </dependency>
    
        <dependency>
            <groupId>com.starry</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>
    
  • application.yml

    server:
      port: 80
    eureka:
      client:
        register-with-eureka: false
        service-url:
          defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka,http://eureka7003.com:7003/eureka
    
  • controller 调用 springcloud-api 的 service

    @RestController
    public class DeptConsumerController {
    
    
        @Autowired
        private DeptClientService service;
    
        @RequestMapping("/consumer/dept/add")
        public boolean add(Dept dept) {
            return service.add(dept);
        }
    
        @RequestMapping("/consumer/dept/get/{id}")
        public Dept get(@PathVariable("id") Long id) {
            return service.get(id);
        }
    
    
        @RequestMapping("/consumer/dept/list")
        public List<Dept> list() {
            return service.list();
        }
    }
    
  • 启动类 加上 @EnableFeignClients 注解

    @SpringBootApplication
    @EnableEurekaClient
    @EnableFeignClients
    public class FeignDeptConsumerApplication {
        public static void main(String[] args) {
            SpringApplication.run(FeignDeptConsumerApplication.class, args);
        }
    }
    
  • 启动服务,正常访问 ; 配置负载均衡算法

    # 服务名
    springcloud-dept-provider:
      ribbon:
        NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule # 类路径
    

总结:

  • 导入依赖
  • 编写和服务提供方方法相同的接口,并加上 @FeignClient 注解并指定服务提供方的名称
  • 使用方使用只需注入接口便可调用方法
  • 启动类上加上 @EnableFeignClients 注解

Hystrix

服务熔断(服务提供方)

  • 新建 maven 项目 springcloud-dept-provider-hystrix-8001,复制 springcloud-dept-provider-8001 ,导入 hystrix 依赖

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-hystrix</artifactId>
            <version>1.4.6.RELEASE</version>
        </dependency>
    
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
    
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka</artifactId>
            <version>1.4.6.RELEASE</version>
        </dependency>
    
        <dependency>
            <groupId>com.starry</groupId>
            <artifactId>springcloud-api</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
        </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>
    
  • controller中添加方法

    @GetMapping("/dept/get/{id}")
    // 指定回退方法
    @HystrixCommand(fallbackMethod = "hystrixGet")
    public Dept get(@PathVariable("id") Long id){
        Dept dept = deptService.queryById(id);
        if (dept == null){
            throw  new RuntimeException("no this dept");
        }
        return dept;
    }
    
    
    /**
     * 回退方法,出现异常或者超时会调用此方法
     * @param id
     * @return
     */
    public Dept hystrixGet(Long id){
        return new Dept(id, "未查询到信息", "数据库中没有此信息");
    }
    
  • 启动类添加 @EnableCircuitBreaker 注解 开启熔断支持

    @SpringBootApplication
    @EnableEurekaClient
    @EnableCircuitBreaker
    public class HystrixDeptProviderApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(HystrixDeptProviderApplication.class, args);
        }
    }
    
  • service接口指定回退工厂

    @FeignClient(name = "springcloud-dept-provider",fallbackFactory = DeptClientServiceFallbackFactory.class)
    @Service
    public interface DeptClientService
    
  • 启动服务,访问对应的controller,
    http://localhost/consumer/dept/get/1 ,正常返回数据
    在这里插入图片描述

    http://localhost/consumer/dept/get/9 ,调用了备用方法
    在这里插入图片描述

服务降级(服务使用方)

  • springcloud-api 新建 DeptClientServiceFallbackFactory 类, 实现 FallbackFactory 接口, 重写方法,返回值为服务实例,最后将类注入spring容器

    @Component
    public class DeptClientServiceFallbackFactory implements FallbackFactory {
        @Override
        public DeptClientService create(Throwable throwable) {
            return new DeptClientService() {
                @Override
                public boolean add(Dept dept) {
                    return false;
                }
    
                @Override
                public Dept get(Long id) {
                    return new Dept(id,"这是客户端的降级信息,这个服务已经被关闭了","没有数据~");
                }
    
                @Override
                public List<Dept> list() {
                    return null;
                }
            };
        }
    }
    
  • 修改 feign 客户端(springcloud-dept-consumer-feign)的配置 开启feign的hystrix支持

    feign:
      hystrix:
        enabled: true
    
  • 启动服务(注册中心,服务提供方,服务使用方[feign])

    访问 http://localhost/consumer/dept/get/2
    在这里插入图片描述
    关闭服务提供方,返回工厂方法的数据
    在这里插入图片描述

流监控

  • 新建 maven 项目 springcloud-dept-consumer-hystrix-dashboard ,导入依赖

    <dependencies>
    
        <!--hystrix-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-hystrix</artifactId>
            <version>1.4.6.RELEASE</version>
        </dependency>
        <!--hystrix-dashboard-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-hystrix-dashboard</artifactId>
            <version>1.4.6.RELEASE</version>
        </dependency>
    
    </dependencies>
    
  • 编写配置文件

    server:
      port: 9001
    
  • 启动类加上 @EnableHystrixDashboard 注解 开启监控

    @SpringBootApplication
    @EnableHystrixDashboard
    public class HystrixDashboardApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(HystrixDashboardApplication.class, args);
        }
    }
    
  • 在需要监控的服务提供方(HystrixDeptProviderApplication)加上hystrix的servlet映射
    前提: 需要导入 hystrixactuator 依赖

    <!--hystrix-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-hystrix</artifactId>
        <version>1.4.6.RELEASE</version>
    </dependency>
    
    <!--监控-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
    
    /**
     * 在需要监控的服务提供方添加hystrix的servlet映射
     * @return
     */
    @Bean
    public ServletRegistrationBean registrationBean(){
        ServletRegistrationBean bean = new ServletRegistrationBean(new HystrixMetricsStreamServlet());
        bean.addUrlMappings("/actuator/hystrix.stream");
        return bean;
    }
    
  • 启动服务,访问 http://localhost:9001/hystrix 跳转到服务监控页间, 输入需要监控的服务提供方 ip地址+端口+/actuator/hystrix.stream
    在这里插入图片描述
    在这里插入图片描述

Zuul(路由网关)

  • 新建 maven 项目,导入依赖
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-zuul</artifactId>
            <version>1.4.6.RELEASE</version>
        </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-devtools</artifactId>
        </dependency>
    </dependencies>
    
  • 编写配置
    server:
      port: 9527
    
    spring:
      application:
        name: spring-zuul
    
    eureka:
      client:
        service-url:
          defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka,http://eureka7003.com:7003/eureka
      instance:
        instance-id: spring-zuul
        prefer-ip-address: true
    
    info:
      app.name: spring-zuul
      company: starry
    
  • 编写启动类 添加 @EnableZuulProxy 注解
    @SpringBootApplication
    @EnableZuulProxy
    public class ZuulApplication {
        public static void main(String[] args) {
            SpringApplication.run(ZuulApplication.class, args);
        }
    }
    
  • 启动服务(注册中心,服务提供方,服务销毁方,网关)
    • 直接访问访问提供方的controller http://localhost:8001/dept/get/1,正常返回数据
    • 可以看到是 ip地址+端口+uri,每个微服务的ip和端口都不一样,我们希望不直接显示微服务地址和服务名
      • 修改 hosts 模拟网关的地址
        127.0.0.1 starryzuul.com
        
      • 默认的转发规则就是 API 网关地址+访问的服务名称+接口 URI;访问 http://starryzuul.com:9527/springcloud-dept-provider/dept/get/1 实现不直接显示微服务地址
      • 配置文件配置路由规则
        # 配置路由
        zuul:
          routes:
            # 自定义服务名
            provider:
              # 要被转发的服务名
              serviceId: springcloud-dept-provider
              # 转发路径
              path: /provider/**
        
      • 将默认的服务器修改为自定义的服务名,服务 http://starryzuul.com:9527/provider/dept/get/9 ,正常返回结果
      • 虽然可以通过自定义的访问名可以访问,但是原来的服务器也还是可以访问,我们希望只能自定义的服务名可以访问;再次添加配置
        # 配置路由
        zuul:
          routes:
            # 自定义服务名
            provider:
              # 要被转发的服务名
              serviceId: springcloud-dept-provider
              # 转发路径
              path: /provider/**
          # 忽略的服务,不能通过这个访问名访问
          # ignored-services: "*" 除了自定义的服务其它的服务都被忽略
          ignored-services: springcloud-dept-provider
        
      • 配置路由前缀
        # 配置路由
        zuul:
         routes:
           # 自定义服务名
           provider:
             # 要被转发的服务名
             serviceId: springcloud-dept-provider
             # 转发路径
             path: /provider/**
         # 忽略的服务,不能通过这个访问名访问
         ignored-services: springcloud-dept-provider
         # 所有路由的前缀
         prefix: /starry
        
      • 服务器前加 /starry 才能访问 ,http://starryzuul.com:9527/starry/provider/dept/get/1

SpringCloudConfig

准备工作

  1. 安装git
  2. gitee(码云) 新建仓库,上传 application.yml
    # 下载一个项目和它的整个代码历史
    $ git clone [url]
    
    # 设置提交代码时的用户信息
    $ git config [--global] user.name "[name]"
    $ git config [--global] user.email "[email address]"
    
    # 添加当前目录的所有文件到暂存区
    git add .
    
    # 提交暂存区到仓库区
    $ git commit -m [message]
    
    # 推送到远程主分支
    $ git push origin master
    
    application.yml
    spring:
        profiles:
            active: test
            
    ---
    spring:
        profiles: dev
        application:
            name: springcloud-client-dev
    
    server:
      port: 7777
    eureka:
      client:
        service-url:
          defaultZone: http://eureka7001.com:7001/eureka
          
          
    ---
    spring:
        profiles: test
        application:
            name: springcloud-client-dev
    server:
      port: 7778
    eureka:
      client:
        service-url:
          defaultZone: http://eureka7002.com:7002/eureka
    
    

服务端获取gitee配置

  • 新建 maven 项目 springcloud-config-server-3344 ,导入依赖
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-config-server</artifactId>
            <version>2.1.1.RELEASE</version>
        </dependency>
    </dependencies>
    
  • 编写配置文件
    server:
      port: 3344
    
    spring:
      application:
        name: springcloud-config-server
      cloud:
        config:
          server:
            git:
           	  # gitee 地址
              uri: https://gitee.com/fanxingweb/springcloud-config.git
    
  • 编写启动类,添加 @EnableConfigServer 注解
    @SpringBootApplication
    @EnableConfigServer
    public class ConfigApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(ConfigApplication.class, args);
        }
    }
    
  • 启动应用,
    • 访问 http://localhost:3344/application-dev.yml 返回 dev 环境的配置
      也可以通过 http://localhost:3344/master/application-test.yml 访问
    • 访问 http://localhost:3344/application-test.yml 返回 test 环境的配置

客户端连接访问远程访问

  • 新建 maven 项目 springcloud-config-client,导入依赖
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-config</artifactId>
            <version>2.1.1.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>
    
  • 编写配置文件
    • bootstrap.yml

      # 系统级别的配置 优先加载
      spring:
        cloud:
          config:
            # 服务端地址
            uri: http://localhost:3344
            # 文件名 不带后缀
            name: clientConfig
            # 分支
            label: master
            # 环境
            profile: test
      
    • application.yml

      # 用户级别的配置
      spring:
        application:
          name: springcloud-config-client
      
  • 编写启动类
    @SpringBootApplication
    public class ClientConfigApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(ClientConfigApplication.class, args);
        }
    }
    
  • 测试是否能正常读取配置
    @RestController
    public class ClientController {
    
        @Value("${spring.application.name}")
        private String applicationName;
    
        @Value("${eureka.client.service-url.defaultZone}")
        private String defaultZone;
    
        @Value("${server.port}")
        private String port;
    
        @RequestMapping("/config")
        public String getConfig(){
            return "applicationName=>" + applicationName +"\t"+
                    "defaultZone=>" + defaultZone +"\t"+
                    "port=>" + port;
        }
    }
    
  • 启动服务,由于我们配置的是 test 环境,对应端口是 7777,访问 http://localhost:7777/config ,正常显示
    applicationName=>springcloud-client-dev defaultZonehttp://eureka7001.com:7001/eureka port7777
    

完整代码

springcloud简单使用

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值