springcloud bus实现动态刷新

1.什么是Bus

  • https://spring.io/projects/spring-cloud-bus

  • springcloudbus使用轻量级消息代理将分布式系统的节点连接起来。然后,可以使用它来广播状态更改(例如配置更改)或其他管理指令。AMQP和Kafka broker实现包含在项目中。或者,在类路径上找到的任何springcloudstream绑定器都可以作为传输使用。

  • 通俗定义: bus称之为springcloud中消息总线,主要用来在微服务系统中实现远端配置更新时通过广播形式通知所有客户端刷新配置信息,避免手动重启服务的工作

2.实现配置刷新原理

 

3.搭建RabbitMQ服务

4.实现自动配置刷新

1.在所有项目中引入bus依赖(这里采用的是刷新config服务端的做法)

<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-bus-amqp</artifactId>
        </dependency>

2.配置统一配置中心连接到mq

spring.rabbitmq.host=192.168.31.1#连接主机

spring.rabbitmq.port=5672 #连接mq端口

spring.rabbitmq.username=guest #连接mq用户名

spring.rabbitmq.password=guest #连接mq密码

注意:这里的几个属性如果是默认的值,例如本机或者是用户名密码都没有改的话,其实也可以直接用默认值不用填写。

3.客户配置中

同样先加入配置

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-bus-amqp</artifactId>
        </dependency>

配置rabbitmq配置

spring.rabbitmq.host=192.168.31.1#连接主机

spring.rabbitmq.port=5672 #连接mq端口

spring.rabbitmq.username=guest #连接mq用户名

spring.rabbitmq.password=guest #连接mq密码

 

4.启动统一配置中心服务

  • 正常启动

 

5.启动客户端服务

  •  

在configclient项目中添加,记得先引入bus依赖

 

6.修改远程配置后在配置中心服务通过执行post接口刷新配置

当修改远程配置之后不进行刷新配置,那么访问得还是原来得数据,必须进行post接口刷新配置

首先再configserver7878得配置文件中添加

management.endpoints.web.exposure.include=*

r然后重启再进行刷新

此时是通过配置server来进行得刷新,配置server连接得所有节点都得到了刷新,

可以看到在配置文件中修改之后得数据了

7.通过上述配置就实现了配置统一刷新

5.指定服务刷新配置

1.说明

  • 默认情况下使用curl -X POST http://localhost:7878/actuator/bus-refresh这种方式刷新配置是全部广播形式,也就是所有的微服务都能接收到刷新配置通知,但有时我们修改的仅仅是某个服务的配置,这个时候对于其他服务的通知是多余的,因此就需要指定服务进行通知

2.指定服务刷新配置实现

 

5.集成webhook实现自动刷新

1.配置webhooks

  • 添加webhooks
  • 在webhooks中添加刷新配置接口

使用natapp来进行内网穿透,直接看官网教程就可以了

https://natapp.cn/

 

使用natapp作为公网地址之后会出现400错误

2.解决400错误问题

  • 在配置中心服务端加入过滤器进行解决(springcloud中一个坑)
package com.jsl.springcloud.filter;
import org.springframework.stereotype.Component;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;

@Component
public class UrlFilter  implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest httpServletRequest = (HttpServletRequest)request;
        String url = new String(httpServletRequest.getRequestURI());
        //只过滤/actuator/bus-refresh请求
        if (!url.endsWith("/bus-refresh")) {
            chain.doFilter(request, response);
            return;
        }
        //获取原始的body
        String body = readAsChars(httpServletRequest);
        //使用HttpServletRequest包装原始请求达到修改post请求中body内容的目的
        CustometRequestWrapper requestWrapper = new CustometRequestWrapper(httpServletRequest);
        chain.doFilter(requestWrapper, response);
    }

    @Override
    public void destroy() {
    }
    private class CustometRequestWrapper extends HttpServletRequestWrapper {
        public CustometRequestWrapper(HttpServletRequest request) {
            super(request);
        }
        @Override
        public ServletInputStream getInputStream() throws IOException {
            byte[] bytes = new byte[0];
            ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
            return new ServletInputStream() {
                @Override
                public boolean isFinished() {
                    return byteArrayInputStream.read() == -1 ? true:false;
                }
                @Override
                public boolean isReady() {
                    return false;
                }

                @Override
                public void setReadListener(ReadListener readListener) {

                }

                @Override
                public int read() throws IOException {
                    return byteArrayInputStream.read();
                }
            };
        }
    }

    public static String readAsChars(HttpServletRequest request)
    {
        BufferedReader br = null;
        StringBuilder sb = new StringBuilder("");
        try
        {
            br = request.getReader();
            String str;
            while ((str = br.readLine()) != null)
            {
                sb.append(str);
            }
            br.close();
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
        finally
        {
            if (null != br)
            {
                try
                {
                    br.close();
                }
                catch (IOException e)
                {
                    e.printStackTrace();
                }
            }
        }
        return sb.toString();
    }
}

6.进行服务的定点刷新

例如有一个微服务loud-provider-hystrix-payment采用集群部署,此时有8001,8002两个开放的端口。其实我们想通过定点更新8001的信息这可以通过定点刷新的。

同上修改好了yml文件后,用postman运行post请求http://{config相关IP地址}:3344/actuator/bus-refresh/cloud-provider-hystrix-payment:8001即可对某一个点进行刷新。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值