Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537
最近有幾個讀者私信給我,問我他們的業(yè)務(wù)場景,要用什么樣的定時任務(wù)。確實(shí),在不用的業(yè)務(wù)場景下要用不同的定時任務(wù),其實(shí)我們的選擇還是挺多的。我今天給大家總結(jié)10種非常實(shí)用的定時任務(wù),總有一種是適合你的。
不知道你有沒有遇到過這種場景:有時需要臨時統(tǒng)計(jì)線上的數(shù)據(jù),然后導(dǎo)出到excel表格中。這種需求有時較為復(fù)雜,光靠寫sql語句是無法滿足需求的,這就需要寫java代碼了。然后將該程序打成一個jar包,在線上環(huán)境執(zhí)行,最后將生成的excel文件下載到本地。
為了減小對線上環(huán)境的影響,我們一般會選擇在凌晨1-2點(diǎn),趁用戶量少的時候,執(zhí)行統(tǒng)計(jì)程序。(其實(shí)凌晨4點(diǎn)左右,用戶才是最少的)
由于時間太晚了,我們完全沒必要守在那里等執(zhí)行結(jié)果,一個定時任務(wù)就能可以搞定。
那么,這種情況用哪種定時任務(wù)更合適呢?
答案是:linux系統(tǒng)的crontab。(不過也不排除有些項(xiàng)目沒部署在linux系統(tǒng)中)
運(yùn)行crontab -e,可以編輯定時器,然后加入如下命令:
0 2 * * * /usr/local/java/jdk1.8/bin/java -jar /data/app/tool.jar > /logs/tool.log &
就可以在每天凌晨2點(diǎn),定時執(zhí)行tool.jar程序,并且把日志輸出到tool.log文件中。當(dāng)然你也可以把后面的執(zhí)行java程序的命令寫成shell腳本,更方便維護(hù)。
使用這種定時任務(wù)支持方便修改定時規(guī)則,有界面可以統(tǒng)一管理配置的各種定時腳本。
crontab命令的基本格式如下:
crontab [參數(shù)] [文件名]
如果沒有指定文件名,則接收鍵盤上輸入的命令,并將它載入到crontab。
參數(shù)功能對照表如下:
參數(shù)功能-u指定用戶-e編輯某個用戶的crontab文件內(nèi)容-l顯示某個用戶的crontab文件內(nèi)容-r刪除某用戶的crontab文件-i刪除某用戶的crontab文件時需確認(rèn)
以上參數(shù),如果沒有使用-u指定用戶,則默認(rèn)使用的當(dāng)前用戶。
通過crontab -e命令編輯文件內(nèi)容,具體語法如下:
[分] [小時] [日期] [月] [星期] 具體任務(wù)
其中:
還有一些特殊字符,比如:
此外,順便說一下crontab需要crond服務(wù)支持,crond是linux下用來周期地執(zhí)行某種任務(wù)的一個守護(hù)進(jìn)程,在安裝linux操作系統(tǒng)后,默認(rèn)會安裝crond服務(wù)工具,且crond服務(wù)默認(rèn)就是自啟動的。crond進(jìn)程每分鐘會定期檢查是否有要執(zhí)行的任務(wù),如果有,則會自動執(zhí)行該任務(wù)。
可以通過以下命令操作相關(guān)服務(wù):
service crond status // 查看運(yùn)行狀態(tài)
service crond start //啟動服務(wù)
service crond stop //關(guān)閉服務(wù)
service crond restart //重啟服務(wù)
service crond reload //重新載入配置
使用crontab的優(yōu)缺點(diǎn):
各位親愛的朋友,你沒看錯,Thread類真的能做定時任務(wù)。如果你看過一些定時任務(wù)框架的源碼,你最后會發(fā)現(xiàn),它們的底層也會使用Thread類。
實(shí)現(xiàn)這種定時任務(wù)的具體代碼如下:
public static void init() {
new Thread(() -> {
while (true) {
try {
System.out.println("doSameThing");
Thread.sleep(1000 * 60 * 5);
} catch (Exception e) {
log.error(e);
}
}
}).start();
}
使用Thread類可以做最簡單的定時任務(wù),在run方法中有個while的死循環(huán)(當(dāng)然還有其他方式),執(zhí)行我們自己的任務(wù)。有個需要特別注意的地方是,需要用try...catch捕獲異常,否則如果出現(xiàn)異常,就直接退出循環(huán),下次將無法繼續(xù)執(zhí)行了。
這種方式做的定時任務(wù),只能周期性執(zhí)行,不能支持定時在某個時間點(diǎn)執(zhí)行。
此外,該線程可以定義成守護(hù)線程,在后臺默默執(zhí)行就好。
使用場景:比如項(xiàng)目中有時需要每隔10分鐘去下載某個文件,或者每隔5分鐘去讀取模板文件生成靜態(tài)html頁面等等,一些簡單的周期性任務(wù)場景。
使用Thread類的優(yōu)缺點(diǎn):
Timer類是jdk專門提供的定時器工具,用來在后臺線程計(jì)劃執(zhí)行指定任務(wù),在java.util包下,要跟TimerTask一起配合使用。
Timer類其實(shí)是一個任務(wù)調(diào)度器,它里面包含了一個TimerThread線程,在這個線程中無限循環(huán)從TaskQueue中獲取TimerTask(該類實(shí)現(xiàn)了Runnable接口),調(diào)用其run方法,就能異步執(zhí)行定時任務(wù)。我們需要繼承TimerTask類,實(shí)現(xiàn)它的run方法,在該方法中加上自己的業(yè)務(wù)邏輯。
實(shí)現(xiàn)這種定時任務(wù)的具體代碼如下:
public class TimerTest {
public static void main(String[] args) {
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
System.out.println("doSomething");
}
},2000,1000);
}
}
先實(shí)例化一個Timer類,然后調(diào)用它的schedule方法,在該方法中實(shí)例化TimerTask類,業(yè)務(wù)邏輯寫在run方法中。schedule方法最后的兩次參數(shù)分別表示:延遲時間 和 間隔時間,單位是毫秒。上面例子中,設(shè)置的定時任務(wù)是每隔1秒執(zhí)行一次,延遲2秒執(zhí)行。
主要包含6個方法:
不過使用Timer實(shí)現(xiàn)定時任務(wù)有以下問題:
使用Timer類的優(yōu)缺點(diǎn):
ScheduledExecutorService是JDK1.5+版本引進(jìn)的定時任務(wù),該類位于java.util.concurrent并發(fā)包下。
ScheduledExecutorService是基于多線程的,設(shè)計(jì)的初衷是為了解決Timer單線程執(zhí)行,多個任務(wù)之間會互相影響的問題。
它主要包含4個方法:
實(shí)現(xiàn)這種定時任務(wù)的具體代碼如下:
public class ScheduleExecutorTest {
public static void main(String[] args) {
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(5);
scheduledExecutorService.scheduleAtFixedRate(() -> {
System.out.println("doSomething");
},1000,1000, TimeUnit.MILLISECONDS);
}
}
調(diào)用ScheduledExecutorService類的scheduleAtFixedRate方法實(shí)現(xiàn)周期性任務(wù),每隔1秒鐘執(zhí)行一次,每次延遲1秒再執(zhí)行。
這種定時任務(wù)是阿里巴巴開發(fā)者規(guī)范中用來替代Timer類的方案,對于多線程執(zhí)行周期性任務(wù),是個不錯的選擇。
ScheduledExecutorService的優(yōu)缺點(diǎn):
spring task是spring3以上版本自帶的定時任務(wù),實(shí)現(xiàn)定時任務(wù)的功能時,需要引入spring-context包,目前它支持:xml 和 注解 兩種方式。
由于xml方式太古老了,我們以springboot項(xiàng)目中注解方式為例。
第一步,在pom.xml文件中引入spring-context相關(guān)依賴。
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
第二步,在springboot啟動類上加上@EnableScheduling注解。
@EnableScheduling
@SpringBootApplication
public class Application {
public static void main(String[] args) {
new SpringApplicationBuilder(Application.class).web(WebApplicationType.SERVLET).run(args);
}
}
第三步,使用@Scheduled注解定義定時規(guī)則。
@Service
public class SpringTaskTest {
@Scheduled(cron = "${sue.spring.task.cron}")
public void fun() {
System.out.println("doSomething");
}
}
第四步,在applicationContext.properties文件中配置參數(shù):
sue.spring.task.cron=*/10 * * * * ?
這樣就能每隔10秒執(zhí)行一次fun方法了。
spring4以上的版本中,cron表達(dá)式包含6個參數(shù):
[秒] [分] [時] [日期] [月] [星期]
還支持幾個常用的特殊符號:
cron表達(dá)式參數(shù)具體含義:
常見cron表達(dá)式使用舉例:
spring task先通過ScheduledAnnotationBeanPostProcessor類的processScheduled方法,解析和收集Scheduled注解中的參數(shù),包含:cron表達(dá)式。
然后在ScheduledTaskRegistrar類的afterPropertiesSet方法中,默認(rèn)初始化一個單線程的ThreadPoolExecutor執(zhí)行任務(wù)。
對spring task感興趣的小伙伴,可以加我微信找我私聊。
使用spring task的優(yōu)缺點(diǎn):
quartz是OpenSymphony開源組織在Job scheduling領(lǐng)域的開源項(xiàng)目,是由java開發(fā)的一個開源的任務(wù)日程管理系統(tǒng)。
quartz能做什么?
架構(gòu)圖如下:
quartz包含的主要接口如下:
我們還是以springboot集成quartz為例。
第一步,在pom.xml文件中引入quartz相關(guān)依賴。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
第二步,創(chuàng)建真正的定時任務(wù)執(zhí)行類,該類繼承QuartzJobBean。
public class QuartzTestJob extends QuartzJobBean {
@Override
protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
String userName = (String) context.getJobDetail().getJobDataMap().get("userName");
System.out.println("userName:" + userName);
}
}
第三步,創(chuàng)建調(diào)度程序JobDetail和調(diào)度器Trigger。
@Configuration
public class QuartzConfig {
@Value("${sue.spring.quartz.cron}")
private String testCron;
/**
* 創(chuàng)建定時任務(wù)
*/
@Bean
public JobDetail quartzTestDetail() {
JobDetail jobDetail = JobBuilder.newJob(QuartzTestJob.class)
.withIdentity("quartzTestDetail", "QUARTZ_TEST")
.usingJobData("userName", "susan")
.storeDurably()
.build();
return jobDetail;
}
/**
* 創(chuàng)建觸發(fā)器
*/
@Bean
public Trigger quartzTestJobTrigger() {
//每隔5秒執(zhí)行一次
CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(testCron);
//創(chuàng)建觸發(fā)器
Trigger trigger = TriggerBuilder.newTrigger()
.forJob(quartzTestDetail())
.withIdentity("quartzTestJobTrigger", "QUARTZ_TEST_JOB_TRIGGER")
.withSchedule(cronScheduleBuilder)
.build();
return trigger;
}
}
第四步,在applicationContext.properties文件中配置參數(shù):
sue.spring.quartz.cron=*/5 * * * * ?
這樣就能每隔5秒執(zhí)行一次QuartzTestJob類的executeInternal方法了。
CronTrigger配置格式:
[秒] [分] [小時] [日] [月] [周] [年]
spring quartz跟spring task的cron表達(dá)式規(guī)則基本一致,只是spring4以上的版本去掉了后面的年,而quartz的CronTrigger的年是非必填的,這里我就不做過多介紹了。
使用spring quartz的優(yōu)缺點(diǎn):
xxl-job是大眾點(diǎn)評(許雪里)開發(fā)的一個分布式任務(wù)調(diào)度平臺,其核心設(shè)計(jì)目標(biāo)是開發(fā)迅速、學(xué)習(xí)簡單、輕量級、易擴(kuò)展。現(xiàn)已開放源代碼并接入多家公司線上產(chǎn)品線,開箱即用。
xxl-job框架對quartz進(jìn)行了擴(kuò)展,使用mysql數(shù)據(jù)庫存儲數(shù)據(jù),并且內(nèi)置jetty作為RPC服務(wù)調(diào)用。
主要特點(diǎn)如下:
管理界面:
整體架構(gòu)圖如下:
使用quartz架構(gòu)圖如下:
xxl-admin管理后臺部署和mysql腳本執(zhí)行等這些前期準(zhǔn)備工作,我就不過多介紹了,有需求的朋友可以找我私聊,這些更偏向于運(yùn)維的事情。
假設(shè)前期工作已經(jīng)OK了,接下來我們需要:
第一步,在pom.xml文件中引入xxl-job相關(guān)依賴。
<dependency>
<groupId>com.xuxueli</groupId>
<artifactId>xxl-job-core</artifactId>
</dependency>
第二步,在applicationContext.properties文件中配置參數(shù):
xxl.job.admin.address: http://localhost:8088/xxl-job-admin/
xxl.job.executor.appname: xxl-job-executor-sample
xxl.job.executor.port: 8888
xxl.job.executor.logpath: /data/applogs/xxl-job/
第三步,創(chuàng)建HelloJobHandler類繼承IJobHandler類:
@JobHandler(value = "helloJobHandler")
@Component
public class HelloJobHandler extends IJobHandler {
@Override
public ReturnT<String> execute(String param) {
System.out.println("XXL-JOB, Hello World.");
return SUCCESS;
}
}
這樣定時任務(wù)就配置好了。
建議把定時任務(wù)單獨(dú)部署到另外一個服務(wù)中,跟api服務(wù)分開。根據(jù)我以往的經(jīng)驗(yàn),job大部分情況下,會對數(shù)據(jù)做批量操作,如果操作的數(shù)據(jù)量太大,可能會對服務(wù)的內(nèi)存和cpu資源造成一定的影響。
使用xxl-job的優(yōu)缺點(diǎn):
elastic-job是當(dāng)當(dāng)網(wǎng)開發(fā)的彈性分布式任務(wù)調(diào)度系統(tǒng),功能豐富強(qiáng)大,采用zookeeper實(shí)現(xiàn)分布式協(xié)調(diào),實(shí)現(xiàn)任務(wù)高可用以及分片。它是專門為高并發(fā)和復(fù)雜業(yè)務(wù)場景開發(fā)。
elastic-job目前是apache的shardingsphere項(xiàng)目下的一個子項(xiàng)目,官網(wǎng)地址:http://shardingsphere.apache.org/elasticjob/。
elastic-job在2.x之后,出了兩個產(chǎn)品線:Elastic-Job-Lite和Elastic-Job-Cloud,而我們一般使用Elastic-Job-Lite就能夠滿足需求。Elastic-Job-Lite定位為輕量級無中心化解決方案,使用jar包的形式提供分布式任務(wù)的協(xié)調(diào)服務(wù),外部僅依賴于Zookeeper。。
主要特點(diǎn)如下:
整體架構(gòu)圖:
第一步,在pom.xml文件中引入elastic-job相關(guān)依賴。
<dependency>
<groupId>com.dangdang</groupId>
<artifactId>elastic-job-lite-core</artifactId>
</dependency>
<dependency>
<groupId>com.dangdang</groupId>
<artifactId>elastic-job-lite-spring</artifactId>
</dependency>
第二步,增加ZKConfig類,配置zookeeper:
@Configuration
@ConditionalOnExpression("'${zk.serverList}'.length() > 0")
public class ZKConfig {
@Bean
public ZookeeperRegistryCenter registry(@Value("${zk.serverList}") String serverList,
@Value("${zk.namespace}") String namespace) {
return new ZookeeperRegistryCenter(new ZookeeperConfiguration(serverList, namespace));
}
}
第三步,定義一個類實(shí)現(xiàn)SimpleJob接口:
public class TestJob implements SimpleJob {
@Override
public void execute(ShardingContext shardingContext){
System.out.println("ShardingTotalCount:"+shardingContext.getShardingTotalCount());
System.out.println("ShardingItem:"+shardingContext.getShardingItem());
}
}
第四步,增加JobConfig配置任務(wù):
@Configuration
public class JobConfig {
@Value("${sue.spring.elatisc.cron}")
private String testCron;
@Value("${sue.spring.elatisc.itemParameters}")
private String shardingItemParameters;
@Value("${sue.spring.elatisc.jobParameters}")
private String jobParameters =;
@Value("${sue.spring.elatisc.shardingTotalCount}")
private int shardingTotalCount;
@Autowired
private ZookeeperRegistryCenter registryCenter;
@Bean
public SimpleJob testJob() {
return new TestJob();
}
@Bean
public JobScheduler simpleJobScheduler(final SimpleJob simpleJob) {
return new SpringJobScheduler(simpleJob, registryCenter, getConfiguration(simpleJob.getClass(),
cron, shardingTotalCount, shardingItemParameters, jobParameters));
}
private geConfiguration getConfiguration(Class<? extends SimpleJob> jobClass,String cron,int shardingTotalCount,String shardingItemParameters,String jobParameters) {
JobCoreConfiguration simpleCoreConfig = JobCoreConfiguration.newBuilder(jobClass.getName(), testCron, shardingTotalCount).
shardingItemParameters(shardingItemParameters).jobParameter(jobParameters).build();
SimpleJobConfiguration simpleJobConfig = new SimpleJobConfiguration(simpleCoreConfig, jobClass.getCanonicalName());
LiteJobConfiguration jobConfig = LiteJobConfiguration.newBuilder(simpleJobConfig).overwrite(true).build();
return jobConfig;
}
}
其中:
第五步,在applicationContext.properties文件中配置參數(shù):
spring.application.name=elasticjobDemo
zk.serverList=localhost:2181
zk.namespace=elasticjobDemo
sue.spring.elatisc.cron=0/5 * * * * ?
sue.spring.elatisc.itemParameters=0=A,1=B,2=C,3=D
sue.spring.elatisc.jobParameters=test
sue.spring.elatisc.shardingTotalCount=4
這樣定時任務(wù)就配置好了,創(chuàng)建定時任務(wù)的步驟,相對于xxl-job來說要繁瑣一些。
使用elastic-job的優(yōu)缺點(diǎn):
Saturn是唯品會開源的一個分布式任務(wù)調(diào)度平臺。取代傳統(tǒng)的Linux Cron/Spring Batch Job的方式,做到全域統(tǒng)一配置,統(tǒng)一監(jiān)控,任務(wù)高可用以及分片并發(fā)處理。
Saturn是在當(dāng)當(dāng)開源的Elastic-Job基礎(chǔ)上,結(jié)合各方需求和我們的實(shí)踐見解改良而成。使用案例:唯品會、酷狗音樂、新網(wǎng)銀行、海融易、航美在線、量富征信等。
github地址:https://github.com/vipshop/Saturn/
TBSchedule是阿里開發(fā)的一款分布式任務(wù)調(diào)度平臺,旨在將調(diào)度作業(yè)從業(yè)務(wù)系統(tǒng)中分離出來,降低或者是消除和業(yè)務(wù)系統(tǒng)的耦合度,進(jìn)行高效異步任務(wù)處理。
目前被廣泛應(yīng)用在阿里巴巴、淘寶、支付寶、京東、聚美、汽車之家、國美等很多互聯(lián)網(wǎng)企業(yè)的流程調(diào)度系統(tǒng)中。
github地址:https://github.com/taobao/TBSchedule
老實(shí)說優(yōu)秀的定時任務(wù)還是挺多的,不是說哪種定時任務(wù)牛逼我們就一定要用哪種,而是要根據(jù)實(shí)際業(yè)務(wù)需求選擇。每種定時任務(wù)都有優(yōu)缺點(diǎn),合理選擇既能滿足業(yè)務(wù)需求,又能避免資源浪費(fèi),才是上上策。當(dāng)然在實(shí)際的業(yè)務(wù)場景,通常會多種定時任務(wù)一起配合使用。
標(biāo)簽是默認(rèn)是自動換行的,因此設(shè)置好寬度之后,能夠較好的實(shí)現(xiàn)效果,但是最近的項(xiàng)目中發(fā)現(xiàn),使用ajax加載數(shù)據(jù)之后,p標(biāo)簽內(nèi)的內(nèi)容沒有換行,導(dǎo)致布局錯亂,于是嘗試著使用換行樣式,雖然解決了問題,但是并沒有發(fā)現(xiàn)本質(zhì)原因,本質(zhì)在于,我當(dāng)時獲取的數(shù)據(jù)是一長串的數(shù)字,瀏覽器應(yīng)該是對數(shù)字和英文單詞處理方式相近,不會截?cái)唷?
先給出各種方式,再具體介紹每一個屬性。
強(qiáng)制不換行
p { white-space:nowrap; }
自動換行
p { word-wrap:break-word; }
強(qiáng)制英文單詞斷行
p { word-break:break-all; }
*注意:設(shè)置強(qiáng)制將英文單詞斷行,需要將行內(nèi)元素設(shè)置為塊級元素。
超出顯示省略號
p{text-overflow:ellipsis;overflow:hidden;}
white-space: normal|pre|nowrap|pre-wrap|pre-line|inherit;
white-space 屬性設(shè)置如何處理元素內(nèi)的空白
normal 默認(rèn)。空白會被瀏覽器忽略。
pre 空白會被瀏覽器保留。其行為方式類似 HTML 中的 pre 標(biāo)簽。
nowrap 文本不會換行,文本會在在同一行上繼續(xù),直到遇到 br 標(biāo)簽為止。
pre-wrap 保留空白符序列,但是正常地進(jìn)行換行。
pre-line 合并空白符序列,但是保留換行符。
inherit 規(guī)定應(yīng)該從父元素繼承 white-space 屬性的值。
word-wrap: normal|break-word;
word-wrap 屬性用來標(biāo)明是否允許瀏覽器在單詞內(nèi)進(jìn)行斷句,這是為了防止當(dāng)一個字符串太長而找不到它的自然斷句點(diǎn)時產(chǎn)生溢出現(xiàn)象。
normal: 只在允許的斷字點(diǎn)換行(瀏覽器保持默認(rèn)處理)
break-word:在長單詞或URL地址內(nèi)部進(jìn)行換行
word-break: normal|break-all|keep-all;
word-break 屬性用來標(biāo)明怎么樣進(jìn)行單詞內(nèi)的斷句。
normal:使用瀏覽器默認(rèn)的換行規(guī)則。
break-all:允許再單詞內(nèi)換行
keep-all:只能在半角空格或連字符處換行
舉例看起區(qū)別:
<!doctype html>
<html lang="en">
<head>
<!--網(wǎng)站編碼格式,UTF-8 國際編碼,GBK或 gb2312 中文編碼-->
<meta http-equiv="content-type" content="text/html;charset=utf-8" />
<meta name="Keywords" content="關(guān)鍵詞一,關(guān)鍵詞二">
<meta name="Description" content="網(wǎng)站描述內(nèi)容">
<meta name="Author" content="Yvette Lau">
<title>Document</title>
<!--css js 文件的引入-->
<style>
.word{background:#E4FFE9;width:250px;margin:50px auto;padding:20px;font-family:"microsoft yahei";}
/* 強(qiáng)制不換行 */
.nowrap{white-space:nowrap;}
/* 允許單詞內(nèi)斷句,首先會嘗試挪到下一行,看看下一行的寬度夠不夠,
不夠的話就進(jìn)行單詞內(nèi)的斷句 */
.breakword{word-wrap: break-word;}
/* 斷句時,不會把長單詞挪到下一行,而是直接進(jìn)行單詞內(nèi)的斷句 */
.breakAll{word-break:break-all;}
/* 超出部分顯示省略號 */
.ellipsis{text-overflow:ellipsis;overflow:hidden;}
</style>
</head>
<body>
<div class = "word">
<p class = "nowrap">wordwrap:breakword;absavhsafhuafdfbjhfvsalguvfaihuivfs</p>
<p class = "breakword">wordwrap:break-word;absavhsafhuafdfbjhfvsalguvfaihui</p>
<p class = "breakAll">wordwrap:break-word;absavhsafhuafdfbjhfvsalguvfaihuivf</p>
<p class = "normal">wordwrap:breakword;absavhsafhuafdfbjhfvsalguvfaihuivfsa</p>
<p class = "ellipsis">wordwrap:breakword;absavhsafhuafdfbjhfvsalguvfaihuivfsab</p>
</div>
</body>
</html>
效果如下:
開源精選》是我們分享Github、Gitee等開源社區(qū)中優(yōu)質(zhì)項(xiàng)目的欄目,包括技術(shù)、學(xué)習(xí)、實(shí)用與各種有趣的內(nèi)容。本期推薦的是一個Nginx界面配置工具——nginxWebUI。
nginxWebUI是一款圖形化管理nginx配置的工具, 可以使用網(wǎng)頁來快速配置nginx的各項(xiàng)功能, 包括http協(xié)議轉(zhuǎn)發(fā)、tcp協(xié)議轉(zhuǎn)發(fā)、反向代理、負(fù)載均衡、靜態(tài)html服務(wù)器、ssl證書自動申請、續(xù)簽、配置等,配置好后可一建生成nginx.conf文件, 同時可控制nginx使用此文件進(jìn)行啟動與重載,完成對nginx的圖形化控制閉環(huán)。
本項(xiàng)目是基于solon的web系統(tǒng),數(shù)據(jù)庫使用h2, 因此服務(wù)器上不需要安裝任何數(shù)據(jù)庫。
本系統(tǒng)通過Let's encrypt申請證書,使用acme.sh腳本進(jìn)行自動化申請和續(xù)簽,開啟續(xù)簽的證書將在每天凌晨2點(diǎn)進(jìn)行續(xù)簽,只有超過60天的證書才會進(jìn)行續(xù)簽,只支持在linux下簽發(fā)證書。
添加tcp/ip轉(zhuǎn)發(fā)配置支持時, 一些低版本的nginx可能需要重新編譯,通過添加–with-stream參數(shù)指定安裝stream模塊才能使用,但在ubuntu 18.04下,官方軟件庫中的nginx已經(jīng)帶有stream模塊,不需要重新編譯。本系統(tǒng)如果配置了tcp轉(zhuǎn)發(fā)項(xiàng)的話,會自動引入ngx_stream_module.so的配置項(xiàng),如果沒有開啟則不引入,最大限度優(yōu)化ngnix配置文件。
打開 http://ip:8080 進(jìn)入主頁。
登錄頁面,第一次打開會要求初始化管理員賬號。
進(jìn)入系統(tǒng)后,可在管理員管理里面添加修改管理員賬號。
在http參數(shù)配置中可以配置nginx的http項(xiàng)目,進(jìn)行http轉(zhuǎn)發(fā),默認(rèn)會給出幾個常用配置,其他需要的配置可自由增刪改查,可以勾選開啟日志跟蹤,生成日志文件。
在TCP參數(shù)配置中可以配置nginx的steam項(xiàng)目參數(shù),進(jìn)行tcp轉(zhuǎn)發(fā)。
在反向代理中可配置nginx的反向代理即server項(xiàng)功能,可開啟ssl功能,可以直接從網(wǎng)頁上上傳pem文件和key文件,或者使用系統(tǒng)內(nèi)申請的證書,可以直接開啟http轉(zhuǎn)跳https功能,也可開啟http2協(xié)議。
在負(fù)載均衡中可配置nginx的負(fù)載均衡即upstream項(xiàng)功能,在反向代理管理中可選擇代理目標(biāo)為配置好的負(fù)載均衡。
在證書管理中可添加證書,并進(jìn)行簽發(fā)和續(xù)簽,開啟定時續(xù)簽后,系統(tǒng)會自動續(xù)簽即將過期的證書。
備份文件管理,這里可以看到nginx.cnf的備份歷史版本,nginx出現(xiàn)錯誤時可以選擇回滾到某一個歷史版本。
最終生成conf文件,可在此進(jìn)行進(jìn)一步手動修改,確認(rèn)修改無誤后,可覆蓋本機(jī)conf文件,并進(jìn)行校驗(yàn)和重啟,可以選擇生成單一nginx.conf文件還是按域名將各個配置文件分開放在conf.d下。
遠(yuǎn)程服務(wù)器管理,如果有多臺nginx服務(wù)器,可以都部署上nginxWebUI,然后登錄其中一臺,在遠(yuǎn)程管理中添加其他服務(wù)器的ip和用戶名密碼,就可以在一臺機(jī)器上管理所有的nginx服務(wù)器了。
提供一鍵同步功能,可以將某一臺服務(wù)器的數(shù)據(jù)配置和證書文件同步到其他服務(wù)器中。
本系統(tǒng)提供http接口調(diào)用,只要開 http://xxx.xxx.xxx.xxx:8080/doc.html 即可查看smat-doc接口頁面。
接口調(diào)用需要在header中添加token,其中token的獲取需要在管理員管理中,打開用戶的接口調(diào)用權(quán)限,然后通過用戶名密碼調(diào)用獲取token接口,才能得到token,然后在knife4j的文檔管理中設(shè)置全局token。
jar安裝說明:
注意:本項(xiàng)目需要在root用戶下運(yùn)行系統(tǒng)命令,極容易被黑客利用,請一定修改密碼為復(fù)雜密碼
以Ubuntu操作系統(tǒng)為例:
1 安裝java運(yùn)行環(huán)境和nginx
Ubuntu:
apt install openjdk-8-jdk
sudo apt install nginx
Centos:
yum install java-1.8.0-openjdk
yum install nginx
Windows:
下載JDK安裝包 https://www.oracle.com/java/technologies/downloads/
配置JAVA運(yùn)行環(huán)境
JAVA_HOME : JDK安裝目錄
Path : JDK安裝目錄\bin
重啟電腦
2 下載最新版發(fā)行包jar
有新版本只需要修改路徑中的版本即可。
Linux: wget -O /home/nginxWebUI/nginxWebUI.jar http://file.nginxwebui.cn/nginxWebUI-3.2.8.jar
Windows: 直接使用瀏覽器下載 http://file.nginxwebui.cn/nginxWebUI-3.2.8.jar
3 啟動程序
Linux: nohup java -jar -Dfile.encoding=UTF-8 /home/nginxWebUI/nginxWebUI.jar --server.port=8080 --project.home=/home/nginxWebUI/ > /dev/null &
Windows: java -jar -Dfile.encoding=UTF-8 D:/home/nginxWebUI/nginxWebUI.jar --server.port=8080 --project.home=D:/home/nginxWebUI/
參數(shù)說明(都是非必填):
--server.port 占用端口, 默認(rèn)以8080端口啟動
--project.home 項(xiàng)目配置文件目錄,存放數(shù)據(jù)庫文件,證書文件,日志等, 默認(rèn)為/home/nginxWebUI/
--spring.database.type=mysql 使用其他數(shù)據(jù)庫,不填為使用本地h2,可選mysql
--spring.datasource.url=jdbc:mysql://ip:port/nginxwebui 數(shù)據(jù)庫url
--spring.datasource.username=root 數(shù)據(jù)庫用戶
--spring.datasource.password=pass 數(shù)據(jù)庫密碼
注意Linux命令最后加一個&號, 表示項(xiàng)目后臺運(yùn)行
docker安裝說明
本項(xiàng)目制作了docker鏡像,同時包含nginx和nginxWebUI在內(nèi),一體化管理與運(yùn)行nginx。
1 安裝docker容器環(huán)境
ubuntu:
apt install docker.io
centos:
yum install docker
2 下載鏡像
docker pull cym1102/nginxwebui:latest
3 啟動容器
docker run -itd -v /home/nginxWebUI:/home/nginxWebUI -e BOOT_OPTIONS="--server.port=8080" --privileged=true --net=host cym1102/nginxwebui:latest
注意:
啟動容器時請使用--net=host參數(shù), 直接映射本機(jī)端口, 因?yàn)閮?nèi)部nginx可能使用任意一個端口, 所以必須映射本機(jī)所有端口
容器需要映射路徑/home/nginxWebUI:/home/nginxWebUI, 此路徑下存放項(xiàng)目所有數(shù)據(jù)文件, 包括數(shù)據(jù)庫, nginx配置文件, 日志, 證書等, 升級鏡像時, 此目錄可保證項(xiàng)目數(shù)據(jù)不丟失. 請注意備份
-e BOOT_OPTIONS 參數(shù)可填充java啟動參數(shù), 可以靠此項(xiàng)參數(shù)修改端口號, "--server.port 占用端口", 不填默認(rèn)以8080端口啟動
日志默認(rèn)存放在/home/nginxWebUI/log/nginxWebUI.log
—END—
開源協(xié)議:MulanPSL-1.0
開源地址:https://github.com/cym1102/nginxWebUI
*請認(rèn)真填寫需求信息,我們會在24小時內(nèi)與您取得聯(lián)系。