一個(gè)task項(xiàng)目呜呐,應(yīng)用里邊都是一些定時(shí)任務(wù)喷斋。我和新入職的高開商定程序部署不依賴于tomcat。
計(jì)劃趕不上變化茧彤,任務(wù)開發(fā)完成還沒等上線呢骡显,哥們要離職了。工作交接時(shí)大概說了一下上線怎么部署曾掂。
結(jié)果呢惫谤,當(dāng)我在linux測試服務(wù)器上部署時(shí),可費(fèi)了一些周折珠洗。之前都是把應(yīng)用部署到tomcat下面的溜歪。那位高開說過,不依賴tomcat容器的部署方式已經(jīng)不是新概念了许蓖。漫長的解決過程中蝴猪,有同事建議我放棄,改用tomcat吧膊爪。我覺得有必要堅(jiān)持下來自阱,最終也堅(jiān)持下來了。
一.先介紹一下項(xiàng)目
工程如下圖米酬。assembly/bin下有一個(gè)emax-paycenter-task.sh文件沛豌,主要是通過nohup命令來運(yùn)行LauncherMain。高開說了赃额,部署時(shí)將該shell文件放到應(yīng)用的根目錄下加派,通過執(zhí)行它來啟動(dòng)程序。
emax-paycenter-task.sh文件里是如下命令跳芳,start用的是nohup命令:
LauncherMain.java里是一個(gè)main方法哼丈,用來初始化環(huán)境:
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.joran.JoranConfigurator;
import org.slf4j.ILoggerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.ClassPathResource;
import org.springframework.web.context.support.XmlWebApplicationContext;
import java.net.URL;
import java.util.concurrent.Semaphore;
/**
* Description 啟動(dòng)方法
* Date 2018/2/8 上午10:01
*/
public class LauncherMain {
private static Logger logger= LoggerFactory.getLogger(LauncherMain.class);
public static void main(String[] args) throws Exception {
logger.info("init @Prop");
Semaphore sp = new Semaphore(0);
XmlWebApplicationContext xmlWeb = new XmlWebApplicationContext();
xmlWeb.setConfigLocation("classpath*:*spring/spring-applicationContext.xml");
String logbackCfg = "logback.xml";
URL logURL = new ClassPathResource(logbackCfg).getURL();
ILoggerFactory loggerFactory = LoggerFactory.getILoggerFactory();
LoggerContext loggerContext = (LoggerContext) loggerFactory;
JoranConfigurator configurator = new JoranConfigurator();
configurator.setContext(loggerContext);
configurator.doConfigure(logURL);
xmlWeb.refresh();
xmlWeb.start();
sp.acquire();
}
}
項(xiàng)目中涉及到的定時(shí)任務(wù)采用Spring的@Scheduled來實(shí)現(xiàn):
@Component
public class AgentPayTask {
@Autowired
private LimitConfigDataHolder limitConfigDataHolder;
@Autowired
private AgentPayTaskService agentPayTaskService;
private static Logger logger = LoggerFactory.getLogger(AgentPayTask.class);
@Scheduled(cron ="0/5 * * * * ?")
public void process() {
System.out.println("AgentPayTask111");
logger.info("AgentPayTask");
Map<String, RateLimiterConfig> LimiterMap = limitConfigDataHolder.getAgentPayLimiter();
agentPayTaskService.distributeTask(LimiterMap);
}
}
二.linux部署
我在本地直接運(yùn)行main方法,程序是沒問題的筛严,里面的定時(shí)任務(wù)都可以正常跑。
將maven打包后的emax-paycenter-task-1.0.0-SNAPSHOT-assembly.tar.gz解壓部署到測試服務(wù)器上饶米。最終執(zhí)行命令
./emax-paycenter-task.sh start &
查看生成的nohup.out文件桨啃,發(fā)現(xiàn)總是找到class com.emax.paycenter.LauncherMain。
后來咨詢運(yùn)維檬输,發(fā)現(xiàn)是沒有給目錄分配權(quán)限所致照瘾。
技能嫻熟的運(yùn)維又幫忙把emax-paycenter-task.sh里的命令修正了一下。最終如下:
再次按照上面命令啟動(dòng)程序丧慈,查看日志文件發(fā)現(xiàn)只有如下一條日志:
2018-03-21 15:11:45.381 [main] INFO [com.emax.paycenter.LauncherMain] - init @Prop
多次測試發(fā)現(xiàn)析命,程序執(zhí)行到sp.acquire();這條語句時(shí)主卫,就不動(dòng)了;我在這條語句后加打印日志結(jié)果也沒打印出來鹃愤;定時(shí)任務(wù)也沒執(zhí)行簇搅。
了解了一下Semaphore信號量,把permits改成0或1或其他值软吐,都不行瘩将。
。凹耙。姿现。。肖抱。一個(gè)小時(shí)备典。。意述。提佣。
。欲险。镐依。。天试。兩個(gè)小時(shí)槐壳。。喜每。务唐。
找同事幫助,無果带兜。
枫笛。。刚照。刑巧。。若干小時(shí)无畔。啊楚。。浑彰。
靈感咋現(xiàn)恭理!我將懷疑的焦點(diǎn)放到了spring context的設(shè)置這里,是不是壓根都沒有設(shè)置成功呢郭变?
xmlWeb.setConfigLocation("classpath*:*spring/spring-applicationContext.xml");
莫非是各jar包里有同名的配置文件颜价? 將路徑參數(shù)"classpath:spring/spring-applicationContext.xml"改成"classpath:spring/spring-applicationContext.xml"后涯保,查看nohup.out發(fā)現(xiàn)出現(xiàn)了新的問題:
[root@localhost emax-paycenter-task]# tail -f nohup.out
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:531)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:295)
... 11 more
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.emax.paycenter.api.service.IPayCenterFacade]
found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency.
Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:997)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:867)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:779)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:503)
... 13 more
同時(shí),日志文件里存在類似問題:spring context初始化時(shí)出現(xiàn)了異常周伦。項(xiàng)目中一個(gè)類“AgentPayTaskQueryServiceImpl”通過@Autowired依賴注入了另一個(gè)bean“IPayCenterFacade”夕春。
而在spring context里找不到“IPayCenterFacade”這個(gè)依賴(NoSuchBeanDefinitionException),從而導(dǎo)致spring context創(chuàng)建AgentPayTaskQueryServiceImpl實(shí)例“agentPayTaskQueryServiceImpl”失敽崃尽(BeanCreationException異常)撇他。
最后,將spring applicationContext里對dubbo配置文件的import由
<import resource="classpath*:*spring/dubbo-applicationContext.xml"/>
改成
<import resource="classpath:spring/dubbo-applicationContext.xml"/>
就可以了狈蚤。