一峰说:SpringCloud的基础了解和使用

以下是本人学习的观点,如果有错或者说得不全面,记得告诉我哟

微服务

指的是微服务的大小,是一个点,针对具体解决某一个问题对应服务的一个服务应用,在idea中可以理解为一个独立的小模块,一个模块就做一件事情。这一个个小模块都可以称为微服务。

微服务架构

微服务架构相当于管理微服务的一种规范,使用各种注解和配置让服务之间能够相互协调,相互配合,为用户提供服务。

SpringCloud

基于SpringBoot提供了一套微服务解决方案,包括服务注册与发现,配置中心,全链路监控,服务网关,负载均衡,熔断器等组件。同时是分布式微服务架构下的一站式解决方案,是各个微服务架构落地技术的集合体,俗称微服务全家桶。

版本问题是SpringCloud最烦的一个东西,我这里是学习,能运行就可以了,没有采用最新的。望谅解。

SpringCloud的各组件使用

1.在idea上新建(maven项目)一个module,把统一的包先导入,再在这个module新建其他组件。

 <!--打包方法 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>
    </properties>

    <dependencyManagement>
        <dependencies>
<!--         springcloud的依赖   -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Hoxton.SR1</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
<!--            springBoot-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>2.3.3.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
<!--            数据库-->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>5.1.8</version>
            </dependency>
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid</artifactId>
                <version>1.1.12</version>
            </dependency>
<!--            SpringBoot启动器-->
            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
                <version>2.1.0</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.apache.httpcomponents</groupId>
                <artifactId>httpclient</artifactId>
                <version>4.5</version>
            </dependency>
        </dependencies>
    </dependencyManagement>

2.我在这里自定义了一个api子模块,用来存放对象信息供给提供者和消费者共享
在这里插入图片描述

import java.io.Serializable;


public class Dept implements Serializable {//Dept实体类,orm 类表关系映射

    private Long deptno;//主键
    private String dname;
    //这个数据是存在哪个数据库的字段~微服务,一个服务对应一个数据量,同一个信息可能存在不同的数据库
    private String db_source;

    public Dept(String dname) {
        this.dname = dname;
    }

    public Dept() {
    }

    public Long getDeptno() {
        return deptno;
    }

    public void setDeptno(Long deptno) {
        this.deptno = deptno;
    }

    public String getDname() {
        return dname;
    }

    public void setDname(String dname) {
        this.dname = dname;
    }

    public String getDb_source() {
        return db_source;
    }

    public void setDb_source(String db_source) {
        this.db_source = db_source;
    }

    @Override
    public String toString() {
        return "Dept{" +
                "deptno=" + deptno +
                ", dname='" + dname + '\'' +
                ", db_source='" + db_source + '\'' +
                '}';
    }
}

Rest服务提供者

Rest风格的增删查改服务。
新建一个名为springcloud-provider-dept-8001的子目录
有些包导入了并不是这里的内容,因为组件是统一相互协调合作的,后面也会加回来,所以我也不删掉了,下面的依赖同理。

<dependencies>
        <!--        hystrix-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
            <version>2.2.5.RELEASE</version>
        </dependency>
<!--        EUREKA-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
            <version>2.2.5.RELEASE</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-actuator -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
            <version>2.3.3.RELEASE</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/com.google.code.gson/gson -->
        <dependency>
            <groupId>com.google.code.gson</groupId>
            <artifactId>gson</artifactId>
            <version>2.8.6</version>
        </dependency>
        <!--我们需要拿到实体类,所以要配置api module-->
        <dependency>
            <groupId>com.fever</groupId>
            <artifactId>springcloud-api</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-core</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
        </dependency>
<!--        test-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-test</artifactId>
            <version>2.3.3.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>2.3.3.RELEASE</version>
        </dependency>
<!--        jetty-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jetty</artifactId>
            <version>2.3.3.RELEASE</version>
        </dependency>

    </dependencies>

1.建数据库,直接建3个吧,后面会尝试多个数据库一起使用
在这里插入图片描述
在这里插入图片描述

2.编写dao数据库层,再配置mybatis,把数据搞到手
在这里插入图片描述
先配置application.yml,在里面配置mybatis,采用了druid数据源:

server:
  port: 8001

#mybatis配置
mybatis:
  type-aliases-package: com.fever.springcloud.pojo
  config-location:  classpath:mybatis/mybatis-config.xml
  mapper-locations: classpath:mybatis/mapper/*.xml

spring:
  application:
    name: springcloud-provider-dept
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource #数据源
    driver-class-name: org.gjt.mm.mysql.Driver
    url: jdbc:mysql://localhost:3306/springcloud1?useUnicode=true&characterEncoding=utf-8
    username: root
    password: 1234

在resources下新建mybatis配置文件:
mybatis-config.xml:配置mybatis

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">

<configuration>
    <settings>
        <setting name="cacheEnabled" value="true"/>
    </settings>
</configuration>

DeptMapper.xml:数据库操作语句配置

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.fever.springcloud.dao.DeptDao">

    <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>

编写dao层:
DeptDao接口:数据库接口,会自动调用mybatis操作同时提供给service业务层调用

import com.fever.springcloud.pojo.Dept;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;
import java.util.List;

@Mapper
@Repository
public interface DeptDao {

    public boolean addDept(Dept dept);
    public Dept queryById(Long id);
    public List<Dept> queryAll();
}

写完dao层就是写service层
DeptService接口:编写业务逻辑,调用dao层的接口进行数据操作,controller层与之直接交互,就是控制层调用service业务层的接口进行展示数据。

import com.fever.springcloud.pojo.Dept;

import java.util.List;

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

DeptServiceImpl:接口的具体操作

import com.fever.springcloud.dao.DeptDao;
import com.fever.springcloud.pojo.Dept;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;

@Service
public class DeptServiceImpl implements DeptService{

    @Autowired
    private DeptDao deptDao;

    @Override
    public boolean addDept(Dept dept) {
        return deptDao.addDept(dept);
    }

    @Override
    public Dept queryById(Long id) {
        return deptDao.queryById(id);
    }

    @Override
    public List<Dept> queryAll() {
        return deptDao.queryAll();
    }
}

接着就是controller控制层的编写
DeptController:调用业务层接口和页面直接打交道,Rest风格也在这里的url体现

import com.fever.springcloud.pojo.Dept;
import com.fever.springcloud.service.DeptService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController
public class DeptController {

    @Autowired
    private DeptService deptService;

    //获取一些配置的信息,得到具体的微服务!
    @Autowired
    private DiscoveryClient client;

    @PostMapping("/dept/add")
    public boolean addDept(Dept dept){

        return deptService.addDept(dept);
    }

    @GetMapping("/dept/get/{id}")
    public Dept get(@PathVariable("id") Long id){
        Dept dept = deptService.queryById(id);
        if (dept==null){
            throw new RuntimeException("id=>"+id+",不存在该用户,或者信息无法找到~");
        }
        return dept;

    }

    @GetMapping("/dept/list")
    public List<Dept> queryAll(){
        return deptService.queryAll();
    }

   
}

编写启动类DeptProvider_8001

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

Rest服务消费者

消费者就是我们使用这些服务的用户

目录
在这里插入图片描述
pom.xml

<dependencies>
        <!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.16</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-autoconfigure -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-autoconfigure</artifactId>
            <version>2.3.3.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>com.fever</groupId>
            <artifactId>springcloud-api</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>2.1.4.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <version>2.1.4.RELEASE</version>
        </dependency>
    </dependencies>

application.yml

server:
  port: 81

DeptConsumerController:消费者控制类

@RestController
public class DeptConsumerController {

    //理解:消费者,不应该有service层
    //RestTemplate....供我们直接调用!注册到spring中
    //(url,实体:Map,Class<T> responseType)

    @Autowired
    private RestTemplate restTemplate;//提供多种便捷访问远程http服务的方法,简单的Restful服务模板


    private static final String REST_URL_PREFIX ="http://localhost:8001";
   

    @RequestMapping("/consumer/dept/add")
    public boolean add(Dept dept){
        return restTemplate.postForObject(REST_URL_PREFIX+"/dept/add",dept,Boolean.class);
    }

    @RequestMapping("/consumer/dept/get/{id}")
    public Dept get(@PathVariable("id") Long id){
        return restTemplate.getForObject(REST_URL_PREFIX+"/dept/get/"+id,Dept.class);
    }

    @RequestMapping("/consumer/dept/list")
    public List<Dept> list(){
        return restTemplate.getForObject(REST_URL_PREFIX+"/dept/list",List.class);
    }
}

DeptConsumer_81:启动类

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

Eureka服务注册与发现

把服务注册,并且启动发现,让用户可以使用这些服务,同时可以进行其他组件功能对这些服务进行管理和调配。访问:www.eureka7001.com:7001.
目录
在这里插入图片描述

pom.xml

 <dependencies>
        <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-eureka-server -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
            <version>2.2.5.RELEASE</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.google.code.gson/gson -->
        <dependency>
            <groupId>com.google.code.gson</groupId>
            <artifactId>gson</artifactId>
            <version>2.8.6</version>
        </dependency>
    </dependencies>

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:
      #监控页面
      #单机:http://${eureka.instance.hostname}:${server.port}/eureka/
      #集群(关联):
      defaultZone: http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/


EurekaServer_7001:启动类

@SpringBootApplication
@EnableEurekaServer//服务端的启动类
public class EurekaServer_7001 {
    public static void main(String[] args) {
        SpringApplication.run(EurekaServer_7001.class,args);
    }
}

在服务提供者springcloud-provider-dept-8001导入包

<!--        EUREKA-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
            <version>2.2.5.RELEASE</version>
        </dependency>

在服务提供者springcloud-provider-dept-8001的application.yml添加

#EUREKA的配置,服务注册到哪里
eureka:
  client:
    service-url:  #监控页面
      defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
  instance:
    instance-id: springcloud-provider-dept8001 #修改eureka上的默认描述信息!

在服务提供者springcloud-provider-dept-8001的DeptController添加

//注册进来的微服务~获取一些消息~
    @GetMapping("/dept/discovery")
    public Object discovery(){
        //获取微服务列表的清单
        List<String> services=client.getServices();
        System.out.println("discovery=>services:"+services);

        //得到一个具体的的为服务信息,通过具体的微服务id,applicationName:
        List<ServiceInstance> instances=client.getInstances("SPRINGCLOUD-PROVIDER-DEPT");

        for (ServiceInstance instance : instances) {
            System.out.println(
              instance.getHost()+"\t"+
              instance.getPort()+"\t"+
              instance.getUri()+"\t"+
              instance.getServiceId()
            );
        }
        return this.client;
    }

在服务提供者springcloud-provider-dept-8001的DeptProvider_8001添加

@EnableEurekaClient //在服务启动后自动注册到Eureka中
@EnableDiscoveryClient//服务发现~

在服务消费者springcloud-consumer-dept-80的pom.xml添加

<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
            <version>2.2.5.RELEASE</version>
        </dependency>

在服务消费者springcloud-consumer-dept-80的application.yml添加

#Eureka配置
eureka:
  client:
    register-with-eureka: false
    service-url:
        defaultZone: http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/,http://eureka7001.com:7001/eureka/

在服务消费者springcloud-consumer-dept-80的DeptConsumer_81添加

@EnableEurekaClient

Ribbon负载均衡

让服务之间能平衡工作,不会全都挤在一个服务中,导致效率不佳。
在服务消费者springcloud-consumer-dept-80的pom.xml添加

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

在服务消费者springcloud-consumer-dept-80的FeverRandomRule添加自定义负载均衡

import com.netflix.client.config.IClientConfig;
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 FeverRandomRule extends AbstractLoadBalancerRule {

    //每个服务,访问5次,换下一个服务(3个)

    //total=0,默认=0,如果=5,我们指向下一个服务节点
    //index=0,默认0,如果total=5,index+1.

    private int total=0;    //被调用的次数
    private int currentIndex = 0;//当前是谁在提供服务~

    public FeverRandomRule() {
    }

    @SuppressWarnings({"RCN_REDUNDANT_NULLCHECK_OF_NULL_VALUE"})
    public Server choose(ILoadBalancer lb, Object key) {
        if (lb == null) {
            return null;
        } else {
            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;
                }

                int index = this.chooseRandomInt(serverCount);//生成区间随机数
                server = (Server)upList.get(index);//从活着的服务中,随机获取一个

                //-=============================================

                if(total<5){
                    server = upList.get(currentIndex);
                    total++;
                }else{
                    total = 0;
                    currentIndex++;
                    if(currentIndex>=upList.size()){
                        currentIndex=0;
                    }
                    server = upList.get(currentIndex);//从活着的服务中,获取指定的服务来进行操作
                }


                //-==============================================



                if (server == null) {
                    Thread.yield();
                } else {
                    if (server.isAlive()) {
                        return server;
                    }

                    server = null;
                    Thread.yield();
                }
            }

            return server;
        }
    }

    protected int chooseRandomInt(int serverCount) {
        return ThreadLocalRandom.current().nextInt(serverCount);
    }

    public Server choose(Object key) {
        return this.choose(this.getLoadBalancer(), key);
    }

    public void initWithNiwsConfig(IClientConfig clientConfig) {
    }
}

在服务消费者springcloud-consumer-dept-80的feverRule添加

import com.netflix.loadbalancer.IRule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class feverRule {

    @Bean
    public IRule myRule(){
        return new FeverRandomRule();//默认是轮询,现在我们定义为~FeverRandomRule
    }
}

在服务消费者springcloud-consumer-dept-80的ConfigBean添加

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;

@Configuration//spring applicationContext.xml
public class ConfigBean {

    //配置负载均衡实现RestTemplate
    //IRule
    //RoundRobinRule 轮询
    //RandomRule 随机
    //AvailabilityFilteringRule: 会先过滤掉,跳闸,访问故障的服务~对剩下的进行轮询!
    //RetryRule : 会先按照轮询获取服务~如果服务获取失败,则会在指定的时间内进行,重试。
    @Bean
    @LoadBalanced//Ribbon
    public RestTemplate getRestTemplate(){
        return new RestTemplate();
    }
    
}

在服务消费者springcloud-consumer-dept-80的DeptConsumerController添加

//Ribbon,我们这里的地址,应该是一个变量,通过服务名来访问
//private static final String REST_URL_PREFIX ="http://localhost:8001";
  private static final String REST_URL_PREFIX ="http://SPRINGCLOUD-PROVIDER-DEPT";

在服务消费者springcloud-consumer-dept-80的DeptConsumer_81添加

//在微服务启动的时候就能去加载我们自定义Ribbon类
@RibbonClient(name = "SPRINGCLOUD-PROVIDER-DEPT",configuration = feverRule.class)

Feign使用接口方式调用服务

这里新建一个消费者来使用feign,防止混淆前面的
创建springcloud-consumer-dept-feign
在这里插入图片描述

在服务消费者springcloud-consumer-dept-feign的pom.xml添加

<dependencies>

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

        <!--        Ribbon-->
        <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-netflix-ribbon -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
            <version>2.2.5.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
            <version>2.2.5.RELEASE</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.16</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-autoconfigure -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-autoconfigure</artifactId>
            <version>2.3.3.RELEASE</version>
        </dependency>
        
        <dependency>
            <groupId>com.fever</groupId>
            <artifactId>springcloud-api</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>2.1.4.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <version>2.1.4.RELEASE</version>
        </dependency>
    </dependencies>

在服务消费者springcloud-consumer-dept-feign的application.yml添加

#  开启降级feign.hystrix
feign:
  hystrix:
    enabled: true

在服务消费者springcloud-consumer-dept-feign的DeptConsumerController添加

@RestController
public class DeptConsumerController {
    @Autowired
    private DeptClientService service=null;

    @RequestMapping("/consumer/dept/add")
    public boolean add(Dept dept){

        return this.service.addDept(dept);
    }

    @RequestMapping("/consumer/dept/get/{id}")
    public Dept get(@PathVariable("id") Long id){
        return this.service.queryById(id);
    }

    @RequestMapping("/consumer/dept/list")
    public List<Dept> list(){

        return this.service.queryAll();
    }

在服务消费者springcloud-consumer-dept-feign的FeignDeptConsumer_81添加

//Ribbon 和 Eureka 整合以后,客户端可以直接调用,不用关心IP地址
@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients(basePackages = {"com.fever.springcloud"})
public class FeignDeptConsumer_81 {

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

}

Hystrix熔断器

这里新建一个提供者来使用Hystrix,防止混淆前面的
springcloud-provider-dept-hystrix-8001
在这里插入图片描述

在服务提供者springcloud-provider-dept-hystrix-8001的pom.xml添加

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

在服务提供者springcloud-provider-dept-hystrix-8001的DeptController添加

import com.fever.springcloud.pojo.Dept;
import com.fever.springcloud.service.DeptService;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

//提供Restful服务!
@RestController
public class DeptController {

    @Autowired
    private DeptService deptService;

    @HystrixCommand(fallbackMethod = "hystrixGet")
    @GetMapping("/dept/get/{id}")
    public Dept get(@PathVariable("id") Long id){
        Dept dept = deptService.queryById(id);

        if (dept==null){
            throw new RuntimeException("id=>"+id+",不存在该用户,或者信息无法找到~");
        }
        return dept;
    }

    //备选方法
    public Dept hystrixGet(@PathVariable("id") Long id){
        Dept dept=new Dept();
        dept.setDeptno(id);
        dept.setDb_source("no this database in MySQL");
        dept.setDname("id=>"+id+"没有对应的信息,null--@Hystrix");
        return dept;
    }
}

在服务提供者springcloud-provider-dept-hystrix-8001的DeptProviderHystrix_8001添加

import com.netflix.hystrix.contrib.metrics.eventstream.HystrixMetricsStreamServlet;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.context.annotation.Bean;

@SpringBootApplication
@EnableEurekaClient //在服务启动后自动注册到Eureka中
@EnableDiscoveryClient//服务发现~
@EnableCircuitBreaker//添加对熔断的支持
public class DeptProviderHystrix_8001 {
    public static void main(String[] args){
        SpringApplication.run(DeptProviderHystrix_8001.class,args);
    }


    //增加一个Servlet
    @Bean
    public ServletRegistrationBean hystrixMetricsStreamServlet(){
        ServletRegistrationBean registrationBean = new ServletRegistrationBean(new HystrixMetricsStreamServlet());
        registrationBean.addUrlMappings("/actuator/hystrix.stream");
        return registrationBean;
    }
}

Zuul路由网关

控制服务路由,重新声明服务id,作用是不暴露服务id和路径
在这里插入图片描述
application.yml

server:
  port: 9501

spring:
  application:
    name: springcloud-zuul

eureka:
  client:
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
  instance:
    instance-id: zuul9527.com
    prefer-ip-address: true

#info配置
info:
  app.name: fever-springcloud
  company.name: blog.feverstudy.com
zuul:
  routes:
    mydept.serviceId: springcloud-provider-dept
    mydept.path: /mydept/**
  ignored-services: "*" #不能再使用这个路径访问了,ignored:忽略
  prefix: /fever #设置公共的前缀

ZuulApplication_9527

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

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

Config:使用Git环境搭建

1.首先搭建git仓库
https://blog.csdn.net/weixin_43906969/article/details/113788314?spm=1001.2014.3001.5502
然后把以下配置文件上传上码云项目里,以便接下来访问
在这里插入图片描述
** application.yml**

spring:
  profiles:
    active: dev

---
spring:
  profiles: dev
  application:
    name: springcloud-config-dev
    
---
spring:
  profiles: test
  application:
    name: springcloud-config-test

config-client.yml

spring:
  profiles:
    active: dev

---
server:
  port: 8201

#spring的配置
spring:
  profiles: dev
  application:
    name: springcloud-provider-dept

#EUREKA的配置,服务注册到哪里
eureka:
  client:
    service-url:  #监控页面
      defaultZone: http://eureka7001.com:7001/eureka/

---
server:
  port: 8202

#spring的配置
spring:
  profiles: test
  application:
    name: springcloud-provider-dept

#EUREKA的配置,服务注册到哪里
eureka:
  client:
    service-url:  #监控页面
      defaultZone: http://eureka7001.com:7001/eureka/

config-dept.yml

spring:
  profiles:
    active: dev
    
---

server:
  port: 8001

#mybatis配置
mybatis:
  type-aliases-package: com.fever.springcloud.pojo
  config-location:  classpath:mybatis/mybatis-config.xml
  mapper-locations: classpath:mybatis/mapper/*.xml

spring:
  profiles: dev
  application:
    name: springcloud-config-dept
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource #数据源
    driver-class-name: org.gjt.mm.mysql.Driver
    url: jdbc:mysql://localhost:3306/springcloud1?useUnicode=true&characterEncoding=utf-8
    username: root
    password: 1234


#EUREKA的配置,服务注册到哪里
eureka:
  client:
    service-url:  #监控页面
      defaultZone: http://eureka7001.com:7001/eureka/
  instance:
    instance-id: springcloud-provider-dept8001 #修改eureka上的默认描述信息!

#info配置
info:
  app.name: fever-springcloud
  company.name: blog.feverstudy.com
  
---


server:
  port: 8001

#mybatis配置
mybatis:
  type-aliases-package: com.fever.springcloud.pojo
  config-location:  classpath:mybatis/mybatis-config.xml
  mapper-locations: classpath:mybatis/mapper/*.xml

spring:
  profiles: test
  application:
    name: springcloud-config-dept
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource #数据源
    driver-class-name: org.gjt.mm.mysql.Driver
    url: jdbc:mysql://localhost:3306/springcloud3?useUnicode=true&characterEncoding=utf-8
    username: root
    password: 1234


#EUREKA的配置,服务注册到哪里
eureka:
  client:
    service-url:  #监控页面
      defaultZone: http://eureka7001.com:7001/eureka/
  instance:
    instance-id: springcloud-provider-dept8001 #修改eureka上的默认描述信息!

#info配置
info:
  app.name: fever-springcloud
  company.name: blog.feverstudy.com

config-eureka.yml

spring:
  profiles:
    active: dev

---
server:
  port: 7001
  
#spring的配置
spring:
  profiles: dev
  application:
    name: springcloud-config-eureka

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

---

server:
  port: 7001
  
#spring的配置
spring:
  profiles: test
  application:
    name: springcloud-config-eureka

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

自定义了一个api子模块,用来存放对象信息供给提供者和消费者共享
在这里插入图片描述

import java.io.Serializable;


public class Dept implements Serializable {//Dept实体类,orm 类表关系映射

    private Long deptno;//主键
    private String dname;
    //这个数据是存在哪个数据库的字段~微服务,一个服务对应一个数据量,同一个信息可能存在不同的数据库
    private String db_source;

    public Dept(String dname) {
        this.dname = dname;
    }

    public Dept() {
    }

    public Long getDeptno() {
        return deptno;
    }

    public void setDeptno(Long deptno) {
        this.deptno = deptno;
    }

    public String getDname() {
        return dname;
    }

    public void setDname(String dname) {
        this.dname = dname;
    }

    public String getDb_source() {
        return db_source;
    }

    public void setDb_source(String db_source) {
        this.db_source = db_source;
    }

    @Override
    public String toString() {
        return "Dept{" +
                "deptno=" + deptno +
                ", dname='" + dname + '\'' +
                ", db_source='" + db_source + '\'' +
                '}';
    }
}

idea项目连接git仓库:用来连接git,获取配置文件
在这里插入图片描述
springcloud-config-server-3344的pom.xml:

 <dependencies>
<!--        config-->
        <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-config-server -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-config-server</artifactId>
            <version>2.1.1.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>2.3.3.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
            <version>2.3.3.RELEASE</version>
        </dependency>
    </dependencies>

springcloud-config-server-3344的application.yml:

server:
  port: 3344

spring:
  application:
    name: springcloud-config-server
  #连接远程仓库
  cloud:
    config:
      server:
        git:
          uri: https://gitee.com/fever888/springcloud-config.git #https,不是git

springcloud-config-server-3344的Config_Server_3344:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.config.server.EnableConfigServer;

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

服务提供者springcloud-config-dept-8001
目录
在这里插入图片描述
服务提供者springcloud-config-dept-8001的pom.xml

<dependencies>
        <!--        config-->
        <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-config-server -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-config</artifactId>
            <version>2.1.1.RELEASE</version>
        </dependency>
        <!--        hystrix-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
            <version>2.2.5.RELEASE</version>
        </dependency>
        <!--        EUREKA-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
            <version>2.2.5.RELEASE</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-actuator -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
            <version>2.3.3.RELEASE</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/com.google.code.gson/gson -->
        <dependency>
            <groupId>com.google.code.gson</groupId>
            <artifactId>gson</artifactId>
            <version>2.8.6</version>
        </dependency>
        <!--我们需要拿到实体类,所以要配置api module-->
        <dependency>
            <groupId>com.fever</groupId>
            <artifactId>springcloud-api</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-core</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
        </dependency>
        <!--        test-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-test</artifactId>
            <version>2.3.3.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>2.3.3.RELEASE</version>
        </dependency>
        <!--        jetty-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jetty</artifactId>
            <version>2.3.3.RELEASE</version>
        </dependency>

    </dependencies>

服务提供者springcloud-config-dept-8001的application.yml

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

服务提供者springcloud-config-dept-8001的bootstrap.yml

spring:
  cloud:
    config:
      name:  config-dept
      label: master
      profile: test
      uri: http://localhost:3344

服务提供者springcloud-config-dept-8001的DeptDao

@Mapper
@Repository
public interface DeptDao {

    public boolean addDept(Dept dept);
    public Dept queryById(Long id);
    public List<Dept> queryAll();
}

服务提供者springcloud-config-dept-8001的mybatis-config.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">

<configuration>
    <settings>
        <setting name="cacheEnabled" value="true"/>
    </settings>
</configuration>

服务提供者springcloud-config-dept-8001的DeptMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.fever.springcloud.dao.DeptDao">

    <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>

服务提供者springcloud-config-dept-8001的DeptService

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

服务提供者springcloud-config-dept-8001的DeptServiceImpl

@Service
public class DeptServiceImpl implements DeptService{

    @Autowired
    private DeptDao deptDao;

    @Override
    public boolean addDept(Dept dept) {
        return deptDao.addDept(dept);
    }

    @Override
    public Dept queryById(Long id) {
        return deptDao.queryById(id);
    }

    @Override
    public List<Dept> queryAll() {
        return deptDao.queryAll();
    }
}

服务提供者springcloud-config-dept-8001的DeptController

import com.fever.springcloud.pojo.Dept;
import com.fever.springcloud.service.DeptService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController
public class DeptController {

    @Autowired
    private DeptService deptService;

    //获取一些配置的信息,得到具体的微服务!
    @Autowired
    private DiscoveryClient client;

    @PostMapping("/dept/add")
    public boolean addDept(Dept dept){

        return deptService.addDept(dept);
    }

    @GetMapping("/dept/get/{id}")
    public Dept get(@PathVariable("id") Long id){
        Dept dept = deptService.queryById(id);
        if (dept==null){
            throw new RuntimeException("id=>"+id+",不存在该用户,或者信息无法找到~");
        }
        return dept;

    }

    @GetMapping("/dept/list")
    public List<Dept> queryAll(){
        return deptService.queryAll();
    }

    //注册进来的微服务~获取一些消息~
    @GetMapping("/dept/discovery")
    public Object discovery(){
        //获取微服务列表的清单
        List<String> services=client.getServices();
        System.out.println("discovery=>services:"+services);

        //得到一个具体的的为服务信息,通过具体的微服务id,applicationName:
        List<ServiceInstance> instances=client.getInstances("SPRINGCLOUD-PROVIDER-DEPT");

        for (ServiceInstance instance : instances) {
            System.out.println(
              instance.getHost()+"\t"+
              instance.getPort()+"\t"+
              instance.getUri()+"\t"+
              instance.getServiceId()
            );
        }
        return this.client;
    }
}

服务提供者springcloud-config-dept-8001的DeptProvider_8001

@SpringBootApplication
@EnableEurekaClient //在服务启动后自动注册到Eureka中
@EnableDiscoveryClient//服务发现~
public class DeptProvider_8001 {
    public static void main(String[] args){
        SpringApplication.run(DeptProvider_8001.class,args);
    }
    
}

注册与发现服务springcloud-config-eureka-7001
在这里插入图片描述
注册与发现服务springcloud-config-eureka-7001的pom.xml

<dependencies>
        <!--        config-->
        <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-config-server -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-config</artifactId>
            <version>2.1.1.RELEASE</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-eureka-server -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
            <version>2.2.5.RELEASE</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.google.code.gson/gson -->
        <dependency>
            <groupId>com.google.code.gson</groupId>
            <artifactId>gson</artifactId>
            <version>2.8.6</version>
        </dependency>

    </dependencies>

注册与发现服务springcloud-config-eureka-7001的application.yml

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

注册与发现服务springcloud-config-eureka-7001的bootstrap.yml

spring:
  cloud:
    config:
      name:  config-eureka
      label: master
      profile: dev
      uri: http://localhost:3344

注册与发现服务springcloud-config-eureka-7001的EurekaServer_7001

@SpringBootApplication
@EnableEurekaServer//服务端的启动类
public class EurekaServer_7001 {

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

服务消费者springcloud-config-client-3355
在这里插入图片描述
服务消费者springcloud-config-client-3355的pom.xml

 <dependencies>
        <!--        config-->
        <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-config-server -->
        <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>
            <version>2.3.3.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
            <version>2.3.3.RELEASE</version>
        </dependency>
    </dependencies>

服务消费者springcloud-config-client-3355的application.yml

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

服务消费者springcloud-config-client-3355的bootstrap.yml

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

服务消费者springcloud-config-client-3355的ConfigClientController

import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class ConfigClientController {

    @Value("${spring.application.name}")
    private String applicationName;

    @Value("${eureka.client.service-url.defaultZone}")
    private String eurekaServer;

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

    @RequestMapping("/config")
    public String getConfig(){
        return "applicationName:"+applicationName+
                "<br/>"+"eurekaServer:"+eurekaServer+
                "<br/>"+"port:"+port;
    }
}

服务消费者springcloud-config-client-3355的ConfigClient_3355

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

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

然后全部config打开就可以直接访问消费者或者提供者服务了

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一峰说

坚持价值输出

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值