Commit 9561e952a382f1214e386c9009e5f7eea9e78802
1 parent
874b37ef
添加使用多线程消息处理sip消息
Showing
7 changed files
with
119 additions
and
58 deletions
src/main/java/com/genersoft/iot/vmp/VManageBootstrap.java
| @@ -6,6 +6,7 @@ import org.springframework.boot.SpringApplication; | @@ -6,6 +6,7 @@ import org.springframework.boot.SpringApplication; | ||
| 6 | import org.springframework.boot.autoconfigure.SpringBootApplication; | 6 | import org.springframework.boot.autoconfigure.SpringBootApplication; |
| 7 | import org.springframework.boot.web.servlet.ServletComponentScan; | 7 | import org.springframework.boot.web.servlet.ServletComponentScan; |
| 8 | import org.springframework.context.ConfigurableApplicationContext; | 8 | import org.springframework.context.ConfigurableApplicationContext; |
| 9 | +import org.springframework.scheduling.annotation.EnableAsync; | ||
| 9 | import org.springframework.scheduling.annotation.EnableScheduling; | 10 | import org.springframework.scheduling.annotation.EnableScheduling; |
| 10 | import springfox.documentation.oas.annotations.EnableOpenApi; | 11 | import springfox.documentation.oas.annotations.EnableOpenApi; |
| 11 | 12 |
src/main/java/com/genersoft/iot/vmp/conf/ThreadPoolTaskConfig.java
0 → 100644
| 1 | +package com.genersoft.iot.vmp.conf; | ||
| 2 | + | ||
| 3 | +import org.springframework.context.annotation.Bean; | ||
| 4 | +import org.springframework.context.annotation.Configuration; | ||
| 5 | +import org.springframework.scheduling.annotation.EnableAsync; | ||
| 6 | +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; | ||
| 7 | + | ||
| 8 | +import java.util.concurrent.ThreadPoolExecutor; | ||
| 9 | + | ||
| 10 | +@Configuration | ||
| 11 | +@EnableAsync | ||
| 12 | +public class ThreadPoolTaskConfig { | ||
| 13 | + | ||
| 14 | + /** | ||
| 15 | + * 默认情况下,在创建了线程池后,线程池中的线程数为0,当有任务来之后,就会创建一个线程去执行任务, | ||
| 16 | + * 当线程池中的线程数目达到corePoolSize后,就会把到达的任务放到缓存队列当中; | ||
| 17 | + * 当队列满了,就继续创建线程,当线程数量大于等于maxPoolSize后,开始使用拒绝策略拒绝 | ||
| 18 | + */ | ||
| 19 | + | ||
| 20 | + /** | ||
| 21 | + * 核心线程数(默认线程数) | ||
| 22 | + */ | ||
| 23 | + private static final int corePoolSize = 5; | ||
| 24 | + /** | ||
| 25 | + * 最大线程数 | ||
| 26 | + */ | ||
| 27 | + private static final int maxPoolSize = 30; | ||
| 28 | + /** | ||
| 29 | + * 允许线程空闲时间(单位:默认为秒) | ||
| 30 | + */ | ||
| 31 | + private static final int keepAliveTime = 30; | ||
| 32 | + /** | ||
| 33 | + * 缓冲队列大小 | ||
| 34 | + */ | ||
| 35 | + private static final int queueCapacity = 10000; | ||
| 36 | + /** | ||
| 37 | + * 线程池名前缀 | ||
| 38 | + */ | ||
| 39 | + private static final String threadNamePrefix = "hdl-uhi-service-"; | ||
| 40 | + | ||
| 41 | + @Bean("taskExecutor") // bean的名称,默认为首字母小写的方法名 | ||
| 42 | + public ThreadPoolTaskExecutor taskExecutor() { | ||
| 43 | + ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); | ||
| 44 | + executor.setCorePoolSize(corePoolSize); | ||
| 45 | + executor.setMaxPoolSize(maxPoolSize); | ||
| 46 | + executor.setQueueCapacity(queueCapacity); | ||
| 47 | + executor.setKeepAliveSeconds(keepAliveTime); | ||
| 48 | + executor.setThreadNamePrefix(threadNamePrefix); | ||
| 49 | + | ||
| 50 | + // 线程池对拒绝任务的处理策略 | ||
| 51 | + // CallerRunsPolicy:由调用线程(提交任务的线程)处理该任务 | ||
| 52 | + executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); | ||
| 53 | + // 初始化 | ||
| 54 | + executor.initialize(); | ||
| 55 | + return executor; | ||
| 56 | + } | ||
| 57 | +} |
src/main/java/com/genersoft/iot/vmp/gb28181/SipLayer.java
| @@ -2,6 +2,7 @@ package com.genersoft.iot.vmp.gb28181; | @@ -2,6 +2,7 @@ package com.genersoft.iot.vmp.gb28181; | ||
| 2 | 2 | ||
| 3 | import com.genersoft.iot.vmp.conf.SipConfig; | 3 | import com.genersoft.iot.vmp.conf.SipConfig; |
| 4 | import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; | 4 | import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; |
| 5 | +import com.genersoft.iot.vmp.gb28181.transmit.ISIPProcessorObserver; | ||
| 5 | import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver; | 6 | import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver; |
| 6 | import gov.nist.javax.sip.SipProviderImpl; | 7 | import gov.nist.javax.sip.SipProviderImpl; |
| 7 | import gov.nist.javax.sip.SipStackImpl; | 8 | import gov.nist.javax.sip.SipStackImpl; |
| @@ -28,28 +29,12 @@ public class SipLayer{ | @@ -28,28 +29,12 @@ public class SipLayer{ | ||
| 28 | private SipConfig sipConfig; | 29 | private SipConfig sipConfig; |
| 29 | 30 | ||
| 30 | @Autowired | 31 | @Autowired |
| 31 | - private SIPProcessorObserver sipProcessorObserver; | ||
| 32 | - | ||
| 33 | - @Autowired | ||
| 34 | - private SipSubscribe sipSubscribe; | 32 | + private ISIPProcessorObserver sipProcessorObserver; |
| 35 | 33 | ||
| 36 | private SipStackImpl sipStack; | 34 | private SipStackImpl sipStack; |
| 37 | 35 | ||
| 38 | private SipFactory sipFactory; | 36 | private SipFactory sipFactory; |
| 39 | 37 | ||
| 40 | - /** | ||
| 41 | - * 消息处理器线程池 | ||
| 42 | - */ | ||
| 43 | - private ThreadPoolExecutor processThreadPool; | ||
| 44 | - | ||
| 45 | - public SipLayer() { | ||
| 46 | - int processThreadNum = Runtime.getRuntime().availableProcessors() * 10; | ||
| 47 | - LinkedBlockingQueue<Runnable> processQueue = new LinkedBlockingQueue<>(10000); | ||
| 48 | - processThreadPool = new ThreadPoolExecutor(processThreadNum,processThreadNum, | ||
| 49 | - 0L,TimeUnit.MILLISECONDS,processQueue, | ||
| 50 | - new ThreadPoolExecutor.CallerRunsPolicy()); | ||
| 51 | - } | ||
| 52 | - | ||
| 53 | 38 | ||
| 54 | @Bean("sipFactory") | 39 | @Bean("sipFactory") |
| 55 | private SipFactory createSipFactory() { | 40 | private SipFactory createSipFactory() { |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/ISIPProcessorObserver.java
0 → 100644
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java
| @@ -7,6 +7,9 @@ import com.genersoft.iot.vmp.gb28181.transmit.event.timeout.ITimeoutProcessor; | @@ -7,6 +7,9 @@ import com.genersoft.iot.vmp.gb28181.transmit.event.timeout.ITimeoutProcessor; | ||
| 7 | import org.slf4j.Logger; | 7 | import org.slf4j.Logger; |
| 8 | import org.slf4j.LoggerFactory; | 8 | import org.slf4j.LoggerFactory; |
| 9 | import org.springframework.beans.factory.annotation.Autowired; | 9 | import org.springframework.beans.factory.annotation.Autowired; |
| 10 | +import org.springframework.beans.factory.annotation.Qualifier; | ||
| 11 | +import org.springframework.scheduling.annotation.Async; | ||
| 12 | +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; | ||
| 10 | import org.springframework.stereotype.Component; | 13 | import org.springframework.stereotype.Component; |
| 11 | 14 | ||
| 12 | import javax.sip.*; | 15 | import javax.sip.*; |
| @@ -22,7 +25,7 @@ import java.util.concurrent.ConcurrentHashMap; | @@ -22,7 +25,7 @@ import java.util.concurrent.ConcurrentHashMap; | ||
| 22 | * @date: 2021年11月5日 下午15:32 | 25 | * @date: 2021年11月5日 下午15:32 |
| 23 | */ | 26 | */ |
| 24 | @Component | 27 | @Component |
| 25 | -public class SIPProcessorObserver implements SipListener { | 28 | +public class SIPProcessorObserver implements ISIPProcessorObserver { |
| 26 | 29 | ||
| 27 | private final static Logger logger = LoggerFactory.getLogger(SIPProcessorObserver.class); | 30 | private final static Logger logger = LoggerFactory.getLogger(SIPProcessorObserver.class); |
| 28 | 31 | ||
| @@ -33,6 +36,10 @@ public class SIPProcessorObserver implements SipListener { | @@ -33,6 +36,10 @@ public class SIPProcessorObserver implements SipListener { | ||
| 33 | @Autowired | 36 | @Autowired |
| 34 | private SipSubscribe sipSubscribe; | 37 | private SipSubscribe sipSubscribe; |
| 35 | 38 | ||
| 39 | + @Autowired | ||
| 40 | + @Qualifier(value = "taskExecutor") | ||
| 41 | + private ThreadPoolTaskExecutor poolTaskExecutor; | ||
| 42 | + | ||
| 36 | /** | 43 | /** |
| 37 | * 添加 request订阅 | 44 | * 添加 request订阅 |
| 38 | * @param method 方法名 | 45 | * @param method 方法名 |
| @@ -65,13 +72,17 @@ public class SIPProcessorObserver implements SipListener { | @@ -65,13 +72,17 @@ public class SIPProcessorObserver implements SipListener { | ||
| 65 | */ | 72 | */ |
| 66 | @Override | 73 | @Override |
| 67 | public void processRequest(RequestEvent requestEvent) { | 74 | public void processRequest(RequestEvent requestEvent) { |
| 68 | - String method = requestEvent.getRequest().getMethod(); | ||
| 69 | - ISIPRequestProcessor sipRequestProcessor = requestProcessorMap.get(method); | ||
| 70 | - if (sipRequestProcessor == null) { | ||
| 71 | - logger.warn("不支持方法{}的request", method); | ||
| 72 | - return; | ||
| 73 | - } | ||
| 74 | - requestProcessorMap.get(method).process(requestEvent); | 75 | + |
| 76 | + poolTaskExecutor.execute(() -> { | ||
| 77 | + String method = requestEvent.getRequest().getMethod(); | ||
| 78 | + ISIPRequestProcessor sipRequestProcessor = requestProcessorMap.get(method); | ||
| 79 | + if (sipRequestProcessor == null) { | ||
| 80 | + logger.warn("不支持方法{}的request", method); | ||
| 81 | + return; | ||
| 82 | + } | ||
| 83 | + requestProcessorMap.get(method).process(requestEvent); | ||
| 84 | + }); | ||
| 85 | + | ||
| 75 | } | 86 | } |
| 76 | 87 | ||
| 77 | /** | 88 | /** |
| @@ -90,43 +101,45 @@ public class SIPProcessorObserver implements SipListener { | @@ -90,43 +101,45 @@ public class SIPProcessorObserver implements SipListener { | ||
| 90 | // } | 101 | // } |
| 91 | // sipRequestProcessor.process(responseEvent); | 102 | // sipRequestProcessor.process(responseEvent); |
| 92 | 103 | ||
| 93 | - | ||
| 94 | - Response response = responseEvent.getResponse(); | ||
| 95 | - logger.debug(responseEvent.getResponse().toString()); | ||
| 96 | - int status = response.getStatusCode(); | ||
| 97 | - if (((status >= 200) && (status < 300)) || status == 401) { // Success! | 104 | + poolTaskExecutor.execute(() -> { |
| 105 | + Response response = responseEvent.getResponse(); | ||
| 106 | + logger.debug(responseEvent.getResponse().toString()); | ||
| 107 | + int status = response.getStatusCode(); | ||
| 108 | + if (((status >= 200) && (status < 300)) || status == 401) { // Success! | ||
| 98 | // ISIPResponseProcessor processor = processorFactory.createResponseProcessor(evt); | 109 | // ISIPResponseProcessor processor = processorFactory.createResponseProcessor(evt); |
| 99 | - CSeqHeader cseqHeader = (CSeqHeader) responseEvent.getResponse().getHeader(CSeqHeader.NAME); | ||
| 100 | - String method = cseqHeader.getMethod(); | ||
| 101 | - ISIPResponseProcessor sipRequestProcessor = responseProcessorMap.get(method); | ||
| 102 | - if (sipRequestProcessor != null) { | ||
| 103 | - sipRequestProcessor.process(responseEvent); | ||
| 104 | - } | ||
| 105 | - if (responseEvent.getResponse() != null && sipSubscribe.getOkSubscribesSize() > 0 ) { | ||
| 106 | - CallIdHeader callIdHeader = (CallIdHeader)responseEvent.getResponse().getHeader(CallIdHeader.NAME); | ||
| 107 | - if (callIdHeader != null) { | ||
| 108 | - SipSubscribe.Event subscribe = sipSubscribe.getOkSubscribe(callIdHeader.getCallId()); | ||
| 109 | - if (subscribe != null) { | ||
| 110 | - SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult(responseEvent); | ||
| 111 | - subscribe.response(eventResult); | 110 | + CSeqHeader cseqHeader = (CSeqHeader) responseEvent.getResponse().getHeader(CSeqHeader.NAME); |
| 111 | + String method = cseqHeader.getMethod(); | ||
| 112 | + ISIPResponseProcessor sipRequestProcessor = responseProcessorMap.get(method); | ||
| 113 | + if (sipRequestProcessor != null) { | ||
| 114 | + sipRequestProcessor.process(responseEvent); | ||
| 115 | + } | ||
| 116 | + if (responseEvent.getResponse() != null && sipSubscribe.getOkSubscribesSize() > 0 ) { | ||
| 117 | + CallIdHeader callIdHeader = (CallIdHeader)responseEvent.getResponse().getHeader(CallIdHeader.NAME); | ||
| 118 | + if (callIdHeader != null) { | ||
| 119 | + SipSubscribe.Event subscribe = sipSubscribe.getOkSubscribe(callIdHeader.getCallId()); | ||
| 120 | + if (subscribe != null) { | ||
| 121 | + SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult(responseEvent); | ||
| 122 | + subscribe.response(eventResult); | ||
| 123 | + } | ||
| 112 | } | 124 | } |
| 113 | } | 125 | } |
| 114 | - } | ||
| 115 | - } else if ((status >= 100) && (status < 200)) { | ||
| 116 | - // 增加其它无需回复的响应,如101、180等 | ||
| 117 | - } else { | ||
| 118 | - logger.warn("接收到失败的response响应!status:" + status + ",message:" + response.getReasonPhrase()/* .getContent().toString()*/); | ||
| 119 | - if (responseEvent.getResponse() != null && sipSubscribe.getErrorSubscribesSize() > 0 ) { | ||
| 120 | - CallIdHeader callIdHeader = (CallIdHeader)responseEvent.getResponse().getHeader(CallIdHeader.NAME); | ||
| 121 | - if (callIdHeader != null) { | ||
| 122 | - SipSubscribe.Event subscribe = sipSubscribe.getErrorSubscribe(callIdHeader.getCallId()); | ||
| 123 | - if (subscribe != null) { | ||
| 124 | - SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult(responseEvent); | ||
| 125 | - subscribe.response(eventResult); | 126 | + } else if ((status >= 100) && (status < 200)) { |
| 127 | + // 增加其它无需回复的响应,如101、180等 | ||
| 128 | + } else { | ||
| 129 | + logger.warn("接收到失败的response响应!status:" + status + ",message:" + response.getReasonPhrase()/* .getContent().toString()*/); | ||
| 130 | + if (responseEvent.getResponse() != null && sipSubscribe.getErrorSubscribesSize() > 0 ) { | ||
| 131 | + CallIdHeader callIdHeader = (CallIdHeader)responseEvent.getResponse().getHeader(CallIdHeader.NAME); | ||
| 132 | + if (callIdHeader != null) { | ||
| 133 | + SipSubscribe.Event subscribe = sipSubscribe.getErrorSubscribe(callIdHeader.getCallId()); | ||
| 134 | + if (subscribe != null) { | ||
| 135 | + SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult(responseEvent); | ||
| 136 | + subscribe.response(eventResult); | ||
| 137 | + } | ||
| 126 | } | 138 | } |
| 127 | } | 139 | } |
| 128 | } | 140 | } |
| 129 | - } | 141 | + }); |
| 142 | + | ||
| 130 | 143 | ||
| 131 | } | 144 | } |
| 132 | 145 |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java
| @@ -204,7 +204,6 @@ public class SIPRequestHeaderProvider { | @@ -204,7 +204,6 @@ public class SIPRequestHeaderProvider { | ||
| 204 | 204 | ||
| 205 | // Event | 205 | // Event |
| 206 | EventHeader eventHeader = sipFactory.createHeaderFactory().createEventHeader(event); | 206 | EventHeader eventHeader = sipFactory.createHeaderFactory().createEventHeader(event); |
| 207 | - eventHeader.setEventType("Catalog"); | ||
| 208 | request.addHeader(eventHeader); | 207 | request.addHeader(eventHeader); |
| 209 | 208 | ||
| 210 | ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("APPLICATION", "MANSCDP+xml"); | 209 | ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("APPLICATION", "MANSCDP+xml"); |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
| @@ -1496,7 +1496,7 @@ public class SIPCommander implements ISIPCommander { | @@ -1496,7 +1496,7 @@ public class SIPCommander implements ISIPCommander { | ||
| 1496 | CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId() | 1496 | CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId() |
| 1497 | : udpSipProvider.getNewCallId(); | 1497 | : udpSipProvider.getNewCallId(); |
| 1498 | 1498 | ||
| 1499 | - Request request = headerProvider.createSubscribeRequest(device, cmdXml.toString(), "z9hG4bK-viaPos-" + tm, "fromTagPos" + tm, null, device.getSubscribeCycleForCatalog(), "presence" , callIdHeader); | 1499 | + Request request = headerProvider.createSubscribeRequest(device, cmdXml.toString(), "z9hG4bK-viaPos-" + tm, "fromTagPos" + tm, null, device.getSubscribeCycleForCatalog(), "Catalog" , callIdHeader); |
| 1500 | transmitRequest(device, request, errorEvent, okEvent); | 1500 | transmitRequest(device, request, errorEvent, okEvent); |
| 1501 | 1501 | ||
| 1502 | return true; | 1502 | return true; |