前言:笔者曾经有18年的硬件研发经验,从(1)51单片机到(2)FPGA到(3)嵌入式ARM(ARM9到CORTEX A9)全都研发设计过,产品从(1)B超的整机研发到(2)智能家居系统到(3)无线电监测机到(4)平板电脑研发到(5)路灯智能控制到(5)工业电脑均有涉及,从(1)普通的电子技术工程师到(2)副总工程师到(3)副总经理到(4)事业部总经理。。。目前已经步入不惑之年的我对于物联网技术的热衷,决定从硬件开始全面转到物联技术框架之一的spring cloud技术,把我的整个学习经历和大家一起分享,也期待在之后有更多机会和大家一起合作,探讨。
先给大家分享一件事情:昨天我去参加了《区块链3.0的技术论坛》,听到所谓“国家千人计划”的教授在宣读他的所谓的落地项目,我听到都晕了,整个过程在说他的技术论文怎么的好,项目怎么的牛,但就是听不懂在讲什么,项目根本就听不到任何对大家有意义的事情,我一直在想这些所谓的“千人计划”专家都是所谓的大学这样教授,那样博导。。。。国家怎么弄出个千人计划就给这些所谓的学者,真正落地项目还不是你我这些做实事的企业家在做,我一直觉得这些所谓的教授只能停留在学术研究可以,带几个研究生可以,但真正的研发出让国人都真正能用起来的产品根本就不行。我强烈呼吁所谓的“千人计划”一定是要有真正做出实际落地项目,而且是真正盈利给国家带来真正效益的那些人拥有。好了,以上是废话,请略过!!!这些言论纯个人立场,请网友勿喷!
今天是:2018年4月27日 研究主题:消息驱动的rabbitmq
一、使用消息驱动(消息代理)的目的
1、消息代理主要用于接收和转发消息,就相当于邮局,邮局只用将消息生产者看做寄件人,将消息消费者看做收件人。我们将一封信间放到邮局的邮箱中,邮递员最终就会吧邮件送到收件人那里,邮局是不关心邮件的内容(当然是合法的内容哈),他们只用关心收件人的地址、联系方式及寄件人的联系方式(万一寄不出去),因此我们就说这个邮局是消息代理。这就是spring cloud的stream框架,使用了该框架后,消息的生产者和消费者可以更加专注于各自的业务,而不用关心邮件投递的过程。
2、RabbitMQ是一个轻量级的消息代理中间件,它支持多种消息通信协议,由于其最大特别是具有高可用的特性,因此被广泛采用。而我们应用最多的是高级消息队列协议(AMQP),它定义了“消息客户端”与“消息代理中间件”之间的通信协议。对于生产者和消费者来说都属于客户端,它们月服务器之间通过AMQP协议进行通信,因此客户端可以使用不同的编程语言实现。
上面框图告诉我们,生成者会将消息投递给“消息代理(RabbitMQ服务器)”,它们之间会建立消息通道,消息由交换器先进性处理,交换器会选择把消息交给哪一个队列,最后消息队列将消息发给消费者。
二、安装RabbitMQ服务器,我们使用3.6.11版本(基于Windows),另外由于RabbitMQ服务器使用的是Erlang语言,因此还需要安装Erlang语言。
所需安装软件有:1、otp_win64_20.0.exe;
2、rabbitmq-server-3.6.11.exe
依次安装(默认路径哈),完成后,打开RabbitMQ的控制台,在路径:C:\Program Files\RabbitMQ Server\rabbitmq_server-3.6.11\sbin下面,我们进入该路径后输入:rabbitmq-plugins enable rabbitmq_management开启插件管理,
输入RabbitMQ的服务口端:15672,打开网址:http://localhost:15672/,并输入用户名:guest;密码:guest。都是默认的:
三、基于spring cloud的消息微服务
1、更改项目,将上节的文件名分别做如下更改:
“cjb-zuul-eureka”更改为“cjb-rabbitmq-eureka”作为注册中心
“cjb-zuul-server”更改为“cjb-rabbitmq-server”作为服务提供者
“cjb-zuul-client”更改为“cjb-rabbitmq-client”作为服务调用者
2、下面是总体框图:
3、cjb-rabbitmq-eureka注册中心跑起来
4、更改“cjb-rabbitmq-server”作为服务提供者内容:
首先,更改“pom.xml”依赖,增加
其次,增加一个接口主要用于新建一个订阅的通道,这个和硬件物联通信协议MQTT有些类似,我们新建一个 类“CjbSendService”,用@output注解进行修饰,使用该注解创建“cjbInput”的消息通道。
package com.example.demo; import org.springframework.cloud.stream.annotation.Output; import org.springframework.messaging.SubscribableChannel; public interface CjbSendService { @Output("cjbInput") SubscribableChannel cjbSendOrder(); }
第三,在主类“CjbApplication”中增加@EnableBinding注解,表示让spring容器开启绑定的功能,需要绑定 到“CjbSendService.class”中,这样就可以让spring容器在启动时,会自动绑定CjbSendService接口中定义的 通道。
package com.example.demo; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; import org.springframework.cloud.stream.annotation.EnableBinding; import java.util.Scanner; @SpringBootApplication @EnableEurekaClient @EnableBinding(CjbSendService.class) public class CjbApplication { public static void main(String[] args) { // 读取控制台输入作为端口参数 Scanner scan = new Scanner(System.in); String port = scan.nextLine(); // 设置启动的服务器端口 new SpringApplicationBuilder(CjbApplication.class).properties( "server.port=" + port).run(args); } }
第四,在控制器“cjbcontroller.class”中增加路径接口“/cjbsend”,往 rabbitmq代理服务器中发送消息
@RequestMapping(value = "/cjbsend", method = RequestMethod.GET) public String CjbSendMessage(){ //创建消息 Message message = MessageBuilder.withPayload("Cjb Rabbitmq is ok!".getBytes()).build(); //发送消息 cjbSendService.cjbSendOrder().send(message); return "You is success!"; }
第五,还有一个别忘了需要在配置中增加rabbitmq代理服务器的配置
spring: application: name: cjb-rabbitmq-server eureka: rabbitmq: host: localhost port: 5672 username: guest password: guest instance: hostname: localhost client: serviceUrl: defaultZone: http://localhost:8888/eureka/
以上已经在服务提供者准备完毕,已经可以向rabbitmq发送消息了,启动服务后,输入网址:http://localhost:8088/cjbsend,出现如下信息,表示已经向代理服务器发送成功消息了:
同时我们可以进入rabbitmq的代理服务器可以看到已经有一个消息订阅,不过下图含有发送和接收一起的消息,因为我已经把之后的接收部分做完了,所以会和接收部分的图重复,请各位注意,以下图的“cjbInput”就是我的消息发送通道:
5、更改“cjb-rabbitmq-client”作为服务调用者:
首先,更改“pom.xml”依赖,增加
其次,增加一个接收消息通道的类“CjbReceiveService”,一定记住主题一定要一样“cjbInput”
package com.example.demo; import org.springframework.cloud.stream.annotation.Input; import org.springframework.messaging.SubscribableChannel; public interface CjbReceiveService { @Input("cjbInput") SubscribableChannel cjbInput(); }
第三,在启动类“CjbClient”中增加@EnableBinding注解,表示让spring容器开启绑定的功能,需要绑定 到“CjbReceiveService.class”中,这样就可以让spring容器在启动时,会自动绑定CjbReceiveService接口中定义 的通道。同时还需要使用@StreamListener注解进行修饰,声明了订阅cjbInput通道的消息内容;启动该主类
package com.example.demo; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.web.servlet.ServletComponentScan; import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; import org.springframework.cloud.client.loadbalancer.LoadBalanced; import org.springframework.cloud.netflix.feign.EnableFeignClients; import org.springframework.cloud.stream.annotation.EnableBinding; import org.springframework.cloud.stream.annotation.StreamListener; import org.springframework.context.annotation.Bean; import org.springframework.web.client.RestTemplate; @SpringBootApplication @EnableDiscoveryClient @EnableCircuitBreaker @ServletComponentScan @EnableFeignClients @EnableBinding(CjbReceiveService.class) public class CjbClient { @LoadBalanced @Bean public RestTemplate getRestTemplate(){ return new RestTemplate(); } public static void main(String[] args) { SpringApplication.run(CjbClient.class, args); } @StreamListener("cjbInput") public void cjbreceive(byte[] msg){ System.out.println("你接收到的消息是"+ new String(msg)); } }
第四,刷新一下网址:http://localhost:8088/cjbsend也就是相当于向rabbitmq代理服务器再发送一次消息,这样就会在cjb-rabbitmq-client的消息控制台中出现我们通过rabbitmq代理服务器转发过来的消息是:“Cjb Rabbitmq is ok!”
第五, 同时我们可以进入rabbitmq的代理服务器可以看到已经有一个消息订阅,请各位注意,以下图的“cjbInput”就 是我的消息接收通道:
四、如果需要完整代码的朋友,可以加入作者QQ群:智物联的spring cloud,入群说明:spring cloud代码需求