10.消息总线(bus+rabbitmq)

来源:互联网 发布:网络防御技术 编辑:程序博客网 时间:2024/06/17 12:03

1.消息总线介绍

Spring Cloud Bus 将分布式的节点用轻量的消息代理连接起来。它可以用于广播配置文件的更改或者服务之间的通讯,也可以用于监控。本文要讲述的是用Spring Cloud Bus实现通知微服务架构的配置文件的更改。这里选用rabbitmq作为消息队列中间件,springcloud对常见消息中间件做了很好的整合

利用上一个工程的eureka-server/config-server/config-client集群。其中config-client集群中有两个服务实例。

传统思路当git仓库的配置文件改变时传统的做法是将config-client集群中所有机器停掉重启(重新读取配置文件)

bus+rabbitmq思路:使用消息总线将集群中的实例都串起来,在git仓库文件改变之后,手动向集群中某一台机器上面的服务发送一个http命令,这一台机器会从新读取配置文件,并自动将命令传播到集群中其他服务实例实现整个集群的配置重读。就不用挨个儿去重启服务。

2.erueka-server

不变(见上一个博文)

3.config-server

不变(见上一个博文)

4.config-client

(1)pom.xml

主要是加入后面五个依赖

<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">  <modelVersion>4.0.0</modelVersion>  <groupId>com.tyf</groupId>  <artifactId>config-client</artifactId>  <version>0.0.1-SNAPSHOT</version>  <packaging>jar</packaging>  <name>config-client</name>  <url>http://maven.apache.org</url>  <properties>    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>  </properties>  <!-- 1 -->  <parent>        <groupId>org.springframework.boot</groupId>        <artifactId>spring-boot-starter-parent</artifactId>        <version>1.5.2.RELEASE</version>        <relativePath/> <!-- lookup parent from repository -->   </parent><!-- 2 --><dependencies>        <dependency>            <groupId>org.springframework.cloud</groupId>            <artifactId>spring-cloud-starter-config</artifactId>        </dependency>        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-web</artifactId>        </dependency><dependency>        <groupId>org.springframework.cloud</groupId>        <artifactId>spring-cloud-starter-eureka</artifactId>   </dependency>        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-test</artifactId>            <scope>test</scope>        </dependency>        <!-- rabbitmq+bus后面五个依赖 -->       <dependency>            <groupId>org.springframework.retry</groupId>            <artifactId>spring-retry</artifactId>        </dependency>       <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-aop</artifactId>        </dependency>         <dependency>            <groupId>org.springframework.cloud</groupId>            <artifactId>spring-cloud-starter-bus-amqp</artifactId>        </dependency>        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-actuator</artifactId>        </dependency>    </dependencies><!-- 3 -->    <dependencyManagement>        <dependencies>            <dependency>                <groupId>org.springframework.cloud</groupId>                <artifactId>spring-cloud-dependencies</artifactId>                <version>Dalston.RC1</version>                <type>pom</type>                <scope>import</scope>            </dependency>        </dependencies>    </dependencyManagement><!-- 4 -->    <build>        <plugins>            <plugin>                <groupId>org.springframework.boot</groupId>                <artifactId>spring-boot-maven-plugin</artifactId>            </plugin>        </plugins>    </build><!-- 5 -->    <repositories>        <repository>            <id>spring-milestones</id>            <name>Spring Milestones</name>            <url>https://repo.spring.io/milestone</url>            <snapshots>                <enabled>false</enabled>            </snapshots>        </repository>    </repositories></project>

(2)bootstrap.properties

spring.application.name=config-clientspring.cloud.config.label=masterspring.cloud.config.profile=testeureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka/spring.cloud.config.discovery.enabled=truespring.cloud.config.discovery.serviceId=config-serverserver.port=8995management.security.enabled=falsespring.cloud.bus.trace.enabled=truespring.rabbitmq.host=192.168.88.131spring.rabbitmq.port=5672spring.rabbitmq.username=unamespring.rabbitmq.password=pword


(3)app

package com.tyf.config_client;import org.springframework.beans.factory.annotation.Value;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.cloud.client.discovery.EnableDiscoveryClient;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;@SpringBootApplication@RestController//@EnableDiscoveryClientpublic class App {@Value("${name}")    String name;@Value("${pass}")    String pass;@Value("${url}")    String url;@RequestMapping("/get")    String hello() {System.out.println(name+pass+url);//response给浏览器        return name+pass+url;    }public static void main(String[] args) {    SpringApplication.run(App.class, args);}}

将config-client服务复制两个(port=8990/port=8995)

5.测试

(1)开启rabbitmq服务

访问http://192.168.88.131:15672查看web窗口,我这里通过name/pword登录



(2)post请求

由于需要向config-client发送一个post请求命令他从新读取配置文件,这里写一个工具类用来发送post请求

kage send_post;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.io.PrintWriter;import java.net.URL;import java.net.URLConnection;import java.util.List;import java.util.Map;public class HttpRequest {    /**     * 向指定 URL 发送POST方法的请求     *      * @param url     *            发送请求的 URL     * @param param     *            请求参数,请求参数应该是 name1=value1&name2=value2 的形式。     * @return 所代表远程资源的响应结果     */    public static String sendPost(String url, String param) {        PrintWriter out = null;        BufferedReader in = null;        String result = "";        try {            URL realUrl = new URL(url);            // 打开和URL之间的连接            URLConnection conn = realUrl.openConnection();            // 设置通用的请求属性            conn.setRequestProperty("accept", "*/*");            conn.setRequestProperty("connection", "Keep-Alive");            conn.setRequestProperty("user-agent",                    "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");            // 发送POST请求必须设置如下两行            conn.setDoOutput(true);            conn.setDoInput(true);            // 获取URLConnection对象对应的输出流            out = new PrintWriter(conn.getOutputStream());            // 发送请求参数            out.print(param);            // flush输出流的缓冲            out.flush();            // 定义BufferedReader输入流来读取URL的响应            in = new BufferedReader(                    new InputStreamReader(conn.getInputStream()));            String line;            while ((line = in.readLine()) != null) {                result += line;            }        } catch (Exception e) {            System.out.println("发送 POST 请求出现异常!"+e);            e.printStackTrace();        }        //使用finally块来关闭输出流、输入流        finally{            try{                if(out!=null){                    out.close();                }                if(in!=null){                    in.close();                }            }            catch(IOException ex){                ex.printStackTrace();            }        }        return result;    }            public static void main(String[] args) {         //发送 POST 请求        String sr=HttpRequest.sendPost("http://localhost:8995/bus/refresh", "key=123&v=456");        System.out.println(sr);    }}

按顺序启动 eureka-server/config-server/config-client1/config-client2

启动上面的post工具,查看config-client1/config-client2的控制台输出的log信息

结果如下:


fetching xxxxxxx 日志显示两个config-client都重新抓取了配置文件


(3)访问rabbitmq图形端


最后那个springCloudBus(topic交换器)就是bus自动创建的