欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

SpringCloud+Eureka+Feign+Ribbon的简化搭建流程,加入熔断,网关和Redis缓存[2]

程序员文章站 2023-09-29 09:22:18
SpringCloud+Eureka+Feign+Ribbon的简化搭建流程,加入熔断,网关和Redis缓存 ......
作者:故事我忘了
个人微信公众号:程序猿的月光宝盒
SpringCloud+Eureka+Feign+Ribbon的简化搭建流程,加入熔断,网关和Redis缓存[2]

前提:本篇是基于

springcloud+eureka+feign+ribbon的简化搭建流程和crud练习[1]

的修改与拓展


1.修改consumercenterfeign.java,把返回值全部设置为string

/**
 * 是consumer调用provider(需要指定provider的名字)
 * 请求的清单列表:规定调用地址、参数、返回值
 * 在正常走通的时候不走centerfeignfallback,当provider down的时候走熔断器,相当于是类的try-catch
 */
@feignclient(name = "provider",fallback = centerfeignfallback.class)
public interface centerfeign {
    @getmapping("/optiondata.do")
    public string optiondata();

    @postmapping("/showempdata.do")
    //feign:不支持对象传参,所以要用@requestbody
    public string showempdata(@requestbody emp emp);

    @postmapping("/add.do")
    public string add(@requestbody emp emp);

    @postmapping("/edit.do")
    public string edit(@requestbody  emp emp);

    @getmapping("/del.do")
    public string del(@requestparam("empno") integer empno);
}

2.在centerfeign.java的同包下创建实现了centerfeign接口的centerfeignfallback.java作为熔断器

@component
public class centerfeignfallback implements centerfeign {
    @override
    public string optiondata() {
        return "provider-optiondata-error";
    }

    @override
    public string showempdata(emp emp) {
        return "provider-showempdata-error";
    }

    @override
    public string add(emp emp) {
        return "provider-add-error";
    }

    @override
    public string edit(emp emp) {
        return "provider-edit-error";
    }

    @override
    public string del(integer empno) {
        return "provider-del-error";
    }
}

3.修改consumercentercontroller.java,返回值全改为string

@restcontroller
public class centercontroller{
    @resource
    private centerfeign centerfeign;

    @getmapping("/optiondata-consumer.do")
    public string optiondata() {
        return centerfeign.optiondata();
    }

    @postmapping("/showempdata-consumer.do")
    public string showempdata(@requestbody emp emp) {
        return centerfeign.showempdata(emp);
    }

    @postmapping("/add-consumer.do")
    public string add(@requestbody emp emp) {
        return centerfeign.add(emp);
    }

    @postmapping("/edit-consumer.do")
    public string edit(@requestbody emp emp) {
        return centerfeign.edit(emp);
    }

    @getmapping("/del-consumer.do")
    public string del(@requestparam("empno") integer empno) {
        return centerfeign.del(empno);
    }
}

4.确认consumer中的配置文件application.properties中有没有开启熔断feign.hystrix.enabled=true,没有的话加上

#端口号
server.port=8764
#应用名
spring.application.name=consumer
#eureka客户端服务url默认区域
eureka.client.serviceurl.defaultzone=http://localhost:8761/eureka/
#开启熔断器
feign.hystrix.enabled=true
#下线名称.ribbon.nf加载平衡规则类名,这里先注释
provider.ribbon.nfloadbalancerruleclassname=com.netflix.loadbalancer.randomrule

5.开启服务测试

访问http://localhost:8761/

发现所有服务已经注册

SpringCloud+Eureka+Feign+Ribbon的简化搭建流程,加入熔断,网关和Redis缓存[2]

正常走provider没有问题

SpringCloud+Eureka+Feign+Ribbon的简化搭建流程,加入熔断,网关和Redis缓存[2]


SpringCloud+Eureka+Feign+Ribbon的简化搭建流程,加入熔断,网关和Redis缓存[2]

SpringCloud+Eureka+Feign+Ribbon的简化搭建流程,加入熔断,网关和Redis缓存[2]

走consumer也没有问题,只是返回的格式是字符串类型,不是json类型,但是没关系,格式还是json的格式,前台该怎么转还能怎么转,不影响

SpringCloud+Eureka+Feign+Ribbon的简化搭建流程,加入熔断,网关和Redis缓存[2]

那怎么走容错?

现在手动停止一个provider

SpringCloud+Eureka+Feign+Ribbon的简化搭建流程,加入熔断,网关和Redis缓存[2]

因为这里我开了负载均衡策略(在consumer中的配置文件中provider.ribbon.nfloadbalancerruleclassname=com.netflix.loadbalancer.randomrule),所以有一定几率触发熔断器,

SpringCloud+Eureka+Feign+Ribbon的简化搭建流程,加入熔断,网关和Redis缓存[2]

这就相当于类之间的try-catch,没有熔断器的话这里百分百是报错误代码.那这里我先把负载均衡关掉,在测试有没有走容错,(猜一下,会走吗?)

SpringCloud+Eureka+Feign+Ribbon的简化搭建流程,加入熔断,网关和Redis缓存[2]

SpringCloud+Eureka+Feign+Ribbon的简化搭建流程,加入熔断,网关和Redis缓存[2]

这里我测了这么多次,都没有走熔断,所以显然不走,为何?

因为没有手动设置负载均衡策略的话,默认走的是轮询.机制,啥是ribbon轮询机制?

简单的说就是有abc三台服务器,正常的情况下走a->b->c,在有一台down了的时候,那台就自动跳过,比如b down了,那么就是a->c

以上,个人理解,若有误请指正,よろしくお願いします~


现在,既然一台服务器工作是没有问题 那我两台provider全部停止呢?

SpringCloud+Eureka+Feign+Ribbon的简化搭建流程,加入熔断,网关和Redis缓存[2]

那答案是肯定的,绝壁走容错~~

SpringCloud+Eureka+Feign+Ribbon的简化搭建流程,加入熔断,网关和Redis缓存[2]

6.测试完没有问题,现在添加网关功能模块

新建模块(spring initializr)zuul-client

SpringCloud+Eureka+Feign+Ribbon的简化搭建流程,加入熔断,网关和Redis缓存[2]

SpringCloud+Eureka+Feign+Ribbon的简化搭建流程,加入熔断,网关和Redis缓存[2]

7.编辑配置文件application.properties

#网关端口
server.port=8765
#应用名
spring.application.name=zuul
#网关路径提供者,后面的**表示:xxx.do
zuul.routes.provider=/pro/**/
#网关路径消费者,后面的**表示:xxx.do
zuul.routes.consumer=/con/**/

8.在启动类上添加注解

//开启网关代理
@enablezuulproxy
//开启eureka客户端
@enableeurekaclient
@springbootapplication
public class zuulclientapplication {

    public static void main(string[] args) {
        springapplication.run(zuulclientapplication.class, args);
    }

}

9.开启服务测试

SpringCloud+Eureka+Feign+Ribbon的简化搭建流程,加入熔断,网关和Redis缓存[2]


测试provider

SpringCloud+Eureka+Feign+Ribbon的简化搭建流程,加入熔断,网关和Redis缓存[2]

测试consumer

SpringCloud+Eureka+Feign+Ribbon的简化搭建流程,加入熔断,网关和Redis缓存[2]

10.网关作用

统一了所有客户端的ip地址和端口号,我们只要给不同层级的应用起别名就ok了(就是这里的SpringCloud+Eureka+Feign+Ribbon的简化搭建流程,加入熔断,网关和Redis缓存[2])

11.加入redis缓存

11.1在provider-one模块的pom文件中加入redis依赖

 <dependency>
            <groupid>org.springframework.boot</groupid>
            <artifactid>spring-boot-starter-data-redis</artifactid>
</dependency>

11.2修改provider-one模块的deptserviceimpl文件,加入@autowired private redistemplate redistemplate;

@service
public class deptserviceimpl implements deptservice {
    @autowired
    private deptmapper deptmapper;
    @autowired
    private redistemplate redistemplate;

    @override
    public map<string, object> optiondata() {
        map<string, object> map=new hashmap<>();
        list<map<string, object>> list = deptmapper.selalldeptdata();
        // 定义redis存储集合的对象
        listoperations<string,map<string,object>> redislist = redistemplate.opsforlist();
        //拼接redis中存储数据对应的key
        string key = "depts";
        //判断redis中是否有key,没有就说明是第一次访问,将数据放入redis
        if(!redistemplate.haskey(key)){
            //直接将数据库查询出来的值放入redis
            system.out.println("provider-one-optiondata的值已经放入redis");
            redislist.leftpushall(key,list);
        }
        map.put("data",list);
        return map;
    }
}

11.3对应的 修改deptservice,返回值变成map

public interface deptservice {
    map<string,object> optiondata();
}

11.4修改centercontroller,把返回值类型改为map

    public map<string, object> optiondata() {
        return deptservice.optiondata();
    }

11.5同样的在provider-two的pom.xml中加入redis依赖

<dependency>
            <groupid>org.springframework.boot</groupid>
            <artifactid>spring-boot-starter-data-redis</artifactid>
</dependency>

11.6修改provider-two模块的deptserviceimpl文件,加入@autowired private redistemplate redistemplate;

@service
public class deptserviceimpl implements deptservice {
    @autowired
    private deptmapper deptmapper;
    @autowired
    private redistemplate redistemplate;

    @override
    public map<string, object> optiondata() {
        map<string, object> map=new hashmap<>();
        list<map<string, object>> list = deptmapper.selalldeptdata();
        // 定义redis存储集合的对象
        listoperations<string,map<string,object>> redislist = redistemplate.opsforlist();
        //拼接redis中存储数据对应的key
        string key = "depts";
        //判断redis中是否有key,没有就说明是第一次访问,将数据放入redis
        if(!redistemplate.haskey(key)){
            //直接将数据库查询出来的值放入redis
            system.out.println("provider-two-optiondata的值已经放入redis");
            redislist.leftpushall(key,list);
        }
        map.put("data",list);
        return map;
    }
}

11.7对应的 修改deptservice,返回值变成map

public interface deptservice {
    map<string,object> optiondata();
}

11.8修改centercontroller,把返回值类型改为map

    public map<string, object> optiondata() {
        return deptservice.optiondata();
    }

11.9更新provider-one模块的配置文件application.properties,加入redis配置

#服务端口号
server.port=8762
#应用名
spring.application.name=provider
#eureka客户端服务url默认区域
eureka.client.serviceurl.defaultzone=http://localhost:8761/eureka/

#数据源驱动类名
spring.datasource.driver-class-name=com.mysql.jdbc.driver
#数据源url
spring.datasource.url=jdbc:mysql:///kh75
#数据源用户名
spring.datasource.username=root
#数据源密码
spring.datasource.password=admin



#后期会写mapper.xml,这里先注释
#mybatis.mapper-locations=classpath:mapper/*.xml

#给实体类起别名,同样这里先注释
#mybatis.type-aliases-package=cn.kgc.vo

#配置redis
spring.redis.port=6379
#redis所在的主机地址
spring.redis.host=xxx.xxx.xxx
spring.redis.database=0

11.10更新provider-two模块的配置文件application.properties,加入redis配置

#服务端口号
server.port=8763
#应用名
spring.application.name=provider
#eureka客户端服务url默认区域
eureka.client.serviceurl.defaultzone=http://localhost:8761/eureka/

#数据源驱动类名
spring.datasource.driver-class-name=com.mysql.jdbc.driver
#数据源url
spring.datasource.url=jdbc:mysql:///kh75
#数据源用户名
spring.datasource.username=root
#数据源密码
spring.datasource.password=admin



#后期会写mapper.xml,这里先注释
#mybatis.mapper-locations=classpath:mapper/*.xml

#给实体类起别名,同样这里先注释
#mybatis.type-aliases-package=cn.kgc.vo
#配置redis
spring.redis.port=6379
#redis所在的主机地址
spring.redis.host=xxx.xxx.xx
spring.redis.database=0

11.11更新consumer的centerfeign,所有返回值都是map

@feignclient(name = "provider",fallback = centerfeignfallback.class)
public interface centerfeign {
    @getmapping("/optiondata.do")
     map<string,object> optiondata();

    @postmapping("/showempdata.do")
    //feign:不支持对象传参,所以要用@requestbody
    map<string,object> showempdata(@requestbody emp emp);

    @postmapping("/add.do")
    map<string,object> add(@requestbody emp emp);

    @postmapping("/edit.do")
    map<string,object> edit(@requestbody  emp emp);

    @getmapping("/del.do")
    map<string,object> del(@requestparam("empno") integer empno);
}

11.12更新centerfeignfallback

@component
public class centerfeignfallback implements centerfeign {
    private map<string, object> map = new hashmap<> ();
    @autowired
    private redistemplate redistemplate;
    @override
    public map<string,object> optiondata() {
         listoperations<string,map<string,object>> redislist = redistemplate.opsforlist();
        map.put("msg","provider-optiondata-error");
        map.put("feign-data",redislist.range("depts",0,-1));
        return map;
    }

    @override
    public map<string,object> showempdata(emp emp) {
         listoperations<string,map<string,object>> redislist = redistemplate.opsforlist();
        map.put("msg","provider-showempdata-error");
        //这里对应的serviceimp里面还没修改成redis,先放着
        map.put("feign-data",redislist.range("emps",0,-1));
        return map;
    }

    @override
    public map<string,object> add(emp emp) {
        map.put("msg","provider-add-error");
        return map;
    }

    @override
    public map<string,object> edit(emp emp) {
        map.put("msg","provider-edit-error");
        return map;
    }

    @override
    public map<string,object> del(integer empno) {
        map.put("msg","provider-del-error");
        return map;
    }
}

11.13再修改consumer中的centercontroller,返回值也全改成map

@restcontroller
public class centercontroller{
    @resource
    private centerfeign centerfeign;

    @getmapping("/optiondata-consumer.do")
    public map<string,object> optiondata() {
        return centerfeign.optiondata();
    }

    @postmapping("/showempdata-consumer.do")
    public map<string,object> showempdata(@requestbody emp emp) {
        return centerfeign.showempdata(emp);
    }

    @postmapping("/add-consumer.do")
    public map<string,object> add(@requestbody emp emp) {
        return centerfeign.add(emp);
    }

    @postmapping("/edit-consumer.do")
    public map<string,object> edit(@requestbody emp emp) {
        return centerfeign.edit(emp);
    }

    @getmapping("/del-consumer.do")
    public map<string,object> del(@requestparam("empno") integer empno) {
        return centerfeign.del(empno);
    }
}

11.14检查consumer的pom文件里是否有加入redis依赖,没有加上...

11.15 打开所有模块进行测试

SpringCloud+Eureka+Feign+Ribbon的简化搭建流程,加入熔断,网关和Redis缓存[2]

SpringCloud+Eureka+Feign+Ribbon的简化搭建流程,加入熔断,网关和Redis缓存[2]

SpringCloud+Eureka+Feign+Ribbon的简化搭建流程,加入熔断,网关和Redis缓存[2]

SpringCloud+Eureka+Feign+Ribbon的简化搭建流程,加入熔断,网关和Redis缓存[2]

SpringCloud+Eureka+Feign+Ribbon的简化搭建流程,加入熔断,网关和Redis缓存[2]

SpringCloud+Eureka+Feign+Ribbon的简化搭建流程,加入熔断,网关和Redis缓存[2]

把提供者断掉,理论上走熔断和redis数据

SpringCloud+Eureka+Feign+Ribbon的简化搭建流程,加入熔断,网关和Redis缓存[2]

SpringCloud+Eureka+Feign+Ribbon的简化搭建流程,加入熔断,网关和Redis缓存[2]

以上....