我是靠谱客的博主 优秀鞋垫,最近开发中收集的这篇文章主要介绍springCloud实践SpringBoot+SpringCloud+Eureka+Feign+Ribbon+Hystrix+Zuul+Mybatis一、SpringCloud是什么?总结,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

SpringBoot+SpringCloud+Eureka+Feign+Ribbon+Hystrix+Zuul+Mybatis

文章目录

  • SpringBoot+SpringCloud+Eureka+Feign+Ribbon+Hystrix+Zuul+Mybatis
  • 一、SpringCloud是什么?
        • 新建项目spring-cloud-parent做为这个项目统一管理pom的jar,
          • 1.Eureka
          • 2.服务提供者
          • 3.feign(服务消费者)
          • 4.ribbon+RestTemplate(服务消费者)
          • 5.Zuul
  • 总结


本文实例采用springboot、springCloud、eureka、feign/ribbon、hystrix、zuul、mybatis

提示:以下是本篇文章正文内容,下面案例可供参考

一、SpringCloud是什么?

spring-cloud是微服务架构的集成者,将一系列优秀的组件进行了整合。
基于spring-boot构建,以spring-boot方式做到一键启动和部署,能够快速构建微服务系统与第三方对接

整体结构如下:

新建项目spring-cloud-parent做为这个项目统一管理pom的jar,

详细pom如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.2.RELEASE</version>
        <relativePath/>
    </parent>
    <groupId>com.example</groupId>
    <artifactId>spring-cloud-parent</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>spring-cloud-parent</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <spring-cloud.version>Finchley.SR2</spring-cloud.version>
    </properties>

    <dependencyManagement>
        <dependencies>
				<dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter</artifactId>
                <version>2.0.2.RELEASE</version>
            </dependency>
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid-spring-boot-starter</artifactId>
                <version>1.1.0</version>
            </dependency>
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>


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

</project>
1.Eureka

eureka就是一个服务中心,将所有的可以提供的服务都注册到它这里来管理,调用者需要的时候去注册中心获取,然后在进行调用,方便后续的水平扩展、故障转移

1. 1、新创建一个注册中心springcloud-service-eureka,让其他的服务暴露在注册中心,主要引入
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
            <version>2.0.0.RELEASE</version>
        </dependency>

详细pom如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.example</groupId>
        <artifactId>spring-cloud-parent</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <relativePath>../pom.xml</relativePath>
    </parent>
    <groupId>com.example</groupId>
    <artifactId>springcloud-service-eureka</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>springcloud-service-eureka</name>
    <description>service registry</description>

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

    <dependencies>

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

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
            <version>2.0.0.RELEASE</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <mainClass>com.example.springcloud.service.eureka.SpringcloudServiceEurekaApplication</mainClass>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

1. 2、此项目只作为一个注册中心,所以不需要过多的代码,只需要启动此项目,在启动类上加上Eureka的注解@EnableEurekaServer表示为注册中心服务,详细代码如下:
package com.example.springcloud.service.eureka;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

@EnableEurekaServer
@SpringBootApplication
public class SpringcloudServiceEurekaApplication {

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

}

1. 3、配置文件中说明对外的服务名称、暴露服务的ip和端口,在application.yml中加入Eureka配置,详情如下:
#eureka的端口号
spring:
application:
# 对外的服务名
name: springcloud-service-eureka

server:
#分配端口
port: 8001

eureka:
instance:
#eureka的主机
hostname: localhost
client:
#因为此项目本身就是一个服务,是用来别的服务注册到本项目中,不向注册中心注册自己
registerWithEureka: false 
fetchRegistry: false
serviceUrl:
#对外提供的服务地址
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
1. 4、启动项目,可以访问http://localhost:8001查看Eureka,如下图:

在这里插入图片描述

注册中心已经创建完成了,下面开始建立服务的提供者,新建springCloud-service-provider,此服务和数据库交互,所以需要引入mysql、mybatis、jdbc等依赖
2.服务提供者
2.1、 在pom中加入Eureka相关依赖,详情如下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.example</groupId>
        <artifactId>spring-cloud-parent</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <relativePath>../pom.xml</relativePath>
    </parent>
    <groupId>com.example</groupId>
    <artifactId>springcloud-service-provider</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>springcloud-service-provider</name>
    <description>eureka provider client</description>

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

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
            <version>2.1.0.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
            <version>2.0.0.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>1.1.1</version>
        </dependency>
        <!-- alibaba的druid数据库连接池 -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.0</version>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <mainClass>com.example.springcloud.service.provider.ProviderApplication</mainClass>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

2.2、 配置服务提供者配置文件,需要配置数据库信息,注册中心配置、mybatis配置等,详情如下:
spring:
  application:
    name: spring-cloud-service-provider
  datasource:
    url: jdbc:mysql://localhost:3306/test?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=UTF-8&useSSL=false
    #GMT%2B8代表: 东八区
    username: root
    password:
    driver-class-name: com.mysql.jdbc.Driver
    type: com.alibaba.druid.pool.DruidDataSource
    filters: stat
    maxActive: 20
    initialSize: 1
    maxWait: 60000
    minIdle: 1
    timeBetweenEvictionRunsMillis: 60000
    minEvictableIdleTimeMillis: 300000
    validationQuery: select 'x'
    testWhileIdle: true
    testOnBorrow: false
    testOnReturn: false
    poolPreparedStatements: true
    maxOpenPreparedStatements: 20
#注册中心的配置
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8001/eureka/
server:
  port: 8084
mybatis:
  mapperLocations: classpath:mapper/*.xml
  typeAliasesPackage: com.example.springcloud.service.provider.dao
#日志输出mybatis里面的sql
logging:
  level:
    com.springcloud.muyan.service.dao: debug
2.3、因需要与数据库交互,在resource下创建mapper文件夹,用来存放mapper.xml,并创建名为UserMapper.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.example.springcloud.service.provider.dao.UserMapper">
    <!-- 获取用户表中所有的信息-->
    <select id="getUserList"  resultType="com.example.springcloud.service.provider.pojo.UserPojo" >
        SELECT * FROM `user`
    </select>
    <!-- 新增一条数据 -->
    <insert id="insert" useGeneratedKeys="false" parameterType="com.example.springcloud.service.provider.pojo.UserPojo" >
        INSERT INTO `user` ( `username`, `password`, `age`) VALUES (#{username},#{password},#{age})
    </insert>
</mapper>
2.4、 新增实体类
package com.example.springcloud.service.provider.pojo;

import lombok.Data;
import lombok.ToString;
import java.io.Serializable;

/**
 * @description
 * @author: jjb
 * @create: 2021-01-25 13:30
 **/
@Data
@ToString
public class UserPojo implements Serializable {

    //id
    private Integer id;
    //用户名
    private String username;
    //密码
    private String password;
    //年龄
    private Integer age;

}

2.5、 新建对应UserMapper.xml接口文件
package com.example.springcloud.service.provider.dao;

import com.example.springcloud.service.provider.pojo.UserPojo;
import org.springframework.stereotype.Repository;
import java.util.List;

/**
 * @description
 * @author: jjb
 * @create: 2021-01-25 13:36
 **/
@Repository
public interface UserMapper {
	//获取用户表中所有信息
    List<UserPojo> getUserList();
	//新增一条数据
    int insert(UserPojo userPojo);
}

2.6、 新建service接口及impl实现类
package com.example.springcloud.service.provider.service;

import com.example.springcloud.service.provider.pojo.UserPojo;

import java.util.List;

/**
 * @description
 * @author: jjb
 * @create: 2021-01-25 13:40
 **/
public interface ProviderService {

    List<UserPojo> getUserList();

    void insert(UserPojo userPojo);
}

impl实现类:

package com.example.springcloud.service.provider.service.impl;

import com.example.springcloud.service.provider.dao.UserMapper;
import com.example.springcloud.service.provider.pojo.UserPojo;
import com.example.springcloud.service.provider.service.ProviderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;

/**
 * @description
 * @author: jjb
 * @create: 2021-01-25 13:41
 **/
@Service
public class ProviderServiceImpl implements ProviderService {

    @Autowired
    private UserMapper userMapper;

    @Override
    public List<UserPojo> getUserList() {
        return userMapper.getUser();
    }

    @Override
    @Transactional
    public void insert(UserPojo userPojo) {
         userMapper.insertUser(userPojo);
    }
}

2.7、创建controller
package com.example.springcloud.service.provider.controller;

import com.example.springcloud.service.provider.pojo.UserPojo;
import com.example.springcloud.service.provider.service.ProviderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Random;

/**
 * @description
 * @author: jjb
 * @create: 2021-01-25 13:45
 **/
@RestController
public class ProviderController {

    @Value("${server.port}")
    private String port;

    @Autowired
    private ProviderService providerService;

    @RequestMapping(value = "/getPort",method = RequestMethod.GET)
    public String getName(@RequestParam(value = "name",required = false) String name){
        String result = "请求人:" + name + ",端口是:" + port;
        return result;
    }

    @RequestMapping(value = "/getUserList",method = RequestMethod.GET)
    public List<UserPojo> getUserList(){
        List<UserPojo> list = providerService.getUserList();
        return list;
    }

    @RequestMapping(value = "/insert")
    public String insert(@RequestBody UserPojo userPojo){
        String result = "成功";
        try {
            providerService.insert(userPojo);
        }catch (Exception ex){
            result = "失败";
            ex.printStackTrace();
        }
        return result;
    }
}

2.8、 在启动类上添加注解@EnableEurekaClient、@ComponentScan、@MapperScan注意是EnableEurekaClient不是EnableEurekaServer
package com.example.springcloud.service.provider;

import com.alibaba.druid.pool.DruidDataSource;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;

import javax.sql.DataSource;

@SpringBootApplication
@EnableEurekaClient
@ComponentScan(value = "com.example.springcloud.service.provider.*")
@MapperScan(value = {"classpath:config/*.xml","com.example.springcloud.service.provider.dao"})
public class ProviderApplication {

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

    @Bean
    @ConfigurationProperties(prefix = "spring.datasource")
    public DataSource druidDataSource(){
        DruidDataSource druidDataSource = new DruidDataSource();
        return  druidDataSource;
    }

}

启动服务,查看是否已经将自己注册到注册中心上,http://localhost:8001,注册成功后,访问一下controller查看方法是否正常响应。
3.feign(服务消费者)

feign是一个声明式的伪http客户端,使用非常简单,只需要创建接口并注解,可使用feign注解和JAX-RS注解。支持可插拔的编码器和解码器。feign默认集成了ribbon,并和eureka做了结合,默认实现了负载均衡的效果。

3.1、新建服务消费者springcloud-service-web-feign,详细pom如下
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.example</groupId>
        <artifactId>spring-cloud-parent</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <relativePath>../pom.xml</relativePath>
    </parent>
    <groupId>com.example</groupId>
    <artifactId>springcloud-service-web-feign</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>springcloud-service-web-feign</name>
    <description>feign test</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <!-- Spring Boot-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <!-- Spring Cloud -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
            <version>2.0.0.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
            <version>2.0.0.RELEASE</version>
        </dependency>

        <!-- 解决 thymeleaf 模板引擎一定要执行严格的 html5 格式校验问题 -->
        <dependency>
            <groupId>net.sourceforge.nekohtml</groupId>
            <artifactId>nekohtml</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
            <version>2.0.2.RELEASE</version>
        </dependency>

        <!-- Hystrix 仪表盘 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
            <version>2.0.1.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <mainClass>com.example.springcloud.service.web.feign.SpringcloudServiceWebFeignApplication</mainClass>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

3.2、配置文件中配置Eureka信息,及注册服务名

spring:
  application:
    name: springcloud-service-web-feign
  thymeleaf:
    cache: false
    mode: LEGACYHTML5
    encoding: UTF-8
    servlet:
      content-type: text/html

server:
  port: 10003
#注册中心的配置
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8001/eureka/

# 设置为true表示开启熔断hystrix,设置false表示关闭熔断机制
feign:
  hystrix:
    enabled: true
    command:
      default:
        execution:
          timeout:
            enabled: true
        isolation:
          thread:
            timeoutInMilliseconds: 10000
  client:
    config:
      default:
        connectTimeout: 10000 #10s就超时
        readTimeout: 10000
#请求处理的超时时间
ribbon:
  ReadTimeout: 120000
  #请求连接的超时时间
  ConnectTimeout: 30000

3.3、创建实体类
package com.example.springcloud.service.provider.pojo;

import lombok.Data;
import lombok.ToString;
import java.io.Serializable;

/**
 * @description
 * @author: jjb
 * @create: 2021-01-25 13:30
 **/
@Data
@ToString
public class UserPojo implements Serializable {

    //id
    private Integer id;
    //用户名
    private String username;
    //密码
    private String password;
    //年龄
    private Integer age;

}

3.4、此处只演示如何进行远程服务调用,其他业务逻辑略,调用远程服务的定义接口声明为feign调用服务方式
package com.example.springcloud.service.web.feign.service;

import com.example.springcloud.service.web.feign.config.FallBackUserPojoClient;
import com.example.springcloud.service.web.feign.config.FeignDisableHystrixConfiguration;
import com.example.springcloud.service.web.feign.pojo.UserPojo;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.*;
import java.util.List;

/**
 * @description
 * @author: jjb
 * @create: 2021-01-25 16:01
 **/

@FeignClient(value = "spring-cloud-service-provider",
        fallback = FallBackUserPojoClient.class
        )
public interface FeignService {

    @RequestMapping(value = "/getPort",method = RequestMethod.GET)
    public String getName(@RequestParam(value = "name") String name);

    @RequestMapping(value = "/getUserList",method = RequestMethod.GET)
    public List<UserPojo> getUser();

    @RequestMapping("/insert")
    public String insertUser(@RequestBody UserPojo userPojo);
}

3.5、这里采用@FeignClient,value是需要调用具体哪个服务,我们这里调用自己写的服务提供者springcloud-service-provider,服务名称都在每个项目的yml文件内,上面的pom文件中我们加入了熔断相关的依赖,在服务的消费者调用服务提供者时,服务挂掉了怎么办,页面请求一直会转圈圈直至超时,视业务情况开启或关闭熔断。
可以看到FeignService中加入了fallback=FallBackUserPojoClient.class,这样就告诉系统,如果调用远程服务出现错误导致失败时,执行FallBackUserPojoClient类,当调用任一远程接口失败时,立即给出响应,不需要长时间等待
3.6、因为我们采用Hystrix熔断机制,所以我们需要用服务的降级处理,新建FallBackUserPojoClient类,这个类是给远程接口降级,需要给哪个接口降级就实现哪个接口,这里我们实现FeignService
package com.example.springcloud.service.web.feign.config;

import com.example.springcloud.service.web.feign.pojo.UserPojo;
import com.example.springcloud.service.web.feign.service.FeignService;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;

/**
 * @description
 * @author: jjb
 * @create: 2021-01-25 16:07
 **/
@Component
public class FallBackUserPojoClient implements FeignService {

    @Override
    public String getPort(String name) {
        return "getPort fail timeout!";
    }

    @Override
    public List<UserPojo> getUserList() {
        ArrayList<UserPojo> pojos = new ArrayList<>();
        UserPojo userPojo = new UserPojo();
        userPojo.setUsername("老王");
        pojos.add(userPojo);
        return pojos;
    }

    @Override
    public String insert(UserPojo userPojo) {
        return "insertUser fail timeout!";
    }
}

3.7、对熔断机制我们需要进行监控,pom依赖中已加入仪表盘
package com.example.springcloud.service.web.feign.config;

import com.netflix.hystrix.contrib.metrics.eventstream.HystrixMetricsStreamServlet;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @description
 * @author: jjb
 * @create: 2021-01-25 16:15
 **/
@Configuration
public class HystrixDashboardConfiguration {

    @Bean
    public ServletRegistrationBean getServlet(){
        HystrixMetricsStreamServlet hystrixMetricsStreamServlet = new HystrixMetricsStreamServlet();
        ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(hystrixMetricsStreamServlet);
        servletRegistrationBean.setLoadOnStartup(1);
        servletRegistrationBean.addUrlMappings("/hystrix.stream");
        servletRegistrationBean.setName("HystrixMetricsStreamServlet");
        return servletRegistrationBean;
    }
}

3.8、创建controller
package com.example.springcloud.service.web.feign.controller;

import com.example.springcloud.service.web.feign.pojo.UserPojo;
import com.example.springcloud.service.web.feign.service.FeignService;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;

/**
 * @description
 * @author: jjb
 * @create: 2021-01-25 16:19
 **/
@RestController
public class FeignController {

    @Autowired
    private FeignService feignService;

    /**
     * 获取具体调用哪个微服务,如果后台将provider服务启动两个端口,多次调用,会返回不同的微服务端口,模拟负载均衡
     * @param name
     * @return
     */
    @HystrixCommand
    @RequestMapping(value = "/getPort",method = RequestMethod.GET)
    public String getPort(@RequestParam(value = "name") String name){
        return  feignService.getPort(name);
    }

    /**
     * 从provider服务中获取所有用户信息
     * @return
     */
    @HystrixCommand
    @RequestMapping(value = "/getUserList",method = RequestMethod.GET)
    public List<UserPojo> getUserList(){
        return feignService.getUserList();
    }

    /**
     * 向远处服务发送新增一条用户请求
     * @param name
     * @param password
     * @param age
     * @return
     */
    @RequestMapping(value = "insert",method = RequestMethod.GET)
    public String insert(@RequestParam(value = "name") String name,
                             @RequestParam(value = "password") String password,
                             @RequestParam(value = "age") int age){
        UserPojo userPojo  = new UserPojo();
        userPojo.setUsername(name);
        userPojo.setPassword(password);
        userPojo.setAge(age);
        System.out.println( "客户端===》新增用户的信息为:username=" + userPojo.getUsername() + ",password=" + userPojo.getPassword() + ",age=" + userPojo.getAge() );
        return feignService.insert(userPojo);
    }

}

3.9、修改启动类,告诉spring启动的时候需要开启Hystrix相关服务
package com.example.springcloud.service.web.feign;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;
import org.springframework.cloud.openfeign.EnableFeignClients;

@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
//开启熔断器和降级
/**
 * 10s失败将服务降级,降级时间是60s,60s内不去调用服务方接口直接熔断,
 * 没有特殊场景不推荐开启熔断
 */
@EnableCircuitBreaker
//开启熔断监控
@EnableHystrixDashboard
public class SpringcloudServiceWebFeignApplication {

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

}

模拟集群,我们需要修改服务提供者application.yml文件中的server.port修改为不同的值,再启动一次,启动两个相同而端口不同的服务,接着启动feign调用接口测试调用远程服务,测试一下每次访问是不是返回了不同的端口,实现了访问集群,负载采用的是客户端负载均衡,再调用获取用户信息接口,接口正常继续测试熔断机制,将启用一个提供者服务停掉,在访问是否会被Hystrix熔断。
再来看看熔断监控,访问http:localhost:10003/hystrix,填写title、dashboard,点击Monitor Stream查看具体监控信息,dashboard中填写localhost:10003/hystrix.stream
4.ribbon+RestTemplate(服务消费者)
4.1、新建项目springcloud-service-web-ribbon,pom详情如下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.example</groupId>
        <artifactId>spring-cloud-parent</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <relativePath>../pom.xml</relativePath>
    </parent>
    <groupId>com.example</groupId>
    <artifactId>springcloud-service-web-ribbon</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>springcloud-service-web-ribbon</name>
    <description>web ribbon</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

        <!-- Spring Boot -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <!-- Spring Cloud -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
            <version>2.0.0.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
            <version>2.0.0.RELEASE</version>
        </dependency>

        <!-- 解决 thymeleaf 模板引擎一定要执行严格的 html5 格式校验问题 -->
        <dependency>
            <groupId>net.sourceforge.nekohtml</groupId>
            <artifactId>nekohtml</artifactId>
        </dependency>

        <!--hystrix依赖,主要是用  @HystrixCommand -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
            <version>2.0.2.RELEASE</version>
        </dependency>

        <!-- Hystrix 仪表盘 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
            <version>2.0.1.RELEASE</version>
        </dependency>


    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <mainClass>com.example.springcloud.service.web.ribbon.SpringcloudServiceWebRibbonApplication</mainClass>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

4.2、新增配置
spring:
  application:
    name: springcloud-service-web-ribbon
  thymeleaf:
    cache: false
    mode: LEGACYHTML5
    encoding: utf-8
    servlet:
      content-type: text/html
      
server:
  port: 10002

eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8001/eureka/

4.3、和feign不同的是ribbon需要借助于RestTemplate,只需要使用RestTemplate中最简单的getForEntity发起一个get请求调用服务端接口,可以通过配置@LoadBalanced注解开启客户端负载均衡
package com.example.springcloud.service.web.ribbon.config;

import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

/**
 * @description
 * @author: jjb
 * @create: 2021-01-27 14:04
 **/
@Configuration
public class RestTemplateConfiguration {

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

4.4、新建实体,业务接口
package com.example.springcloud.service.web.ribbon.pojo;

import lombok.Data;
import lombok.ToString;

/**
 * @description
 * @author: jjb
 * @create: 2021-01-27 14:06
 **/
@Data
@ToString
public class UserPojo {

    //id
    private Integer id;
    //用户名
    private String username;
    //密码
    private String password;
    //年龄
    private Integer age;
}

package com.example.springcloud.service.web.ribbon.service;

import com.example.springcloud.service.web.ribbon.pojo.UserPojo;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import java.util.ArrayList;
import java.util.List;

/**
 * @description
 * @author: jjb
 * @create: 2021-01-27 14:09
 **/
@Service
public class RibbonService {

    @Autowired
    private RestTemplate restTemplate;

    @HystrixCommand(fallbackMethod = "failGetPort")
    public String getPort(String name){
        return  restTemplate.getForObject("http://spring-cloud-service-provider/getPort?name="+name,String.class);
    }

    @HystrixCommand(fallbackMethod = "fallGetUserList")
    public List<UserPojo> getUserList(){
        return restTemplate.getForObject("http://spring-cloud-service-provider/getUserList",List.class);
    }

    public List<UserPojo> fallGetUserList(){
        UserPojo userPojo = new UserPojo();
        userPojo.setUsername("熔断了~");
        ArrayList<UserPojo> list = new ArrayList<>();
        list.add(userPojo);
        return list;
    }

    public String failGetPort(String name){
        return "调用远程服务springcloud-service-provider失败,熔断getPort方法,name="+name;
    }

}

注意:和feign一样,ribbon也加入了熔断机制,注解@HystrixCommand(),fallbackMethod是熔断降级后的处理方法
package com.example.springcloud.service.web.ribbon.controller;

import com.example.springcloud.service.web.ribbon.pojo.UserPojo;
import com.example.springcloud.service.web.ribbon.service.RibbonService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

/**
 * @description
 * @author: jjb
 * @create: 2021-01-27 14:25
 **/
@RestController
public class RibbonController {

    @Autowired
    private RibbonService ribbonService;

    @RequestMapping(value = "/getPort",method = RequestMethod.GET)
    public String getPort(@RequestParam("name") String name){
        return ribbonService.getPort(name);
    }

    @RequestMapping(value = "/getUserList",method = RequestMethod.GET)
    public List<UserPojo> getUserList(){
        return ribbonService.getUserList();
    }
}

在启动类上添加注解,完整代码如下:
package com.example.springcloud.service.web.ribbon;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;
import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;

@SpringBootApplication
@EnableDiscoveryClient
@EnableHystrix
@EnableHystrixDashboard
public class SpringcloudServiceWebRibbonApplication {

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

}

启动项目调用ribbon接口查看调用是否正常
5.Zuul
Zuul的主要功能是路由转发和过滤器。路由功能是微服务的一部分,新建项目springcloud-service-zuul
pom文件:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.example</groupId>
        <artifactId>spring-cloud-parent</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <relativePath>../pom.xml</relativePath>
    </parent>

    <groupId>com.example</groupId>
    <artifactId>springcloud-service-zuul</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>springcloud-service-zuul</name>
    <description>zuul</description>

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

    <dependencies>
        <!-- Spring Boot -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!-- Spring Cloud -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
            <version>2.0.0.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
            <version>2.0.1.RELEASE</version>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <mainClass>com.example.springcloud.service.zuul.SpringcloudServiceZuulApplication</mainClass>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

5.1、zuul相当于只是起到过滤器作用,没有过多的代码,先修改配置文件
spring:
  application:
    name: springcloud-service-zuul

server:
  port: 10004
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8001/eureka/

zuul:
  routes:
    feign:
      path: /feign/**
      serviceId: springcloud-service-web-feign
    ribbon:
      path: /ribbon/**
      serviceId: springcloud-service-web-ribbon
这里使用routes,当poth为/feign/** 转发到feign服务, /ribbon/** 转发到ribbon服务,zuul提供了自定义过滤器(ZuulFilter),可以过滤代理请求,提供额外的功能逻辑,例如:鉴权,记录日志等。
定义调用失败之后的处理类:
package com.example.springcloud.service.zuul.fallback;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.cloud.netflix.zuul.filters.route.FallbackProvider;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.stereotype.Component;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;

/**
 * @description
 * @author: jjb
 * @create: 2021-01-27 15:59
 **/
@Component
public class WebFeignFallbackProvider implements FallbackProvider {
    @Override
    public String getRoute() {
        return "springcloud-service-web-feign";
    }

    @Override
    public ClientHttpResponse fallbackResponse(String route, Throwable cause) {
        return new ClientHttpResponse() {
            @Override
            public HttpStatus getStatusCode() throws IOException {
                return HttpStatus.OK;
            }

            @Override
            public int getRawStatusCode() throws IOException {
                return HttpStatus.OK.value();
            }

            @Override
            public String getStatusText() throws IOException {
                return HttpStatus.OK.getReasonPhrase();
            }

            @Override
            public void close() {

            }

            @Override
            public InputStream getBody() throws IOException {
                ObjectMapper objectMapper = new ObjectMapper();
                HashMap<String, Object> map = new HashMap<>();
                map.put("status", 200);
                map.put("message", "网络异常,连接失败!");
                return new ByteArrayInputStream(objectMapper.writeValueAsString(map).getBytes("UTF-8"));
            }

            @Override
            public HttpHeaders getHeaders() {
                HttpHeaders headers = new HttpHeaders();
                headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
                return headers;
            }
        };
    }
}

package com.example.springcloud.service.zuul.fallback;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.cloud.netflix.zuul.filters.route.FallbackProvider;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.stereotype.Component;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;

/**
 * @description
 * @author: jjb
 * @create: 2021-01-27 16:04
 **/
@Component
public class WebRibbonFallbackProvider implements FallbackProvider {
    @Override
    public String getRoute() {
        return "springcloud-service-web-ribbon";
    }

    @Override
    public ClientHttpResponse fallbackResponse(String route, Throwable cause) {
        return new ClientHttpResponse() {
            @Override
            public HttpStatus getStatusCode() throws IOException {
                return HttpStatus.OK;
            }

            @Override
            public int getRawStatusCode() throws IOException {
                return HttpStatus.OK.value();
            }

            @Override
            public String getStatusText() throws IOException {
                return HttpStatus.OK.getReasonPhrase();
            }

            @Override
            public void close() {

            }

            @Override
            public InputStream getBody() throws IOException {
                ObjectMapper objectMapper = new ObjectMapper();
                HashMap<String, Object> hashMap = new HashMap<>();
                hashMap.put("status", 200);
                hashMap.put("message", "网络异常,连接失败!");
                return new ByteArrayInputStream(objectMapper.writeValueAsString(hashMap).getBytes("UTF-8"));
            }

            @Override
            public HttpHeaders getHeaders() {
                HttpHeaders headers = new HttpHeaders();
                headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
                return headers;
            }
        };
    }
}

配置启动类:

package com.example.springcloud.service.zuul;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;

@SpringBootApplication
@EnableEurekaClient
@EnableZuulProxy
public class SpringcloudServiceZuulApplication {

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

}

启动zuul,访问/feign/**,在访问/ribbon/**

代码下载地址:
https://gitee.com/code_depository/spring-cloud-parent


总结

以上就是今天所演示内容,本文仅简单介绍springCloud的使用,如有不足请指正。

最后

以上就是优秀鞋垫为你收集整理的springCloud实践SpringBoot+SpringCloud+Eureka+Feign+Ribbon+Hystrix+Zuul+Mybatis一、SpringCloud是什么?总结的全部内容,希望文章能够帮你解决springCloud实践SpringBoot+SpringCloud+Eureka+Feign+Ribbon+Hystrix+Zuul+Mybatis一、SpringCloud是什么?总结所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(51)

评论列表共有 0 条评论

立即
投稿
返回
顶部