diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..6cf8ada --- /dev/null +++ b/Dockerfile @@ -0,0 +1,10 @@ +FROM java:8 +MAINTAINER king <1609724385@qq.com> +VOLUME /tmp +COPY /target/iotgatewayservice.jar iotgatewayservice.jar +COPY --from=hengyunabc/arthas:latest /opt/arthas /opt/arthas +ENV TimeZone=Asia/Shanghai +ENV active=dev +ENV JAVA_OPTS="-Xmx512M -Xms512M" +RUN ln -snf /usr/share/zoneinfo/$TimeZone /etc/localtime && echo $TimeZone > /etc/timezone +ENTRYPOINT java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /iotgatewayservice.jar --spring.profiles.active=$active \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..43f7a2d --- /dev/null +++ b/pom.xml @@ -0,0 +1,234 @@ + + + 4.0.0 + com.telpo + iotgatewayservice + 1.0-SNAPSHOT + data-iot-gateway-server + 数据推送服务 + jar + + UTF-8 + UTF-8 + 1.8 + UTF-8 + 2.2.0.RELEASE + Hoxton.RELEASE + true + + + + org.springframework.boot + spring-boot-starter-parent + 2.2.5.RELEASE + + + + + + org.springframework.boot + spring-boot-devtools + runtime + true + + + + org.projectlombok + lombok + true + + + + + com.telpo + common + 1.1.19 + + + + + org.apache.qpid + qpid-jms-client + 0.47.0 + + + + commons-codec + commons-codec + 1.10 + + + + + com.alibaba.cloud + spring-cloud-starter-alibaba-nacos-discovery + + + + com.alibaba.cloud + spring-cloud-starter-alibaba-nacos-config + + + + + org.springframework.boot + spring-boot-starter-web + + + + + + mysql + mysql-connector-java + runtime + + + + + + com.baomidou + mybatis-plus + 3.3.1 + + + + + org.mybatis.spring.boot + mybatis-spring-boot-autoconfigure + 2.1.2 + + + + + org.mybatis.spring.boot + mybatis-spring-boot-starter + 2.1.2 + + + + + + com.alibaba + druid-spring-boot-starter + 1.1.22 + + + + + org.springframework.boot + spring-boot-starter-test + test + + + org.junit.vintage + junit-vintage-engine + + + + + + org.springframework.boot + spring-boot-configuration-processor + true + + + + + org.apache.commons + commons-lang3 + 3.10 + + + + + org.springframework.boot + spring-boot-starter-aop + + + + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + + + + + org.springframework.boot + spring-boot-starter-data-redis + + + + + org.apache.commons + commons-pool2 + + + + + org.springframework.kafka + spring-kafka + + + + + com.squareup.okhttp3 + okhttp + 4.8.0 + + + + + de.codecentric + spring-boot-admin-starter-client + 2.2.4 + + + + + + + + + + org.springframework.cloud + spring-cloud-dependencies + ${spring-cloud.version} + pom + import + + + + com.alibaba.cloud + spring-cloud-alibaba-dependencies + ${spring-cloud-alibaba.version} + pom + import + + + + + + ${project.artifactId} + + + org.springframework.boot + spring-boot-maven-plugin + + + true + + + + + repackage + + + + + + + + + \ No newline at end of file diff --git a/push_service_run.sh b/push_service_run.sh new file mode 100644 index 0000000..61e3d63 --- /dev/null +++ b/push_service_run.sh @@ -0,0 +1,39 @@ +#!/bin/bash +environment=$1 +version=$2 +echo "环境变量为$environment,版本为$version!" +if [[ $environment == 'pro' ]]; then + echo "开始远程构建容器" + docker stop iot_gateway_service || true + docker rm iot_gateway_service || true + docker rmi -f $(docker images | grep registry.cn-shanghai.aliyuncs.com/telpo_platform/iot_gateway_service | awk '{print $3}') + docker login --username=rzl_wangjx@1111649216405698 --password=telpo.123 registry.cn-shanghai.aliyuncs.com + docker pull registry.cn-shanghai.aliyuncs.com/telpo_platform/iot_gateway_service:$version + docker run -v /home/data/iotgatewayserver/log:/var/log/iotgatewayserver -e active=pro --restart=always -d --network host --name iot_gateway_service registry.cn-shanghai.aliyuncs.com/telpo_platform/iot_gateway_service:$version + #删除产生的None镜像 + docker rmi -f $(docker images | grep none | awk '{print $3}') + docker ps -a +else + if [[ $environment == 'test' ]]; then + #echo "开始远程构建容器" + docker stop iot_gateway_service || true + docker rm iot_gateway_service || true + + docker rmi -f $(docker images | grep 139.224.254.18:5000/iot_gateway_service | awk '{print $3}') + docker pull 139.224.254.18:5000/iot_gateway_service:$version + docker run -v /home/data/iotgatewayserver/log:/var/log/iotgatewayserver -e active=test --restart=always -d --network host --name iot_gateway_service 139.224.254.18:5000/iot_gateway_service:$version + + #删除产生的None镜像 + docker rmi -f $(docker images | grep none | awk '{print $3}') + docker ps -a + else + docker stop iot_gateway_service || true + docker rm iot_gateway_service || true + docker rmi -f $(docker images | grep 139.224.254.18:5000/iot_gateway_service | awk '{print $3}') + docker pull 139.224.254.18:5000/iot_gateway_service:$version + docker run -v /home/data/iotgatewayserver/log:/var/log/iotgatewayserver -e active=dev --restart=always -d --network host --name iot_gateway_service telpo/iot_gateway_service:$version + #删除产生的None镜像 + docker rmi -f $(docker images | grep none | awk '{print $3}') + docker ps -a + fi +fi diff --git a/setup_dev.sh b/setup_dev.sh new file mode 100644 index 0000000..b084149 --- /dev/null +++ b/setup_dev.sh @@ -0,0 +1,26 @@ +#!/bin/bash +mvn clean +mvn package -Dmaven.test.skip=true +#image_version=$(date +%Y%m%d%H%M) +image_version=$version +docker stop iot_gateway_service || true +docker rm iot_gateway_service || true +# 删除镜像 +docker rmi -f $(docker images | grep telpo/iot_gateway_service | awk '{print $3}') + +docker build . -t telpo/push_service:$image_version + +#TODO:推送镜像到私有仓库 +echo '=================开始推送镜像=======================' +docker tag telpo/iot_gateway_service:$image_version 139.224.254.18:5000/iot_gateway_service:$image_version +docker push 139.224.254.18:5000/iot_gateway_service:$image_version +echo '=================推送镜像完成=======================' + +#删除产生的None镜像 +docker rmi -f $(docker images | grep none | awk '{print $3}') +# 查看镜像列表 +docker images +# 启动容器 +docker run -v /home/data/iotgatewayserver/log:/var/log/iotgatewayserver -d -e active=dev --network host --restart=always --name iot_gateway_service telpo/iot_gateway_service:$image_version +# 查看日志 +docker logs push_service diff --git a/setup_pro.sh b/setup_pro.sh new file mode 100644 index 0000000..1eea540 --- /dev/null +++ b/setup_pro.sh @@ -0,0 +1,20 @@ +#!/usr/bin/env bash +mvn clean +mvn package -Dmaven.test.skip=true +image_version=$version +# 删除镜像 +docker rmi -f $( + docker images | grep registry.cn-shanghai.aliyuncs.com/telpo_platform/iot_gateway_service | awk '{print $3}' +) +# 构建telpo/mrp:$image_version镜像 +docker build . -t telpo/iot_gateway_service:$image_version +#TODO:推送镜像到阿里仓库 +echo '=================开始推送镜像=======================' +docker login --username=rzl_wangjx@1111649216405698 --password=telpo.123 registry.cn-shanghai.aliyuncs.com +docker tag telpo/iot_gateway_service:$image_version registry.cn-shanghai.aliyuncs.com/telpo_platform/iot_gateway_service:$image_version +docker push registry.cn-shanghai.aliyuncs.com/telpo_platform/iot_gateway_service:$image_version +echo '=================推送镜像完成=======================' +#删除产生的None镜像 +docker rmi -f $(docker images | grep none | awk '{print $3}') +# 查看镜像列表 +docker images diff --git a/setup_test.sh b/setup_test.sh new file mode 100644 index 0000000..c63b808 --- /dev/null +++ b/setup_test.sh @@ -0,0 +1,26 @@ +#!/bin/bash +mvn clean +mvn package -Dmaven.test.skip=true +#image_version=$(date +%Y%m%d%H%M) +image_version=$version +docker stop iot_gateway_service || true +docker rm iot_gateway_service || true +# 删除镜像 +docker rmi -f $(docker images | grep telpo/iot_gateway_service | awk '{print $3}') + +docker build . -t telpo/iot_gateway_service:$image_version + +#TODO:推送镜像到私有仓库 +echo '=================开始推送镜像=======================' +docker tag telpo/iot_gateway_service:$image_version 139.224.254.18:5000/iot_gateway_service:$image_version +docker push 139.224.254.18:5000/iot_gateway_service:$image_version +echo '=================推送镜像完成=======================' + +#删除产生的None镜像 +docker rmi -f $(docker images | grep none | awk '{print $3}') +# 查看镜像列表 +docker images +# 启动容器 +docker run -v /home/data/iotgatewayserver/log:/var/log/iotgatewayserver -d -e active=test --network host --restart=always --name iot_gateway_service telpo/iot_gateway_service:$image_version +# 查看日志 +docker logs iot_gateway_service diff --git a/src/main/java/com/telpo/iotgateway/IotGatewayApplication.java b/src/main/java/com/telpo/iotgateway/IotGatewayApplication.java new file mode 100644 index 0000000..ef36f9b --- /dev/null +++ b/src/main/java/com/telpo/iotgateway/IotGatewayApplication.java @@ -0,0 +1,37 @@ +package com.telpo.iotgateway; + +import com.telpo.iotgateway.server.IotSubscribe; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.context.properties.ConfigurationPropertiesScan; +import org.springframework.cloud.client.discovery.EnableDiscoveryClient; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.core.env.ConfigurableEnvironment; +import org.springframework.scheduling.annotation.EnableAsync; +import org.springframework.scheduling.annotation.EnableScheduling; + +/** + * @program: DataPushServer + * @description: 推送服务启动程序 + * @author: linwl + * @create: 2020-07-10 18:04 + */ +@SpringBootApplication +@EnableDiscoveryClient +@ConfigurationPropertiesScan +@EnableAsync +@EnableScheduling +@Slf4j +public class IotGatewayApplication { + + public static void main(String[] args) { + ConfigurableApplicationContext applicationContext = SpringApplication.run(IotGatewayApplication.class, args); + + ConfigurableEnvironment environment = applicationContext.getEnvironment(); + IotSubscribe iotSubscribe = new IotSubscribe(environment); + iotSubscribe.start(); + log.info("推送服务启动!"); + } +} diff --git a/src/main/java/com/telpo/iotgateway/config/JacksonConfig.java b/src/main/java/com/telpo/iotgateway/config/JacksonConfig.java new file mode 100644 index 0000000..e690110 --- /dev/null +++ b/src/main/java/com/telpo/iotgateway/config/JacksonConfig.java @@ -0,0 +1,61 @@ +package com.telpo.iotgateway.config; + +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer; +import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer; +import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer; +import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer; +import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; +import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer; +import com.fasterxml.jackson.module.paramnames.ParameterNamesModule; +import models.Constants; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.format.DateTimeFormatter; + +/** + * @program: DataPushServer + * @description: 序列化设置 + * @author: linwl + * @create: 2020-07-11 09:15 + */ +@Configuration +public class JacksonConfig { + + @Bean + public ObjectMapper objectMapper() { + ObjectMapper objectMapper = new ObjectMapper(); + objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); + objectMapper.disable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE); + JavaTimeModule javaTimeModule = new JavaTimeModule(); + javaTimeModule.addSerializer( + LocalDateTime.class, + new LocalDateTimeSerializer( + DateTimeFormatter.ofPattern(Constants.DEFAULT_DATE_TIME_FORMAT))); + javaTimeModule.addSerializer( + LocalDate.class, + new LocalDateSerializer(DateTimeFormatter.ofPattern(Constants.DEFAULT_DATE_FORMAT))); + javaTimeModule.addSerializer( + LocalTime.class, + new LocalTimeSerializer(DateTimeFormatter.ofPattern(Constants.DEFAULT_TIME_FORMAT))); + javaTimeModule.addDeserializer( + LocalDateTime.class, + new LocalDateTimeDeserializer( + DateTimeFormatter.ofPattern(Constants.DEFAULT_DATE_TIME_FORMAT))); + javaTimeModule.addDeserializer( + LocalDate.class, + new LocalDateDeserializer(DateTimeFormatter.ofPattern(Constants.DEFAULT_DATE_FORMAT))); + javaTimeModule.addDeserializer( + LocalTime.class, + new LocalTimeDeserializer(DateTimeFormatter.ofPattern(Constants.DEFAULT_TIME_FORMAT))); + objectMapper.registerModule(javaTimeModule).registerModule(new ParameterNamesModule()); + return objectMapper; + } +} diff --git a/src/main/java/com/telpo/iotgateway/config/SchedulingExecutorConfig.java b/src/main/java/com/telpo/iotgateway/config/SchedulingExecutorConfig.java new file mode 100644 index 0000000..5a757ee --- /dev/null +++ b/src/main/java/com/telpo/iotgateway/config/SchedulingExecutorConfig.java @@ -0,0 +1,40 @@ +package com.telpo.iotgateway.config; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.SchedulingConfigurer; +import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; +import org.springframework.scheduling.config.ScheduledTaskRegistrar; + +/** + * @program: DataPushServer + * @description: 定时任务线程配置 + * @author: linwl + * @create: 2020-07-24 10:53 + */ +@Configuration +public class SchedulingExecutorConfig implements SchedulingConfigurer { + + @Value("${scheduler.pool.size}") + private int pollSize; + + @Value("${scheduler.pool.await-seconds}") + private int awaitSeconds; + + @Override + public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { + ThreadPoolTaskScheduler taskScheduler = taskScheduler(); + taskRegistrar.setTaskScheduler(taskScheduler); + } + + @Bean(destroyMethod = "shutdown", name = "taskScheduler") + public ThreadPoolTaskScheduler taskScheduler() { + ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler(); + scheduler.setPoolSize(pollSize); + scheduler.setThreadNamePrefix("task-"); + scheduler.setAwaitTerminationSeconds(awaitSeconds); + scheduler.setWaitForTasksToCompleteOnShutdown(true); + return scheduler; + } +} diff --git a/src/main/java/com/telpo/iotgateway/dto/BaseDto.java b/src/main/java/com/telpo/iotgateway/dto/BaseDto.java new file mode 100644 index 0000000..f8f3a23 --- /dev/null +++ b/src/main/java/com/telpo/iotgateway/dto/BaseDto.java @@ -0,0 +1,23 @@ +package com.telpo.iotgateway.dto; + +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; + +/** + * @program: DataPushServer + * @description: + * @author: linwl + * @create: 2020-07-22 17:23 + */ +@Setter +@Getter +@ToString +public class BaseDto { + + /** 设备号 */ + private String imei; + + /** 数据时间 */ + private String time; +} diff --git a/src/main/java/com/telpo/iotgateway/exception/GobalExceptionHandler.java b/src/main/java/com/telpo/iotgateway/exception/GobalExceptionHandler.java new file mode 100644 index 0000000..e5bf117 --- /dev/null +++ b/src/main/java/com/telpo/iotgateway/exception/GobalExceptionHandler.java @@ -0,0 +1,30 @@ +package com.telpo.iotgateway.exception; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestControllerAdvice; +import response.ERRORCODE; +import response.Result; + +import java.text.MessageFormat; + +/** + * @program: DataPushServer + * @description: 全局异常拦截 + * @author: linwl + * @create: 2020-07-11 10:29 + */ +@Slf4j +@RestControllerAdvice(basePackages = "com.telpo.datapushserver.controller") +public class GobalExceptionHandler { + @ExceptionHandler(value = Exception.class) + @ResponseBody + public Result exceptionErrorHandler(Exception e) throws Exception { + log.error(MessageFormat.format("推送服务发生异常:{0}!", e.getMessage()), e); + return new Result.Builder() + .setCode(ERRORCODE.SystemErr) + .setMessage(MessageFormat.format("系统发生异常:{0}!", e.getMessage())) + .build(); + } +} diff --git a/src/main/java/com/telpo/iotgateway/listener/IotJmsConnectionListener.java b/src/main/java/com/telpo/iotgateway/listener/IotJmsConnectionListener.java new file mode 100644 index 0000000..57b2f0c --- /dev/null +++ b/src/main/java/com/telpo/iotgateway/listener/IotJmsConnectionListener.java @@ -0,0 +1,66 @@ +package com.telpo.iotgateway.listener; + +import lombok.extern.slf4j.Slf4j; +import org.apache.qpid.jms.JmsConnectionListener; +import org.apache.qpid.jms.message.JmsInboundMessageDispatch; +import org.springframework.stereotype.Component; + +import javax.jms.MessageConsumer; +import javax.jms.MessageProducer; +import javax.jms.Session; +import java.net.URI; +import java.time.LocalDateTime; + +/** + * @program: iotgateway + * @description: IotJms连接侦听 + * @author: linwl + * @create: 2021-02-24 11:22 + **/ +@Slf4j +@Component +public class IotJmsConnectionListener implements JmsConnectionListener { + /** + * 连接成功建立。 + */ + @Override + public void onConnectionEstablished(URI remoteURI) { + log.info("onConnectionEstablished, remoteUri:{0}, time:{1}", remoteURI, LocalDateTime.now()); + } + + /** + * 尝试过最大重试次数之后,最终连接失败。 + */ + @Override + public void onConnectionFailure(Throwable error) { + log.error("onConnectionFailure, {}", error.getMessage()); + } + + /** + * 连接中断。 + */ + @Override + public void onConnectionInterrupted(URI remoteURI) { + log.info("onConnectionInterrupted, remoteUri:{0}, time:{1}", remoteURI, LocalDateTime.now()); + } + + /** + * 连接中断后又自动重连上。 + */ + @Override + public void onConnectionRestored(URI remoteURI) { + log.info("onConnectionRestored, remoteUri:{0}, time:{1}", remoteURI, LocalDateTime.now()); + } + + @Override + public void onInboundMessage(JmsInboundMessageDispatch envelope) {} + + @Override + public void onSessionClosed(Session session, Throwable cause) {} + + @Override + public void onConsumerClosed(MessageConsumer consumer, Throwable cause) {} + + @Override + public void onProducerClosed(MessageProducer producer, Throwable cause) {} +} diff --git a/src/main/java/com/telpo/iotgateway/listener/IotMessageListener.java b/src/main/java/com/telpo/iotgateway/listener/IotMessageListener.java new file mode 100644 index 0000000..763269d --- /dev/null +++ b/src/main/java/com/telpo/iotgateway/listener/IotMessageListener.java @@ -0,0 +1,75 @@ +package com.telpo.iotgateway.listener; + +import com.google.common.base.Stopwatch; +import lombok.extern.slf4j.Slf4j; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import javax.jms.Message; +import javax.jms.MessageListener; +import java.util.concurrent.ExecutorService; + +/** + * @program: iotgateway + * @description: Iot消息侦听 + * @author: linwl + * @create: 2021-02-24 11:39 + **/ +@Slf4j +@Component +public class IotMessageListener implements MessageListener { + + int count = 0; + + private ExecutorService executorService; + public void setExecutorService(ExecutorService executorService) { + this.executorService = executorService; + } + + @Override + public void onMessage(Message message) { + try { + //1.收到消息之后一定要ACK。 + // 推荐做法:创建Session选择Session.AUTO_ACKNOWLEDGE,这里会自动ACK。 + // 其他做法:创建Session选择Session.CLIENT_ACKNOWLEDGE,这里一定要调message.acknowledge()来ACK。 + // message.acknowledge(); + //2.建议异步处理收到的消息,确保onMessage函数里没有耗时逻辑。 + // 如果业务处理耗时过程过长阻塞住线程,可能会影响SDK收到消息后的正常回调。 + executorService.submit(() -> processMessage(message)); + count++; + } catch (Exception e) { + log.error("submit task occurs exception ", e); + } + } + + /** + * 在这里处理您收到消息后的具体业务逻辑。 + */ + private static void processMessage(Message message) { + try { + byte[] body = message.getBody(byte[].class); + String content = new String(body); + String topic = message.getStringProperty("topic"); + String messageId = message.getStringProperty("messageId"); + log.info("receive message" + + ", topic = " + topic + + ", messageId = " + messageId + + ", content = " + content); + } catch (Exception e) { + log.error("processMessage occurs error ", e); + } + } + + @Scheduled(cron = "${scheduler.task.cron}") + public void countMessages() { + //log.info("开始执行定时推送失败的推送记录!"); + // 获取推送失败的记录 + //try { + log.warn("约1分钟处理 {} 个请求",count); + count = 0; + //} catch (Exception e) { + // log.error("执行定时计数发生异常:", e); + //} + } + +} diff --git a/src/main/java/com/telpo/iotgateway/server/IotSubscribe.java b/src/main/java/com/telpo/iotgateway/server/IotSubscribe.java new file mode 100644 index 0000000..be2fb56 --- /dev/null +++ b/src/main/java/com/telpo/iotgateway/server/IotSubscribe.java @@ -0,0 +1,154 @@ +package com.telpo.iotgateway.server; + +import com.telpo.iotgateway.listener.IotJmsConnectionListener; +import com.telpo.iotgateway.listener.IotMessageListener; +import lombok.extern.slf4j.Slf4j; +import org.apache.qpid.jms.JmsConnection; +import org.apache.qpid.jms.JmsConnectionListener; +import org.springframework.core.env.ConfigurableEnvironment; +import org.springframework.stereotype.Component; +import org.apache.commons.codec.binary.Base64; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +import javax.jms.*; + +import javax.crypto.Mac; +import javax.crypto.spec.SecretKeySpec; +import javax.naming.Context; +import javax.naming.InitialContext; +import javax.naming.NamingException; +import java.util.Hashtable; + +/** + * @program: DipperPositionServer + * @description: 北斗定位 + * @author: king + * @create: 2021-01-13 14:01 + */ +@Slf4j +@Component +public class IotSubscribe { + + //参数说明,请参见AMQP客户端接入说明文档。 + private String accessKey; + private String accessSecret; + private String consumerGroupId; + //iotInstanceId:企业版实例请填写实例ID,公共实例请填空字符串""。 + private String iotInstanceId; + private long timeStamp; + //签名方法:支持hmacmd5、hmacsha1和hmacsha256。 + private String signMethod; + private String clientId; + private String iotHost; + private String iotPort; + + // 执行单元线程池 + private final static ExecutorService executorService = new ThreadPoolExecutor( + Runtime.getRuntime().availableProcessors(), + Runtime.getRuntime().availableProcessors() * 2, 60, TimeUnit.SECONDS, + new LinkedBlockingQueue<>(50000)); + // Jms连接侦听 + private static JmsConnectionListener myJmsConnectionListener = new IotJmsConnectionListener(); + // 消息侦听 + private static MessageListener messageListener = new IotMessageListener(); + + public IotSubscribe(ConfigurableEnvironment environment) { + //参数说明,请参见AMQP客户端接入说明文档。 + this.accessKey = environment.getProperty("iot.accessKey"); + this.accessSecret = environment.getProperty("iot.accessSecret"); + this.consumerGroupId = environment.getProperty("iot.consumerGroupId"); + //iotInstanceId:企业版实例请填写实例ID,公共实例请填空字符串""。 + this.iotInstanceId = environment.getProperty("iot.iotInstanceId"); + //签名方法:支持hmacmd5、hmacsha1和hmacsha256。 + this.signMethod = environment.getProperty("iot.signMethod"); + this.clientId = environment.getProperty("iot.clientId"); + this.iotHost = environment.getProperty("iot.iotHost"); + this.iotPort = environment.getProperty("iot.iotPort"); + + timeStamp = System.currentTimeMillis(); + } + + /* + * 同步进程线程 + */ + public void start() { + + try { + //计算签名,password组装方法,请参见AMQP客户端接入说明文档。 + String userInfo = getUserInfo(); + String signContent = "authId=" + accessKey + "×tamp=" + timeStamp;; + String password = doSign(signContent,accessSecret, signMethod); + + //接入域名,请参见AMQP客户端接入说明文档。 + // TODO Change ${YourHost} + String connectionUrl = "failover:(amqps://" + iotHost + ":" + iotPort + + "?amqp.idleTimeout=80000)" + + "?failover.reconnectDelay=30"; + + Hashtable hashtable = new Hashtable<>(); + hashtable.put("connectionfactory.SBCF",connectionUrl); + hashtable.put("queue.QUEUE", "default"); + hashtable.put(Context.INITIAL_CONTEXT_FACTORY, "org.apache.qpid.jms.jndi.JmsInitialContextFactory"); + Context context = new InitialContext(hashtable); + ConnectionFactory cf = (ConnectionFactory)context.lookup("SBCF"); + Destination queue = (Destination)context.lookup("QUEUE"); + + // 创建连接。 + Connection connection = cf.createConnection(userInfo, password); + ((JmsConnection) connection).addConnectionListener(myJmsConnectionListener); + // 创建会话。 + // Session.CLIENT_ACKNOWLEDGE: 收到消息后,需要手动调用message.acknowledge()。 + // Session.AUTO_ACKNOWLEDGE: SDK自动ACK(推荐)。 + Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); + connection.start(); + + // 创建Receiver连接。消费消息 + MessageConsumer consumer = session.createConsumer(queue); + + // 设置消息侦听 + ((IotMessageListener)messageListener).setExecutorService(this.executorService); + consumer.setMessageListener(messageListener); + + } catch (IllegalArgumentException e) { + log.error("IllegalArgumentException:{}", e.getMessage()); + } catch (NamingException e) { + log.error("NamingException:{}", e.getMessage()); + } catch (JMSException e) { + log.error("JMSException:{}", e.getMessage()); + } catch (Exception e) { + log.error("Exception:{}", e.getMessage()); + } + } + + /* + * userInfo组装 + */ + private String getUserInfo() { + //userInfo组装 + String userInfo = clientId + "|authMode=aksign" + + ",signMethod=" + signMethod + + ",timestamp=" + timeStamp + + ",authId=" + accessKey + + ",iotInstanceId=" + iotInstanceId + + ",consumerGroupId=" + consumerGroupId + + "|"; + //计算签名,password组装方法,请参见AMQP客户端接入说明文档。 + return userInfo; + } + + /** + * 计算签名,password组装方法,请参见AMQP客户端接入说明文档。 + */ + private static String doSign(String toSignString, String secret, String signMethod) throws Exception { + SecretKeySpec signingKey = new SecretKeySpec(secret.getBytes(), signMethod); + Mac mac = Mac.getInstance(signMethod); + mac.init(signingKey); + byte[] rawHmac = mac.doFinal(toSignString.getBytes()); + return Base64.encodeBase64String(rawHmac); + } + +} diff --git a/src/main/resources/bootstrap-dev.yaml b/src/main/resources/bootstrap-dev.yaml new file mode 100644 index 0000000..70a8c52 --- /dev/null +++ b/src/main/resources/bootstrap-dev.yaml @@ -0,0 +1,10 @@ +spring: + main: + allow-bean-definition-overriding: true + application: + name: push-service + cloud: + nacos: + config: + server-addr: 172.16.192.26:8848 + file-extension: yaml \ No newline at end of file diff --git a/src/main/resources/bootstrap-pro.yaml b/src/main/resources/bootstrap-pro.yaml new file mode 100644 index 0000000..23fb7a8 --- /dev/null +++ b/src/main/resources/bootstrap-pro.yaml @@ -0,0 +1,10 @@ +spring: + main: + allow-bean-definition-overriding: true + application: + name: push-service + cloud: + nacos: + config: + server-addr: 172.19.42.38:8848 + file-extension: yaml \ No newline at end of file diff --git a/src/main/resources/bootstrap-test.yaml b/src/main/resources/bootstrap-test.yaml new file mode 100644 index 0000000..568cfc8 --- /dev/null +++ b/src/main/resources/bootstrap-test.yaml @@ -0,0 +1,48 @@ +spring: + main: + allow-bean-definition-overriding: true + application: + name: push-service + cloud: + nacos: + config: + server-addr: 172.19.42.44:8848 + file-extension: yaml + jackson: + time-zone: GMT+8 + date-format: yyyy-MM-dd HH:mm:ss + aop: + auto: true + proxy-target-class: true + devtools: + restart: + enabled: true + freemarker: + cache: false + +async: + pool: + corePoolSize: 4 + maxPoolSize: 8 + queueCapacity: 5000 + +scheduler: + pool: + size: 1 + #等待任务完成退出最大秒数 + await-seconds: 6 + task: + cron: "0 */1 * * * *" + +iot: + accessKey: LTAI4FdXhwy1evoHXingMaiZ + accessSecret: CGmGpzta6ro8Bta4RLiQD18EF8m6Bm + consumerGroupId: eQVdFouKAYajil208F7F000100 + iotInstanceId: iot-cn-nif1vosz501 + RegionId: cn-shanghai + ProductKey: a18mXM6Cvx8 + //签名方法:支持hmacmd5、hmacsha1和hmacsha256。 + signMethod: hmacmd5 + clientId: gateway + iotHost: contoso.com + iotPort: 5671 \ No newline at end of file diff --git a/src/main/resources/bootstrap.yaml b/src/main/resources/bootstrap.yaml new file mode 100644 index 0000000..70a8c52 --- /dev/null +++ b/src/main/resources/bootstrap.yaml @@ -0,0 +1,10 @@ +spring: + main: + allow-bean-definition-overriding: true + application: + name: push-service + cloud: + nacos: + config: + server-addr: 172.16.192.26:8848 + file-extension: yaml \ No newline at end of file diff --git a/src/main/resources/log/logback-spring.xml b/src/main/resources/log/logback-spring.xml new file mode 100644 index 0000000..1de6973 --- /dev/null +++ b/src/main/resources/log/logback-spring.xml @@ -0,0 +1,197 @@ + + + + + + + + + + + + + + + + + + + + + + + + + debug + + + ${CONSOLE_LOG_PATTERN} + + UTF-8 + + + + + + + + + + ${log.path}/log_debug.log + + + %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n + UTF-8 + + + + + ${log.path}/debug/log-debug-%d{yyyy-MM-dd}.%i.log + + 100MB + + + 7 + + + + debug + ACCEPT + DENY + + + + + + + ${log.path}/log_info.log + + + %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n + UTF-8 + + + + + ${log.path}/info/log-info-%d{yyyy-MM-dd}.%i.log + + 100MB + + + 7 + + + + info + ACCEPT + DENY + + + + + + + ${log.path}/log_warn.log + + + %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n + UTF-8 + + + + ${log.path}/warn/log-warn-%d{yyyy-MM-dd}.%i.log + + 100MB + + + 7 + + + + warn + ACCEPT + DENY + + + + + + + + ${log.path}/log_error.log + + + %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n + UTF-8 + + + + ${log.path}/error/log-error-%d{yyyy-MM-dd}.%i.log + + 100MB + + + 15 + + + + ERROR + ACCEPT + DENY + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file