Merge branch 'opengoofy:develop' into develop

pull/750/head
Gdk666 3 years ago committed by GitHub
commit f3aa0b878b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -0,0 +1,40 @@
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# This workflow will build a Java project with Maven
# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven
on:
push:
branches:
- develop
jobs:
contrib-readme-job:
runs-on: ubuntu-latest
name: A job to automate contrib in readme
steps:
- name: Contribute List
uses: akhilmhdh/contributors-readme-action@v2.3.6
with:
image_size: 50
columns_per_row: 9
committer_email: m7798432@163.com
committer_username: pirme
commit_message: 'Update the list of contributors'
env:
GITHUB_TOKEN: ${{ secrets.ACTION_TOKEN }}

@ -0,0 +1 @@
distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.5.0/apache-maven-3.5.0-bin.zip

@ -38,50 +38,572 @@ Hippo-4J 通过对 JDK 线程池增强,以及扩展三方框架底层线程池
- 容器管理 - Tomcat、Jetty、Undertow 容器线程池运行时查看和线程数变更。 - 容器管理 - Tomcat、Jetty、Undertow 容器线程池运行时查看和线程数变更。
- 中间件适配 - Dubbo、Hystrix、RocketMQ、RabbitMQ 等消费线程池运行时数据查看和线程数变更。 - 中间件适配 - Dubbo、Hystrix、RocketMQ、RabbitMQ 等消费线程池运行时数据查看和线程数变更。
> 开源作者为爱发电不容易,看完有收获,右上角帮忙点个 Star 🤩
## 快速开始 ## 快速开始
对于本地演示目的,请参阅 [Quick start](https://hippo4j.cn/docs/user_docs/user_guide/quick-start) 对于本地演示目的,请参阅 [Quick start](https://hippo4j.cn/docs/user_docs/user_guide/quick-start)
演示环境: http://console.hippo4j.cn/index.html 演示环境: [http://console.hippo4j.cn/index.html](http://console.hippo4j.cn/index.html)
## 联系我 ## 联系我
![](https://user-images.githubusercontent.com/77398366/185774220-c11951f9-e130-4d60-8204-afb5c51d4401.png) ![](https://user-images.githubusercontent.com/77398366/185774220-c11951f9-e130-4d60-8204-afb5c51d4401.png)
扫码添加微信备注hippo4j邀您加入群聊。若图片加载不出来访问 [官网站点](https://hippo4j.cn/docs/user_docs/other/group) 扫码添加微信备注hippo4j邀您加入群聊。若图片加载不出来访问 [官网站点](https://hippo4j.cn/docs/user_docs/other/group)
## 友情链接 ## 友情链接
- [[ Sa-Token ]](https://github.com/dromara/sa-token):一个轻量级 java 权限认证框架,让鉴权变得简单、优雅! - [[ Sa-Token ]](https://github.com/dromara/sa-token):一个轻量级 java 权限认证框架,让鉴权变得简单、优雅!
- [[ HertzBeat ]](https://github.com/dromara/hertzbeat):易用友好的云监控系统, 无需 Agent, 强大自定义监控能力。 - [[ HertzBeat ]](https://github.com/dromara/hertzbeat):易用友好的云监控系统, 无需 Agent, 强大自定义监控能力。
- [[ JavaGuide ]](https://github.com/Snailclimb/JavaGuide):一份涵盖大部分 Java 程序员所需要掌握的核心知识。 - [[ JavaGuide ]](https://github.com/Snailclimb/JavaGuide):一份涵盖大部分 Java 程序员所需要掌握的核心知识。
- [[ toBeBetterJavaer ]](https://github.com/itwanger/toBeBetterJavaer):一份通俗易懂、风趣幽默的 Java 学习指南。 - [[ toBeBetterJavaer ]](https://github.com/itwanger/toBeBetterJavaer):一份通俗易懂、风趣幽默的 Java 学习指南。
## 开发者 ## 贡献者
Hippo-4J 获得的成就属于每一位贡献者!如果有意贡献,请参考 [good first issue](https://github.com/opengoofy/hippo4j/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22) 或者 [good pro issue](https://github.com/opengoofy/hippo4j/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+pro+issue%22)。
<a href="https://github.com/opengoofy/hippo4j/graphs/contributors"><img src="https://opencollective.com/hippo4j/contributors.svg?width=890&button=false" /></a>
## 谁在使用
如果您正在使用这个项目,可以在 [此处](https://github.com/opengoofy/hippo4j/issues/13) 登记您所在的组织或公司,谢谢 感谢所有为项目作出贡献的开发者。如果有意贡献,参考 [good first issue](https://github.com/opengoofy/hippo4j/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22)。
![身边云](https://user-images.githubusercontent.com/77398366/189787832-f51d475c-d758-40f2-9812-997637804e6f.png) <!-- readme: contributors -start -->
![Medbanks](https://user-images.githubusercontent.com/77398366/189787960-16f89af9-a615-4da3-8309-18d0793aed05.png) <table>
![神州数码](https://user-images.githubusercontent.com/77398366/189786973-1a924f41-1558-4b03-acfd-49f279b99ce7.png) <tr>
![payermax](https://user-images.githubusercontent.com/77398366/189787071-ccfa45fa-31c0-4a39-9969-9d20d6948a7b.png) <td align="center">
![轻松到家](https://user-images.githubusercontent.com/77398366/189787144-fb6f7c4a-bdd8-4bdf-8ce1-c1e386c7aecd.png) <a href="https://github.com/itmachen">
![鲁班到家](https://user-images.githubusercontent.com/77398366/189787219-09201124-8ac6-496e-b562-9b4eecc11806.png) <img src="https://avatars.githubusercontent.com/u/77398366?v=4" width="50;" alt="itmachen"/>
![广东天枢新能源科技有限公司](https://user-images.githubusercontent.com/77398366/189787263-d1998874-51ec-42ea-89d8-961cf1c2a557.png) <br />
![FitTime](https://user-images.githubusercontent.com/77398366/189787924-c6f1835c-c81b-403b-a7ec-386c261766a9.png) <sub><b>小马哥</b></sub>
![51社保](https://user-images.githubusercontent.com/77398366/189787481-b9eae343-8310-4333-b385-b68e224d1438.png) </a>
![好货云店](https://user-images.githubusercontent.com/77398366/189787520-7ea68573-2232-4ba5-bedc-94754884c75c.png) </td>
![斗象科技](https://user-images.githubusercontent.com/77398366/189788405-ea93d8f0-3c17-49e0-bd96-8fc259d0eb89.png) <td align="center">
![深圳航天信息有限公司](https://user-images.githubusercontent.com/77398366/189787780-7815f0c0-8478-4403-99ec-27fe07537b99.png) <a href="https://github.com/shining-stars-lk">
![新东方](https://user-images.githubusercontent.com/77398366/189787802-2bb240bd-307f-4e8d-aaa5-ff71e0d46acc.png) <img src="https://avatars.githubusercontent.com/u/40255310?v=4" width="50;" alt="shining-stars-lk"/>
<br />
<sub><b>Lucky 8</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/weihubeats">
<img src="https://avatars.githubusercontent.com/u/42484192?v=4" width="50;" alt="weihubeats"/>
<br />
<sub><b>Weihubeats</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/pirme">
<img src="https://avatars.githubusercontent.com/u/41976977?v=4" width="50;" alt="pirme"/>
<br />
<sub><b>李金来</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/iwangjie">
<img src="https://avatars.githubusercontent.com/u/23075587?v=4" width="50;" alt="iwangjie"/>
<br />
<sub><b>王杰</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/BigXin0109">
<img src="https://avatars.githubusercontent.com/u/24769514?v=4" width="50;" alt="BigXin0109"/>
<br />
<sub><b>BigXin0109</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/shanjianq">
<img src="https://avatars.githubusercontent.com/u/49084314?v=4" width="50;" alt="shanjianq"/>
<br />
<sub><b>Shanjianq</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/xqxyxchy">
<img src="https://avatars.githubusercontent.com/u/21134578?v=4" width="50;" alt="xqxyxchy"/>
<br />
<sub><b>Null</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/Gdk666">
<img src="https://avatars.githubusercontent.com/u/22442067?v=4" width="50;" alt="Gdk666"/>
<br />
<sub><b>Null</b></sub>
</a>
</td></tr>
<tr>
<td align="center">
<a href="https://github.com/pizihao">
<img src="https://avatars.githubusercontent.com/u/48643103?v=4" width="50;" alt="pizihao"/>
<br />
<sub><b>Pizihao</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/maxisvest">
<img src="https://avatars.githubusercontent.com/u/20422618?v=4" width="50;" alt="maxisvest"/>
<br />
<sub><b>Null</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/zhuanghaozhe">
<img src="https://avatars.githubusercontent.com/u/73152769?v=4" width="50;" alt="zhuanghaozhe"/>
<br />
<sub><b>庄昊哲</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/liulinfei121">
<img src="https://avatars.githubusercontent.com/u/57127515?v=4" width="50;" alt="liulinfei121"/>
<br />
<sub><b>Null</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/road2master">
<img src="https://avatars.githubusercontent.com/u/53806703?v=4" width="50;" alt="road2master"/>
<br />
<sub><b>Lijx</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/Atmanuclear">
<img src="https://avatars.githubusercontent.com/u/25747005?v=4" width="50;" alt="Atmanuclear"/>
<br />
<sub><b>Null</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/hippo4j">
<img src="https://avatars.githubusercontent.com/u/93200041?v=4" width="50;" alt="hippo4j"/>
<br />
<sub><b>Hippo4j</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/imyzt">
<img src="https://avatars.githubusercontent.com/u/28680198?v=4" width="50;" alt="imyzt"/>
<br />
<sub><b>杨镇涛</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/Tliutao">
<img src="https://avatars.githubusercontent.com/u/17719583?v=4" width="50;" alt="Tliutao"/>
<br />
<sub><b>Liutao</b></sub>
</a>
</td></tr>
<tr>
<td align="center">
<a href="https://github.com/monsterxxp">
<img src="https://avatars.githubusercontent.com/u/37952446?v=4" width="50;" alt="monsterxxp"/>
<br />
<sub><b>Null</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/voilaf">
<img src="https://avatars.githubusercontent.com/u/16870828?v=4" width="50;" alt="voilaf"/>
<br />
<sub><b>Null</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/gywanghai">
<img src="https://avatars.githubusercontent.com/u/102774648?v=4" width="50;" alt="gywanghai"/>
<br />
<sub><b>二师兄</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/skyemin">
<img src="https://avatars.githubusercontent.com/u/38172444?v=4" width="50;" alt="skyemin"/>
<br />
<sub><b>Null</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/Redick01">
<img src="https://avatars.githubusercontent.com/u/15903214?v=4" width="50;" alt="Redick01"/>
<br />
<sub><b>Redick Liu</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/xiaochengxuyuan">
<img src="https://avatars.githubusercontent.com/u/9032006?v=4" width="50;" alt="xiaochengxuyuan"/>
<br />
<sub><b>Sean Wu</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/HKMV">
<img src="https://avatars.githubusercontent.com/u/26456469?v=4" width="50;" alt="HKMV"/>
<br />
<sub><b>Serenity</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/gewuwo">
<img src="https://avatars.githubusercontent.com/u/97213587?v=4" width="50;" alt="gewuwo"/>
<br />
<sub><b>格悟沃</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/hushtian">
<img src="https://avatars.githubusercontent.com/u/55479601?v=4" width="50;" alt="hushtian"/>
<br />
<sub><b>Null</b></sub>
</a>
</td></tr>
<tr>
<td align="center">
<a href="https://github.com/jinlingmei">
<img src="https://avatars.githubusercontent.com/u/24669082?v=4" width="50;" alt="jinlingmei"/>
<br />
<sub><b>Null</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/linlinjie">
<img src="https://avatars.githubusercontent.com/u/22275940?v=4" width="50;" alt="linlinjie"/>
<br />
<sub><b>Null</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/selectbook">
<img src="https://avatars.githubusercontent.com/u/8454350?v=4" width="50;" alt="selectbook"/>
<br />
<sub><b>Leping Huang</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/soulmz">
<img src="https://avatars.githubusercontent.com/u/10662992?v=4" width="50;" alt="soulmz"/>
<br />
<sub><b>Soulzz</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/tomsun28">
<img src="https://avatars.githubusercontent.com/u/24788200?v=4" width="50;" alt="tomsun28"/>
<br />
<sub><b>Tomsun28</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/backbay2-yzg">
<img src="https://avatars.githubusercontent.com/u/64394486?v=4" width="50;" alt="backbay2-yzg"/>
<br />
<sub><b>游祖光</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/puppet4">
<img src="https://avatars.githubusercontent.com/u/28887178?v=4" width="50;" alt="puppet4"/>
<br />
<sub><b>Tudo</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/2EXP">
<img src="https://avatars.githubusercontent.com/u/26007713?v=4" width="50;" alt="2EXP"/>
<br />
<sub><b>Null</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/onesimplecoder">
<img src="https://avatars.githubusercontent.com/u/30288465?v=4" width="50;" alt="onesimplecoder"/>
<br />
<sub><b>Alic</b></sub>
</a>
</td></tr>
<tr>
<td align="center">
<a href="https://github.com/CalebZYC">
<img src="https://avatars.githubusercontent.com/u/42887532?v=4" width="50;" alt="CalebZYC"/>
<br />
<sub><b>Null</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/Hibernate5666">
<img src="https://avatars.githubusercontent.com/u/30147527?v=4" width="50;" alt="Hibernate5666"/>
<br />
<sub><b>Cheng Xihong</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/smartdj">
<img src="https://avatars.githubusercontent.com/u/3272679?v=4" width="50;" alt="smartdj"/>
<br />
<sub><b>DJ</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/dmego">
<img src="https://avatars.githubusercontent.com/u/22118976?v=4" width="50;" alt="dmego"/>
<br />
<sub><b>Dmego</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/dousp">
<img src="https://avatars.githubusercontent.com/u/5936499?v=4" width="50;" alt="dousp"/>
<br />
<sub><b>Douspeng</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/hl1248">
<img src="https://avatars.githubusercontent.com/u/70790953?v=4" width="50;" alt="hl1248"/>
<br />
<sub><b>Lucas</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/gentlelynn">
<img src="https://avatars.githubusercontent.com/u/19168453?v=4" width="50;" alt="gentlelynn"/>
<br />
<sub><b>Lynn</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/sanliangitch">
<img src="https://avatars.githubusercontent.com/u/48200100?v=4" width="50;" alt="sanliangitch"/>
<br />
<sub><b>WuLang</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/alexhaoxuan">
<img src="https://avatars.githubusercontent.com/u/46749051?v=4" width="50;" alt="alexhaoxuan"/>
<br />
<sub><b>Alexli</b></sub>
</a>
</td></tr>
<tr>
<td align="center">
<a href="https://github.com/baymax55">
<img src="https://avatars.githubusercontent.com/u/35788491?v=4" width="50;" alt="baymax55"/>
<br />
<sub><b>Baymax55</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/qizhongju">
<img src="https://avatars.githubusercontent.com/u/19883548?v=4" width="50;" alt="qizhongju"/>
<br />
<sub><b>Bug搬运工</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/san4j">
<img src="https://avatars.githubusercontent.com/u/40364355?v=4" width="50;" alt="san4j"/>
<br />
<sub><b>San4j</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/zhenyed">
<img src="https://avatars.githubusercontent.com/u/26167590?v=4" width="50;" alt="zhenyed"/>
<br />
<sub><b>Zhenye</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/dongming0920">
<img src="https://avatars.githubusercontent.com/u/57832778?v=4" width="50;" alt="dongming0920"/>
<br />
<sub><b>Null</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/f497196689">
<img src="https://avatars.githubusercontent.com/u/15325854?v=4" width="50;" alt="f497196689"/>
<br />
<sub><b>Fengjing</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/Snailclimb">
<img src="https://avatars.githubusercontent.com/u/29880145?v=4" width="50;" alt="Snailclimb"/>
<br />
<sub><b>Guide</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/hbw1994">
<img src="https://avatars.githubusercontent.com/u/22744421?v=4" width="50;" alt="hbw1994"/>
<br />
<sub><b>Null</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/hncboy">
<img src="https://avatars.githubusercontent.com/u/27755574?v=4" width="50;" alt="hncboy"/>
<br />
<sub><b>Null</b></sub>
</a>
</td></tr>
<tr>
<td align="center">
<a href="https://github.com/stronglong">
<img src="https://avatars.githubusercontent.com/u/15846157?v=4" width="50;" alt="stronglong"/>
<br />
<sub><b>Itermis</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/janey668">
<img src="https://avatars.githubusercontent.com/u/99872936?v=4" width="50;" alt="janey668"/>
<br />
<sub><b>Null</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/jialei-jack">
<img src="https://avatars.githubusercontent.com/u/93201205?v=4" width="50;" alt="jialei-jack"/>
<br />
<sub><b>Jialei-jack</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/klsq94">
<img src="https://avatars.githubusercontent.com/u/16208392?v=4" width="50;" alt="klsq94"/>
<br />
<sub><b>Hui Cao</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/kongyanbo-cx">
<img src="https://avatars.githubusercontent.com/u/58963923?v=4" width="50;" alt="kongyanbo-cx"/>
<br />
<sub><b>Null</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/lishiyu">
<img src="https://avatars.githubusercontent.com/u/36871640?v=4" width="50;" alt="lishiyu"/>
<br />
<sub><b>Null</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/Nhxz">
<img src="https://avatars.githubusercontent.com/u/72447160?v=4" width="50;" alt="Nhxz"/>
<br />
<sub><b>Nhxz</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/op-lht">
<img src="https://avatars.githubusercontent.com/u/34021816?v=4" width="50;" alt="op-lht"/>
<br />
<sub><b>Op-lht</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/wangjie-github">
<img src="https://avatars.githubusercontent.com/u/35762878?v=4" width="50;" alt="wangjie-github"/>
<br />
<sub><b>Wangjie</b></sub>
</a>
</td></tr>
<tr>
<td align="center">
<a href="https://github.com/wangyi123456">
<img src="https://avatars.githubusercontent.com/u/25248959?v=4" width="50;" alt="wangyi123456"/>
<br />
<sub><b>Null</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/Williamren97">
<img src="https://avatars.githubusercontent.com/u/43086401?v=4" width="50;" alt="Williamren97"/>
<br />
<sub><b>William Ren</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/wzw8795">
<img src="https://avatars.githubusercontent.com/u/90670917?v=4" width="50;" alt="wzw8795"/>
<br />
<sub><b>Null</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/huaxianchao">
<img src="https://avatars.githubusercontent.com/u/50727527?v=4" width="50;" alt="huaxianchao"/>
<br />
<sub><b>Null</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/yangzhiw">
<img src="https://avatars.githubusercontent.com/u/13634974?v=4" width="50;" alt="yangzhiw"/>
<br />
<sub><b>Opentanent</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/yhc777">
<img src="https://avatars.githubusercontent.com/u/71164753?v=4" width="50;" alt="yhc777"/>
<br />
<sub><b>Null</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/zhaiweij">
<img src="https://avatars.githubusercontent.com/u/10173248?v=4" width="50;" alt="zhaiweij"/>
<br />
<sub><b>Zhaiweij</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/zhaojinchao95">
<img src="https://avatars.githubusercontent.com/u/33742097?v=4" width="50;" alt="zhaojinchao95"/>
<br />
<sub><b>Zhaojinchao</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/zj1997">
<img src="https://avatars.githubusercontent.com/u/31212787?v=4" width="50;" alt="zj1997"/>
<br />
<sub><b>Null</b></sub>
</a>
</td></tr>
<tr>
<td align="center">
<a href="https://github.com/li-xiao-shuang">
<img src="https://avatars.githubusercontent.com/u/34903552?v=4" width="50;" alt="li-xiao-shuang"/>
<br />
<sub><b>李晓双 Li Xiao Shuang</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/oreoft">
<img src="https://avatars.githubusercontent.com/u/51789848?v=4" width="50;" alt="oreoft"/>
<br />
<sub><b>没有气的汽水</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/wo883721">
<img src="https://avatars.githubusercontent.com/u/10241323?v=4" width="50;" alt="wo883721"/>
<br />
<sub><b>Xinhao</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/Createsequence">
<img src="https://avatars.githubusercontent.com/u/49221670?v=4" width="50;" alt="Createsequence"/>
<br />
<sub><b>黄成兴</b></sub>
</a>
</td></tr>
</table>
<!-- readme: contributors -end -->

@ -47,4 +47,11 @@ sidebar_position: 2
<td align="center" ><a href="https://blog.csdn.net/qq_34741165">OnlyBig</a></td> <td align="center" ><a href="https://blog.csdn.net/qq_34741165">OnlyBig</a></td>
<td align="center" >1064730540@qq.com</td> <td align="center" >1064730540@qq.com</td>
</tr> </tr>
<tr>
<td align="center"><a href="https://github.com/pizihao"><img src="https://avatars.githubusercontent.com/u/48643103?v=4?s=64" width="64px;"/></a></td>
<td align="center">刘文浩</td>
<td align="center" ><a href="https://github.com/pizihao">pizihao</a></td>
<td align="center" ><a href="https://www.yuque.com/chenghu-08dla/pizig1">pizihao</a></td>
<td align="center" >hao3073liu@163.com</td>
</tr>
</table> </table>

@ -2,7 +2,7 @@
sidebar_position: 1 sidebar_position: 1
--- ---
# hippo4j server 部署 # 源码包部署
[RELEASE](https://github.com/opengoofy/hippo4j/releases) 页面下载对应版本并进行解压。 [RELEASE](https://github.com/opengoofy/hippo4j/releases) 页面下载对应版本并进行解压。

@ -2,11 +2,33 @@
sidebar_position: 2 sidebar_position: 2
--- ---
# hippo4j server docker 构建 # Docker 部署
## 镜像启动
Docker 镜像默认使用内置 H2 数据库,数据持久化到 Docker 容器存储卷中。
```shell
docker run -d -p 6691:6691 --name hippo4j-server hippo4j/hippo4j-server
```
或者,底层存储数据库切换为 MySQL。`DATASOURCE_HOST` 需要切换为本地 IP不能使用 `127.0.0.1``localhost`
```shell
docker run -d -p 6691:6691 --name hippo4j-server \
-e DATASOURCE_HOST=xxx.xxx.xxx.xxx \
-e DATASOURCE_PORT=3306 \
-e DATASOURCE_DB=hippo4j_manager \
-e DATASOURCE_USERNAME=root \
-e DATASOURCE_PASSWORD=root \
hippo4j/hippo4j-server
```
访问 Server 控制台,路径 `http://localhost:6691/index.html` 默认用户名密码admin / 123456
## 镜像构建 ## 镜像构建
可以通过以下命令快速构建 Hippo4J Server 如果想要自定义镜像,可以通过以下命令快速构建 Hippo4J Server
方式一: 方式一:
@ -18,39 +40,10 @@ docker build -t hippo4j/hippo4j-server ../hippo4j-server
``` ```
方式二: 方式二:
通过 `maven docker plugin` 通过 `maven docker plugin`
```shell ```shell
# 进入到 hippo4j-server 工程路径下 # 进入到 hippo4j-server 工程路径下
mvn clean package -DskipTests -Dskip.spotless.apply=true docker:build mvn clean package -DskipTests -Dskip.spotless.apply=true docker:build
``` ```
## 镜像启动
- 下载镜像
```shell
docker pull hippo4j/hippo4j-server
```
- 创建容器并运行
```shell
docker run -d -p 6691:6691 --name hippo4j-server hippo4j/hippo4j-server
# 如需个性化参数指定,请参考下述命令
/**
* 暂时只暴露以下参数
*
* MYSQL_HOST、MYSQL_PORT、MYSQL_DB、MYSQL_USERNAME、MYSQL_PASSWORD
* MYSQL_HOST 需要使用本地 IP不能使用 127.0.0.1
*/
docker run -d -p 6691:6691 --name hippo4j-server \
-e MYSQL_HOST=xxx.xxx.x.x \
-e MYSQL_PORT=3306 \
-e MYSQL_DB=hippo4j_manager \
-e MYSQL_USERNAME=root \
-e MYSQL_PASSWORD=root \
hippo4j/hippo4j-server
```

@ -6,18 +6,10 @@ sidebar_position: 3
## 服务启动 ## 服务启动
MySQL 数据库导入 [Hippo4J 初始化 SQL 语句](https://github.com/longtai-cn/hippo4j/blob/develop/hippo4j-server/conf/hippo4j_manager.sql)。 使用 Docker 运行服务端,默认使用内置 H2 数据库,数据持久化到 Docker 容器存储卷中。
使用 Docker 运行服务端,可以灵活定制相关参数。`MYSQL_HOST` 需要使用本地 IP不能使用 `127.0.0.1`
```shell ```shell
docker run -d -p 6691:6691 --name hippo4j-server \ docker run -d -p 6691:6691 --name hippo4j-server hippo4j/hippo4j-server
-e MYSQL_HOST=xxx.xxx.x.x \
-e MYSQL_PORT=3306 \
-e MYSQL_DB=hippo4j_manager \
-e MYSQL_USERNAME=root \
-e MYSQL_PASSWORD=root \
hippo4j/hippo4j-server
``` ```
> 如果没有 Docker可以使用源码编译的方式启动 [Hippo4J-Server](https://github.com/longtai-cn/hippo4j/tree/develop/hippo4j-server) 模块下 ServerApplication 应用类。 > 如果没有 Docker可以使用源码编译的方式启动 [Hippo4J-Server](https://github.com/longtai-cn/hippo4j/tree/develop/hippo4j-server) 模块下 ServerApplication 应用类。

@ -94,13 +94,15 @@ public class DubboThreadPoolAdapter implements ThreadPoolAdapter, ApplicationLis
@Override @Override
public void onApplicationEvent(ApplicationStartedEvent event) { public void onApplicationEvent(ApplicationStartedEvent event) {
boolean is2xVersion = false; boolean isLegacyVersion = false;
String poolKey = ExecutorService.class.getName(); String poolKey = ExecutorService.class.getName();
if (Version.getIntVersion(Version.getVersion()) < 3000000) { // Since 2.7.5, Dubbo has changed the way thread pools are used
is2xVersion = true; // fixed https://github.com/opengoofy/hippo4j/issues/708
if (Version.getIntVersion(Version.getVersion()) < 2070500) {
isLegacyVersion = true;
} }
try { try {
if (is2xVersion) { if (isLegacyVersion) {
DataStore dataStore = ExtensionLoader.getExtensionLoader(DataStore.class).getDefaultExtension(); DataStore dataStore = ExtensionLoader.getExtensionLoader(DataStore.class).getDefaultExtension();
Map<String, Object> executors = dataStore.get(poolKey); Map<String, Object> executors = dataStore.get(poolKey);
executors.forEach((key, value) -> DUBBO_PROTOCOL_EXECUTOR.put(key, (ThreadPoolExecutor) value)); executors.forEach((key, value) -> DUBBO_PROTOCOL_EXECUTOR.put(key, (ThreadPoolExecutor) value));
@ -112,7 +114,7 @@ public class DubboThreadPoolAdapter implements ThreadPoolAdapter, ApplicationLis
ConcurrentMap<Integer, ExecutorService> executorServiceMap = data.get(poolKey); ConcurrentMap<Integer, ExecutorService> executorServiceMap = data.get(poolKey);
executorServiceMap.forEach((key, value) -> DUBBO_PROTOCOL_EXECUTOR.put(String.valueOf(key), (ThreadPoolExecutor) value)); executorServiceMap.forEach((key, value) -> DUBBO_PROTOCOL_EXECUTOR.put(String.valueOf(key), (ThreadPoolExecutor) value));
} catch (Exception ex) { } catch (Exception ex) {
log.error("Failed to get Dubbo {}.X protocol thread pool", is2xVersion ? "2" : "3", ex); log.error("Failed to get Dubbo {}.X protocol thread pool", isLegacyVersion ? "2" : "3", ex);
} }
} }
} }

@ -0,0 +1,97 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.hippo4j.adapter.web;
import cn.hippo4j.common.config.ApplicationContextHolder;
import cn.hippo4j.common.model.WebIpAndPortInfo;
import cn.hippo4j.common.toolkit.Assert;
import cn.hippo4j.common.toolkit.StringUtil;
import cn.hippo4j.core.toolkit.inet.InetUtils;
import org.springframework.boot.web.server.WebServer;
import java.util.Arrays;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicReference;
/**
* Ip and port Holder
*/
public class WebIpAndPortHolder {
/**
* Application ip and application post
*/
protected static AtomicReference<WebIpAndPortInfo> webIpAndPort = new AtomicReference<>();
public static final String ALL = "*";
protected static final String SEPARATOR = ",";
private WebIpAndPortHolder() {
}
protected static void initIpAndPort() {
webIpAndPort.compareAndSet(null, getWebIpAndPortInfo());
}
private static WebIpAndPortInfo getWebIpAndPortInfo() {
InetUtils inetUtils = ApplicationContextHolder.getBean(InetUtils.class);
InetUtils.HostInfo loopBackHostInfo = inetUtils.findFirstNonLoopBackHostInfo();
Assert.notNull(loopBackHostInfo, "Unable to get the application IP address");
String ip = loopBackHostInfo.getIpAddress();
WebThreadPoolHandlerChoose webThreadPoolHandlerChoose = ApplicationContextHolder.getBean(WebThreadPoolHandlerChoose.class);
WebThreadPoolService webThreadPoolService = webThreadPoolHandlerChoose.choose();
// When get the port at startup, can get the message: "port xxx was already in use" or use two ports
WebServer webServer = webThreadPoolService.getWebServer();
String port = String.valueOf(webServer.getPort());
return new WebIpAndPortInfo(ip, port);
}
/**
* get WebIpAndPortInfo, If it is null, initialize it
*
* @return WebIpAndPortInfo
*/
public static WebIpAndPortInfo getWebIpAndPort() {
if (webIpAndPort.get() == null) {
initIpAndPort();
}
return WebIpAndPortHolder.webIpAndPort.get();
}
/**
* Check the new properties and instance IP and port
*
* @param nodes nodes in properties
* @return Whether it meets the conditions
*/
public static boolean check(String nodes) {
WebIpAndPortInfo webIpAndPort = WebIpAndPortHolder.getWebIpAndPort();
if (StringUtil.isEmpty(nodes) || ALL.equals(nodes)) {
return true;
}
String[] splitNodes = nodes.split(SEPARATOR);
return Arrays.stream(splitNodes)
.distinct()
.map(WebIpAndPortInfo::build)
.filter(Objects::nonNull)
.anyMatch(each -> each.check(webIpAndPort.getIpSegment(), webIpAndPort.getPort()));
}
}

@ -0,0 +1,21 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.hippo4j.auth.secuity;
public final class JwtTokenManagerTest {
}

@ -0,0 +1,21 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.hippo4j.auth.toolkit;
public final class JwtTokenUtilTest {
}

@ -0,0 +1,51 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.hippo4j.common.api;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
/**
* when init thread-pool dynamic refresh.
*/
public interface ThreadPoolInitRefresh extends ApplicationRunner {
/**
* Initializes the thread pool after system startup
*
* @param context new properties
*/
void initRefresh(String context);
/**
* get from the Configuration center
*
* @return new properties
* @throws Exception exception
*/
String getProperties() throws Exception;
@Override
default void run(ApplicationArguments args) throws Exception {
String properties = getProperties();
if (properties == null) {
return;
}
initRefresh(properties);
}
}

@ -41,7 +41,7 @@ public class GroupKey {
for (int i = 1; i < params.length - 1; i++) { for (int i = 1; i < params.length - 1; i++) {
groupKey.append(params[i]).append(GROUP_KEY_DELIMITER); groupKey.append(params[i]).append(GROUP_KEY_DELIMITER);
} }
groupKey.append(params[params.length]); groupKey.append(params[params.length - 1]);
return groupKey.toString(); return groupKey.toString();
} }

@ -0,0 +1,21 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.hippo4j.common.executor;
public final class ExecutorFactoryTest {
}

@ -0,0 +1,21 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.hippo4j.common.executor;
public final class ThreadPoolManagerTest {
}

@ -0,0 +1,35 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.hippo4j.common.function;
import cn.hippo4j.common.toolkit.Assert;
import java.math.BigDecimal;
import org.junit.Test;
public final class MatcherFunctionTest {
public static <T> boolean matchTest(Matcher<T> matcher, T value) {
return matcher.match(value);
}
@Test
public void assertMatch() {
Assert.isTrue(matchTest(Boolean.TRUE::equals, true));
Assert.isTrue(matchTest(BigDecimal.ZERO::equals, BigDecimal.ZERO));
}
}

@ -0,0 +1,21 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.hippo4j.common.function;
public final class NoArgsConsumerTest {
}

@ -0,0 +1,21 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.hippo4j.common.spi;
public final class DynamicThreadPoolServiceLoaderTest {
}

@ -0,0 +1,21 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.hippo4j.common.toolkit;
public final class AssertTest {
}

@ -0,0 +1,83 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.hippo4j.common.toolkit;
import org.checkerframework.checker.units.qual.A;
import org.junit.Test;
import java.util.Arrays;
import java.util.List;
import static org.junit.Assert.*;
public class GroupKeyTest {
@Test
public void getKey() {
String dataId = "dataId";
String group = "group";
String datumStr = "datumStr";
String expected = "dataId+group+datumStr";
String key = GroupKey.getKey(dataId, group, datumStr);
Assert.isTrue(key.equals(expected));
}
@Test
public void testGetKey() {
String dataId = "dataId";
String group = "group";
String expected = "dataId+group";
String key = GroupKey.getKey(dataId, group);
Assert.isTrue(key.equals(expected));
}
@Test
public void testGetKey1() {
String[] strings = {"dataId", "group", "datumStr"};
String expected = "dataId+group+datumStr";
String key = GroupKey.getKey(strings);
Assert.isTrue(key.equals(expected));
}
@Test
public void getKeyTenant() {
String dataId = "dataId";
String group = "group";
String datumStr = "datumStr";
String expected = "dataId+group+datumStr";
String keyTenant = GroupKey.getKeyTenant(dataId, group, datumStr);
Assert.isTrue(keyTenant.equals(expected));
}
@Test
public void parseKey() {
String groupKey = "prescription+dynamic-threadpool-example+message-consume+12";
String[] strings = GroupKey.parseKey(groupKey);
Assert.isTrue(strings.length == 4);
}
@Test
public void urlEncode() {
String str = "hello+World%";
String expected = "hello%2BWorld%25";
StringBuilder stringBuilder = new StringBuilder();
GroupKey.urlEncode(str, stringBuilder);
Assert.isTrue(stringBuilder.toString().contains(expected));
}
}

@ -0,0 +1,21 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.hippo4j.common.web;
public final class ResultsTest {
}

@ -11,6 +11,7 @@
<properties> <properties>
<maven.deploy.skip>true</maven.deploy.skip> <maven.deploy.skip>true</maven.deploy.skip>
<h2.version>2.1.214</h2.version>
</properties> </properties>
<dependencies> <dependencies>
@ -38,6 +39,7 @@
<dependency> <dependency>
<groupId>com.h2database</groupId> <groupId>com.h2database</groupId>
<artifactId>h2</artifactId> <artifactId>h2</artifactId>
<version>${h2.version}</version>
<scope>runtime</scope> <scope>runtime</scope>
</dependency> </dependency>

@ -61,7 +61,7 @@ public class ThreadPoolServiceImpl implements ThreadPoolService {
.eq(!StringUtils.isBlank(reqDTO.getTenantId()), ConfigAllInfo::getTenantId, reqDTO.getTenantId()) .eq(!StringUtils.isBlank(reqDTO.getTenantId()), ConfigAllInfo::getTenantId, reqDTO.getTenantId())
.eq(!StringUtils.isBlank(reqDTO.getItemId()), ConfigAllInfo::getItemId, reqDTO.getItemId()) .eq(!StringUtils.isBlank(reqDTO.getItemId()), ConfigAllInfo::getItemId, reqDTO.getItemId())
.eq(!StringUtils.isBlank(reqDTO.getTpId()), ConfigAllInfo::getTpId, reqDTO.getTpId()) .eq(!StringUtils.isBlank(reqDTO.getTpId()), ConfigAllInfo::getTpId, reqDTO.getTpId())
.eq(ConfigAllInfo::getDelFlag, DelEnum.NORMAL) .eq(ConfigAllInfo::getDelFlag, DelEnum.NORMAL.getIntCode())
.orderByDesc(reqDTO.getDesc() != null, ConfigAllInfo::getGmtCreate); .orderByDesc(reqDTO.getDesc() != null, ConfigAllInfo::getGmtCreate);
return configInfoMapper.selectPage(reqDTO, wrapper).convert(each -> BeanUtil.convert(each, ThreadPoolRespDTO.class)); return configInfoMapper.selectPage(reqDTO, wrapper).convert(each -> BeanUtil.convert(each, ThreadPoolRespDTO.class));
} }

@ -17,8 +17,121 @@
package cn.hippo4j.config.toolkit; package cn.hippo4j.config.toolkit;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import cn.hippo4j.common.toolkit.Assert;
import org.junit.Test;
/** /**
* SimpleReadWriteLock Test * SimpleReadWriteLock Test
*/ */
public class SimpleReadWriteLockTest { public class SimpleReadWriteLockTest {
@Test
public void singleTryReadLockTest() {
SimpleReadWriteLock simpleReadWriteLock = new SimpleReadWriteLock();
boolean result = simpleReadWriteLock.tryReadLock();
Assert.isTrue(result);
}
@Test
public void multiTryReadLockTest() {
SimpleReadWriteLock simpleReadWriteLock = new SimpleReadWriteLock();
simpleReadWriteLock.tryReadLock();
boolean result = simpleReadWriteLock.tryReadLock();
Assert.isTrue(result);
}
@Test
public void singleTryWriteLockTest() {
SimpleReadWriteLock simpleReadWriteLock = new SimpleReadWriteLock();
boolean result = simpleReadWriteLock.tryWriteLock();
Assert.isTrue(result);
}
@Test
public void multiTryWriteLockTest() {
SimpleReadWriteLock simpleReadWriteLock = new SimpleReadWriteLock();
simpleReadWriteLock.tryWriteLock();
boolean result = simpleReadWriteLock.tryWriteLock();
Assert.isTrue(!result);
}
@Test
public void tryReadWriteLockTest() {
SimpleReadWriteLock simpleReadWriteLock = new SimpleReadWriteLock();
simpleReadWriteLock.tryReadLock();
boolean result = simpleReadWriteLock.tryWriteLock();
Assert.isTrue(!result);
}
@Test
public void tryWriteReadLockTest() {
SimpleReadWriteLock simpleReadWriteLock = new SimpleReadWriteLock();
simpleReadWriteLock.tryWriteLock();
boolean result = simpleReadWriteLock.tryReadLock();
Assert.isTrue(!result);
}
@Test
public void releaseReadLockTest() {
SimpleReadWriteLock simpleReadWriteLock = new SimpleReadWriteLock();
simpleReadWriteLock.tryReadLock();
simpleReadWriteLock.releaseReadLock();
boolean result = simpleReadWriteLock.tryWriteLock();
Assert.isTrue(result);
}
@Test
public void releaseWriteLockTest() {
SimpleReadWriteLock simpleReadWriteLock = new SimpleReadWriteLock();
simpleReadWriteLock.tryWriteLock();
simpleReadWriteLock.releaseWriteLock();
boolean result = simpleReadWriteLock.tryReadLock();
Assert.isTrue(result);
}
@Test
public void multiThreadTryWriteLockTest() throws Exception {
SimpleReadWriteLock simpleReadWriteLock = new SimpleReadWriteLock();
CountDownLatch countDownLatch = new CountDownLatch(2);
new Thread(() -> {
try {
TimeUnit.SECONDS.sleep(1);
while (true) {
if (simpleReadWriteLock.tryWriteLock()) {
System.out.println(Thread.currentThread() + " -1 get write lock success");
TimeUnit.SECONDS.sleep(5);
System.out.println(Thread.currentThread() + " -1 execute done");
simpleReadWriteLock.releaseWriteLock();
countDownLatch.countDown();
break;
}
}
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}).start();
new Thread(() -> {
try {
TimeUnit.SECONDS.sleep(2);
while (true) {
if (simpleReadWriteLock.tryWriteLock()) {
System.out.println(Thread.currentThread() + " -2 get write lock success");
TimeUnit.SECONDS.sleep(1);
System.out.println(Thread.currentThread() + " -2 execute done");
countDownLatch.countDown();
break;
}
}
} catch (InterruptedException e) {
throw new RuntimeException(e);
} finally {
simpleReadWriteLock.releaseWriteLock();
}
}).start();
countDownLatch.await();
Assert.isTrue(simpleReadWriteLock.tryWriteLock());
}
} }

@ -17,12 +17,6 @@
package cn.hippo4j.console.service.impl; package cn.hippo4j.console.service.impl;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import cn.hippo4j.common.enums.DelEnum; import cn.hippo4j.common.enums.DelEnum;
import cn.hippo4j.common.model.InstanceInfo; import cn.hippo4j.common.model.InstanceInfo;
import cn.hippo4j.common.toolkit.GroupKey; import cn.hippo4j.common.toolkit.GroupKey;
@ -30,17 +24,9 @@ import cn.hippo4j.config.mapper.ConfigInfoMapper;
import cn.hippo4j.config.mapper.HisRunDataMapper; import cn.hippo4j.config.mapper.HisRunDataMapper;
import cn.hippo4j.config.mapper.ItemInfoMapper; import cn.hippo4j.config.mapper.ItemInfoMapper;
import cn.hippo4j.config.mapper.TenantInfoMapper; import cn.hippo4j.config.mapper.TenantInfoMapper;
import cn.hippo4j.config.model.CacheItem; import cn.hippo4j.config.model.*;
import cn.hippo4j.config.model.ConfigAllInfo;
import cn.hippo4j.config.model.ConfigInfoBase;
import cn.hippo4j.config.model.ItemInfo;
import cn.hippo4j.config.model.TenantInfo;
import cn.hippo4j.config.service.ConfigCacheService; import cn.hippo4j.config.service.ConfigCacheService;
import cn.hippo4j.console.model.ChartInfo; import cn.hippo4j.console.model.*;
import cn.hippo4j.console.model.LineChartInfo;
import cn.hippo4j.console.model.PieChartInfo;
import cn.hippo4j.console.model.RankingChart;
import cn.hippo4j.console.model.TenantChart;
import cn.hippo4j.console.service.DashboardService; import cn.hippo4j.console.service.DashboardService;
import cn.hippo4j.discovery.core.BaseInstanceRegistry; import cn.hippo4j.discovery.core.BaseInstanceRegistry;
import cn.hippo4j.discovery.core.Lease; import cn.hippo4j.discovery.core.Lease;
@ -52,9 +38,14 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import static cn.hippo4j.common.toolkit.ContentUtil.getGroupKey; import static cn.hippo4j.common.toolkit.ContentUtil.getGroupKey;
/** /**
@ -76,9 +67,9 @@ public class DashboardServiceImpl implements DashboardService {
@Override @Override
public ChartInfo getChartInfo() { public ChartInfo getChartInfo() {
Integer tenantCount = tenantInfoMapper.selectCount(Wrappers.lambdaQuery(TenantInfo.class).eq(TenantInfo::getDelFlag, DelEnum.NORMAL.getCode())); Integer tenantCount = tenantInfoMapper.selectCount(Wrappers.lambdaQuery(TenantInfo.class).eq(TenantInfo::getDelFlag, DelEnum.NORMAL.getIntCode()));
Integer itemCount = itemInfoMapper.selectCount(Wrappers.lambdaQuery(ItemInfo.class).eq(ItemInfo::getDelFlag, DelEnum.NORMAL.getIntCode())); Integer itemCount = itemInfoMapper.selectCount(Wrappers.lambdaQuery(ItemInfo.class).eq(ItemInfo::getDelFlag, DelEnum.NORMAL.getIntCode()));
Integer threadPoolCount = configInfoMapper.selectCount(Wrappers.lambdaQuery(ConfigAllInfo.class).eq(ConfigAllInfo::getDelFlag, DelEnum.NORMAL.getCode())); Integer threadPoolCount = configInfoMapper.selectCount(Wrappers.lambdaQuery(ConfigAllInfo.class).eq(ConfigAllInfo::getDelFlag, DelEnum.NORMAL.getIntCode()));
ChartInfo chartInfo = new ChartInfo(); ChartInfo chartInfo = new ChartInfo();
chartInfo.setTenantCount(tenantCount) chartInfo.setTenantCount(tenantCount)
.setItemCount(itemCount) .setItemCount(itemCount)
@ -111,16 +102,16 @@ public class DashboardServiceImpl implements DashboardService {
@Override @Override
public TenantChart getTenantChart() { public TenantChart getTenantChart() {
List<Map<String, Object>> tenantChartList = Lists.newArrayList(); List<Map<String, Object>> tenantChartList = Lists.newArrayList();
List<TenantInfo> tenantInfos = tenantInfoMapper.selectList(Wrappers.lambdaQuery(TenantInfo.class).eq(TenantInfo::getDelFlag, DelEnum.NORMAL)); List<TenantInfo> tenantInfos = tenantInfoMapper.selectList(Wrappers.lambdaQuery(TenantInfo.class).eq(TenantInfo::getDelFlag, DelEnum.NORMAL.getIntCode()));
for (TenantInfo tenant : tenantInfos) { for (TenantInfo tenant : tenantInfos) {
int tenantThreadPoolNum = 0; int tenantThreadPoolNum = 0;
LambdaQueryWrapper<ItemInfo> itemQueryWrapper = LambdaQueryWrapper<ItemInfo> itemQueryWrapper =
Wrappers.lambdaQuery(ItemInfo.class).eq(ItemInfo::getTenantId, tenant.getTenantId()).eq(ItemInfo::getDelFlag, DelEnum.NORMAL).select(ItemInfo::getItemId); Wrappers.lambdaQuery(ItemInfo.class).eq(ItemInfo::getTenantId, tenant.getTenantId()).eq(ItemInfo::getDelFlag, DelEnum.NORMAL.getIntCode()).select(ItemInfo::getItemId);
List<ItemInfo> itemInfos = itemInfoMapper.selectList(itemQueryWrapper); List<ItemInfo> itemInfos = itemInfoMapper.selectList(itemQueryWrapper);
for (ItemInfo item : itemInfos) { for (ItemInfo item : itemInfos) {
LambdaQueryWrapper<ConfigAllInfo> threadPoolQueryWrapper = Wrappers.lambdaQuery(ConfigAllInfo.class) LambdaQueryWrapper<ConfigAllInfo> threadPoolQueryWrapper = Wrappers.lambdaQuery(ConfigAllInfo.class)
.eq(ConfigInfoBase::getItemId, item.getItemId()) .eq(ConfigInfoBase::getItemId, item.getItemId())
.eq(ConfigAllInfo::getDelFlag, DelEnum.NORMAL); .eq(ConfigAllInfo::getDelFlag, DelEnum.NORMAL.getIntCode());
Integer threadPoolCount = configInfoMapper.selectCount(threadPoolQueryWrapper); Integer threadPoolCount = configInfoMapper.selectCount(threadPoolQueryWrapper);
tenantThreadPoolNum += threadPoolCount; tenantThreadPoolNum += threadPoolCount;
} }
@ -136,13 +127,13 @@ public class DashboardServiceImpl implements DashboardService {
@Override @Override
public PieChartInfo getPieChart() { public PieChartInfo getPieChart() {
LambdaQueryWrapper<ItemInfo> itemQueryWrapper = Wrappers.lambdaQuery(ItemInfo.class).eq(ItemInfo::getDelFlag, DelEnum.NORMAL).select(ItemInfo::getItemId); LambdaQueryWrapper<ItemInfo> itemQueryWrapper = Wrappers.lambdaQuery(ItemInfo.class).eq(ItemInfo::getDelFlag, DelEnum.NORMAL.getIntCode()).select(ItemInfo::getItemId);
List<Object> itemNameList = itemInfoMapper.selectObjs(itemQueryWrapper); List<Object> itemNameList = itemInfoMapper.selectObjs(itemQueryWrapper);
List<Map<String, Object>> pieDataList = Lists.newArrayList(); List<Map<String, Object>> pieDataList = Lists.newArrayList();
for (Object each : itemNameList) { for (Object each : itemNameList) {
LambdaQueryWrapper<ConfigAllInfo> threadPoolQueryWrapper = Wrappers.lambdaQuery(ConfigAllInfo.class) LambdaQueryWrapper<ConfigAllInfo> threadPoolQueryWrapper = Wrappers.lambdaQuery(ConfigAllInfo.class)
.eq(ConfigInfoBase::getItemId, each) .eq(ConfigInfoBase::getItemId, each)
.eq(ConfigAllInfo::getDelFlag, DelEnum.NORMAL); .eq(ConfigAllInfo::getDelFlag, DelEnum.NORMAL.getIntCode());
Integer threadPoolCount = configInfoMapper.selectCount(threadPoolQueryWrapper); Integer threadPoolCount = configInfoMapper.selectCount(threadPoolQueryWrapper);
if (threadPoolCount != null) { if (threadPoolCount != null) {
Dict dict = Dict.create().set("name", each).set("value", threadPoolCount); Dict dict = Dict.create().set("name", each).set("value", threadPoolCount);

File diff suppressed because one or more lines are too long

@ -1 +1 @@
.waves-ripple{position:absolute;border-radius:100%;background-color:rgba(0,0,0,.15);background-clip:padding-box;pointer-events:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-transform:scale(0);transform:scale(0);opacity:1}.waves-ripple.z-active{opacity:0;-webkit-transform:scale(2);transform:scale(2);-webkit-transition:opacity 1.2s ease-out,-webkit-transform .6s ease-out;transition:opacity 1.2s ease-out,-webkit-transform .6s ease-out;transition:opacity 1.2s ease-out,transform .6s ease-out;transition:opacity 1.2s ease-out,transform .6s ease-out,-webkit-transform .6s ease-out}.dashboard-editor-container[data-v-490e92e5]{padding:32px;background-color:#f0f2f5;position:relative;min-height:100vh} .waves-ripple{position:absolute;border-radius:100%;background-color:rgba(0,0,0,.15);background-clip:padding-box;pointer-events:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-transform:scale(0);transform:scale(0);opacity:1}.waves-ripple.z-active{opacity:0;-webkit-transform:scale(2);transform:scale(2);-webkit-transition:opacity 1.2s ease-out,-webkit-transform .6s ease-out;transition:opacity 1.2s ease-out,-webkit-transform .6s ease-out;transition:opacity 1.2s ease-out,transform .6s ease-out;transition:opacity 1.2s ease-out,transform .6s ease-out,-webkit-transform .6s ease-out}.dashboard-editor-container[data-v-a25e0782]{padding:32px;background-color:#f0f2f5;position:relative;min-height:100vh}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -17,31 +17,24 @@
FROM openjdk:8-jre-slim FROM openjdk:8-jre-slim
MAINTAINER lijianxin MAINTAINER lijianxin
ENV MYSQL_HOST="127.0.0.1" \ ENV DATASOURCE_MODE="h2" \
MYSQL_PORT="3306" \ DATASOURCE_HOST="127.0.0.1" \
MYSQL_DB="hippo4j_manager" \ DATASOURCE_PORT="3306" \
MYSQL_USERNAME="root" \ DATASOURCE_DB="hippo4j_manager" \
MYSQL_PASSWORD="root" \ DATASOURCE_USERNAME="root" \
DATASOURCE_PASSWORD="root" \
BASE_DIR="/opt/hippo4j" BASE_DIR="/opt/hippo4j"
ENV TZ=PRC ENV TZ=PRC
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
ADD conf/hippo4j-logback.xml ${BASE_DIR}/logback.xml ADD conf/hippo4j-logback.xml ${BASE_DIR}/conf/hippo4j-logback.xml
ADD conf/application.properties ${BASE_DIR}/conf/application.properties
ADD target/hippo4j-server.jar ${BASE_DIR}/hippo4j-server.jar ADD target/hippo4j-server.jar ${BASE_DIR}/hippo4j-server.jar
ADD docker-startup.sh ${BASE_DIR}/docker-startup.sh
WORKDIR ${BASE_DIR} WORKDIR ${BASE_DIR}
RUN chmod +x docker-startup.sh
ENTRYPOINT ["./docker-startup.sh"]
ENTRYPOINT ["sh","-c","java -jar \
-Xloggc:${BASE_DIR}/hippo4j_gc.log -verbose:gc -XX:+PrintGCDetails \
-XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps -XX:+UseGCLogFileRotation \
-XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M \
-XX:-OmitStackTraceInFastThrow -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=${BASE_DIR}/java_heapdump.hprof \
-Xms1024m -Xmx1024m -Xmn512m \
-Dhippo4j.standalone=true -Dhippo4j.home=${BASE_DIR} \
hippo4j-server.jar \
--server.max-http-header-size=524288 --server.tomcat.basedir=${BASE_DIR}/tomcat/ \
--logging.config=${BASE_DIR}/logback.xml \
--spring.datasource.url=\"jdbc:mysql://$MYSQL_HOST:$MYSQL_PORT/$MYSQL_DB?characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&serverTimezone=GMT%2B8\" \
--spring.datasource.username=$MYSQL_USERNAME --spring.datasource.password=$MYSQL_PASSWORD \
"]

@ -47,6 +47,7 @@
</logger> </logger>
<root level="${logLevel}"> <root level="${logLevel}">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="FILE-ALL"/> <appender-ref ref="FILE-ALL"/>
<appender-ref ref="FILE-ERROR"/> <appender-ref ref="FILE-ERROR"/>
</root> </root>

@ -0,0 +1,44 @@
#!/bin/bash
export JAVA_HOME
export JAVA="$JAVA_HOME/bin/java"
export SERVER="hippo4j-server"
JAVA_OPT="${JAVA_OPT} -Djava.ext.dirs=${JAVA_HOME}/jre/lib/ext:${JAVA_HOME}/lib/ext"
JAVA_OPT="${JAVA_OPT} -Xloggc:${BASE_DIR}/logs/hippo4j_gc.log -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M"
JAVA_OPT="${JAVA_OPT} -Xms1024m -Xmx1024m -Xmn512m"
JAVA_OPT="${JAVA_OPT} -Dhippo4j.standalone=true"
JAVA_OPT="${JAVA_OPT} -XX:-OmitStackTraceInFastThrow -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=${BASE_DIR}/logs/java_heapdump.hprof"
JAVA_OPT="${JAVA_OPT} -Dhippo4j.home=${BASE_DIR}"
JAVA_OPT="${JAVA_OPT} ${JAVA_OPT_EXT}"
JAVA_OPT="${JAVA_OPT} --logging.config=${BASE_DIR}/conf/hippo4j-logback.xml"
JAVA_OPT="${JAVA_OPT} --server.max-http-header-size=524288"
JAVA_OPT="${JAVA_OPT} --server.tomcat.basedir=${BASE_DIR}/bin"
if [[ "${DATASOURCE_MODE}" == "mysql" ]]; then
JAVA_OPT="${JAVA_OPT} --spring.datasource.url=\"jdbc:mysql://${DATASOURCE_HOST}:${DATASOURCE_PORT}/${DATASOURCE_DB}?characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&serverTimezone=GMT%2B8\" "
JAVA_OPT="${JAVA_OPT} ---spring.datasource.username=${DATASOURCE_USERNAME} --spring.datasource.password=${DATASOURCE_PASSWORD} "
elif [[ "${DATASOURCE_MODE}" == "h2" ]]; then
JAVA_OPT="${JAVA_OPT} --spring.profiles.active=h2 --spring.datasource.url=jdbc:h2:file:${BASE_DIR}/h2_hippo4j;DB_CLOSE_DELAY=-1;DATABASE_TO_UPPER=false;MODE=MYSQL"
else
echo "hippo4j DATASOURCE_MODE is error, value ${DATASOURCE_MODE}, use default h2"
fi
if [ ! -d "${BASE_DIR}/logs" ]; then
mkdir ${BASE_DIR}/logs
fi
echo "$JAVA ${JAVA_OPT}"
echo "hippo4j is starting with standalone"
if [ ! -f "${BASE_DIR}/logs/start.out" ]; then
touch "${BASE_DIR}/logs/start.out"
fi
echo "$JAVA ${JAVA_OPT}" > ${BASE_DIR}/logs/start.out 2>&1 &
java -jar hippo4j-server.jar ${JAVA_OPT}
echo "hippo4j is startingyou can check the ${BASE_DIR}/logs/"

@ -14,19 +14,12 @@
</properties> </properties>
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>cn.hippo4j</groupId> <groupId>cn.hippo4j</groupId>
<artifactId>hippo4j-console</artifactId> <artifactId>hippo4j-console</artifactId>
<version>${revision}</version> <version>${revision}</version>
</dependency> </dependency>
<dependency>
<groupId>cn.hippo4j</groupId>
<artifactId>hippo4j-discovery</artifactId>
<version>${revision}</version>
</dependency>
<!-- Adapter start --> <!-- Adapter start -->
<dependency> <dependency>
<groupId>javax.xml.bind</groupId> <groupId>javax.xml.bind</groupId>

@ -0,0 +1,44 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.hippo4j.server.config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* Database configuration.
*
* <p> Quoted from org.apache.shenyu.admin.config.DataBaseConfiguration
*/
@Configuration
public class DataBaseConfiguration {
@Bean
@ConditionalOnMissingBean(value = DataBaseProperties.class)
public DataBaseProperties dataBaseProperties(@Value("${hippo4j.database.dialect:h2}") String dialect,
@Value("${hippo4j.database.init_script:sql-script/h2/schema.sql}") String initScript,
@Value("${hippo4j.database.init_enable:false}") Boolean initEnable) {
DataBaseProperties dataSourceProperties = new DataBaseProperties();
dataSourceProperties.setDialect(dialect);
dataSourceProperties.setInitScript(initScript);
dataSourceProperties.setInitEnable(initEnable);
return dataSourceProperties;
}
}

@ -0,0 +1,46 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.hippo4j.server.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* Database properties.
*
* <p> Quoted from org.apache.shenyu.admin.config.properties.DataBaseProperties
*/
@Data
@ConfigurationProperties(prefix = "hippo4j.database")
public class DataBaseProperties {
/**
* Dialect
*/
private String dialect;
/**
* Init script
*/
private String initScript;
/**
* Init enable
*/
private Boolean initEnable;
}

@ -0,0 +1,131 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.hippo4j.server.init;
import cn.hippo4j.server.config.DataBaseProperties;
import com.google.common.base.Splitter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.jdbc.ScriptRunner;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.nio.charset.StandardCharsets;
import java.sql.*;
import java.util.List;
import java.util.Objects;
/**
* Local datasource loader.
*
* <p> Quoted from org.apache.shenyu.admin.spring.LocalDataSourceLoader
*/
@Slf4j
@Component
@ConditionalOnExpression("'${hippo4j.database.dialect}' == 'mysql' or '${hippo4j.database.dialect}' == 'h2'")
public class LocalDataSourceLoader implements InstantiationAwareBeanPostProcessor {
private static final String PRE_FIX = "file:";
@Resource
private DataBaseProperties dataBaseProperties;
@Override
public Object postProcessAfterInitialization(@NonNull final Object bean, final String beanName) throws BeansException {
if ((bean instanceof DataSourceProperties) && dataBaseProperties.getInitEnable()) {
this.init((DataSourceProperties) bean);
}
return bean;
}
private void init(final DataSourceProperties properties) {
try {
String jdbcUrl = properties.getUrl();
// If jdbcUrl in the configuration file specifies the hippo4j database, it is removed,
// because the hippo4j database does not need to be specified when executing the SQL file,
// otherwise the hippo4j database will be disconnected when the hippo4j database does not exist
if (Objects.equals(dataBaseProperties.getDialect(), "mysql")) {
jdbcUrl = StringUtils.replace(properties.getUrl(), "/hippo4j_manager?", "?");
}
Connection connection = DriverManager.getConnection(jdbcUrl, properties.getUsername(), properties.getPassword());
// TODO Compatible with h2 to execute `INSERT IGNORE INTO` statement error
if (Objects.equals(dataBaseProperties.getDialect(), "h2") && ifNonExecute(connection)) {
return;
}
execute(connection, dataBaseProperties.getInitScript());
} catch (Exception ex) {
log.error("Datasource init error.", ex);
throw new RuntimeException(ex.getMessage());
}
}
private boolean ifNonExecute(final Connection conn) throws SQLException {
try (
Statement statement = conn.createStatement();
ResultSet resultSet = statement.executeQuery("SELECT COUNT(*) FROM `user`")) {
if (resultSet.next()) {
int countUser = resultSet.getInt(1);
return countUser > 0 ? true : false;
}
} catch (Exception ignored) {
log.error("Query data for errors.", ignored);
}
return false;
}
private void execute(final Connection conn, final String script) throws Exception {
ScriptRunner runner = new ScriptRunner(conn);
try {
// Doesn't print logger
runner.setLogWriter(null);
runner.setAutoCommit(true);
Resources.setCharset(StandardCharsets.UTF_8);
List<String> initScripts = Splitter.on(";").splitToList(script);
for (String sqlScript : initScripts) {
if (sqlScript.startsWith(PRE_FIX)) {
String sqlFile = sqlScript.substring(PRE_FIX.length());
try (Reader fileReader = getResourceAsReader(sqlFile)) {
log.info("Execute hippo4j schema sql: {}", sqlFile);
runner.runScript(fileReader);
}
} else {
try (Reader fileReader = Resources.getResourceAsReader(sqlScript)) {
log.info("Execute hippo4j schema sql: {}", sqlScript);
runner.runScript(fileReader);
}
}
}
} finally {
conn.close();
}
}
private static Reader getResourceAsReader(final String resource) throws IOException {
return new InputStreamReader(new FileInputStream(resource), StandardCharsets.UTF_8);
}
}

@ -1,6 +1,9 @@
### Default database ### Data source customization section
hippo4j.database.dialect=h2
hippo4j.database.init_enable=true
hippo4j.database.init_script=sql-script/h2/hippo4j_manager.sql
spring.datasource.driver-class-name=org.h2.Driver spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.url=jdbc:h2:mem:hippo4j_manager;DB_CLOSE_DELAY=-1;MODE=MySQL; spring.datasource.url=jdbc:h2:file:{your storage address}/h2_hippo4j_test_file;DB_CLOSE_DELAY=-1;DATABASE_TO_UPPER=false;MODE=MYSQL;
spring.datasource.username=sa spring.datasource.username=sa
spring.datasource.password=sa spring.datasource.password=sa
spring.datasource.schema=classpath:sql-script/h2/hippo4j_manager.sql

@ -1,5 +0,0 @@
### Data source customization section
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/hippo4j_manager?characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&serverTimezone=GMT%2B8
spring.datasource.username=root
spring.datasource.password=root

@ -21,10 +21,21 @@ tenant=hippo4j
hippo4j.core.clean-history-data-period=30 hippo4j.core.clean-history-data-period=30
hippo4j.core.clean-history-data-enable=true hippo4j.core.clean-history-data-enable=true
### Initialize the database dialect class.
hippo4j.database.dialect=mysql
hippo4j.database.init_enable=true
hippo4j.database.init_script=sql-script/mysql/hippo4j_manager.sql
### Use netty to report thread pool monitoring data. The default is http. ### Use netty to report thread pool monitoring data. The default is http.
# hippo4j.core.monitor.report-type=netty # hippo4j.core.monitor.report-type=netty
#*************** Config Module Related Configurations ***************# #*************** Config Module Related Configurations ***************#
### Default database
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/hippo4j_manager?characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&serverTimezone=GMT%2B8
spring.datasource.username=root
spring.datasource.password=root
### Hikari Datasource ### Hikari Datasource
spring.datasource.hikari.pool-name=Hikari spring.datasource.hikari.pool-name=Hikari
spring.datasource.hikari.connectionTimeout=30000 spring.datasource.hikari.connectionTimeout=30000

@ -1,15 +1,7 @@
,--, ,--, ,---._ __ __ ___ ___ __
,--.'| ,--.'| .-- -.' \ Hippo4J ${application.version} | |--.|__|.-----..-----..-----.| | | |__| Hippo4J ${application.version}
,--, | : ,--, ,-.----. ,-.----. ,--, | : | | : Port: ${server.port} | || || _ || _ || _ || | | | | Port: ${server.port} PID: ${pid}
,---.'| : ',--.'| \ / \ \ / \ ,---. ,---.'| : ' : ; | PID: ${pid} |__|__||__|| __|| __||_____||____ | | |
| | : _' || |, | : || : | ' ,'\ ; : | | ; : | Console: http://127.0.0.1:${server.port}/index.html |__| |__| |: ||___| Site: https://hippo4j.cn
: : |.' |`--'_ | | .\ :| | .\ : / / || | : _' | | : : `---'
| ' ' ; :,' ,'| . : |: |. : |: |. ; ,. :: : |.' | : https://hippo4j.cn
' | .'. |' | | | | \ :| | \ :' | |: :| ' ' ; : | ; |
| | : | '| | : | : . || : . |' | .; :\ \ .'. | ___ l
' : | : ;' : |__ : |`-': |`-'| : | `---`: | ' / /\ J :
| | ' ,/ | | '.'|: : : : : : \ \ / ' ; |/ ../ `..- ,
; : ;--' ; : ;| | : | | : `----' | : ;\ \ ;
| ,/ | , / `---'.| `---'.| ' ,/ \ \ ,'
'---' ---`-' `---` `---` '--' "---....--'

@ -1,235 +1,155 @@
/******************************************/ CREATE TABLE IF NOT EXISTS `tenant` (
/* 数据库全名 = hippo4j_manager */ `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键ID',
/* 表名称 = tenant */ `tenant_id` varchar(128) DEFAULT NULL COMMENT '租户ID',
/******************************************/ `tenant_name` varchar(128) DEFAULT NULL COMMENT '租户名称',
DROP TABLE IF EXISTS `tenant`, `tenant_info`; `tenant_desc` varchar(256) DEFAULT NULL COMMENT '租户介绍',
CREATE TABLE `tenant` ( `owner` varchar(32) DEFAULT '-' COMMENT '负责人',
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键ID', `gmt_create` datetime DEFAULT NULL COMMENT '创建时间',
`tenant_id` varchar(128) DEFAULT NULL COMMENT '租户ID', `gmt_modified` datetime DEFAULT NULL COMMENT '修改时间',
`tenant_name` varchar(128) DEFAULT NULL COMMENT '租户名称', `del_flag` tinyint(1) DEFAULT NULL COMMENT '是否删除',
`tenant_desc` varchar(256) DEFAULT NULL COMMENT '租户介绍', PRIMARY KEY (`id`)
`owner` varchar(32) DEFAULT '-' COMMENT '负责人', );
`gmt_create` datetime DEFAULT NULL COMMENT '创建时间',
`gmt_modified` datetime DEFAULT NULL COMMENT '修改时间', CREATE TABLE IF NOT EXISTS `item` (
`del_flag` tinyint(1) DEFAULT NULL COMMENT '是否删除', `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键ID',
PRIMARY KEY (`id`), `tenant_id` varchar(128) DEFAULT NULL COMMENT '租户ID',
UNIQUE KEY `tenant_id` (`id`), `item_id` varchar(128) DEFAULT NULL COMMENT '项目ID',
KEY `uk_tenantinfo_tenantid` (`tenant_id`,`del_flag`) USING BTREE `item_name` varchar(128) DEFAULT NULL COMMENT '项目名称',
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='租户表'; `item_desc` varchar(256) DEFAULT NULL COMMENT '项目介绍',
`owner` varchar(32) DEFAULT NULL COMMENT '负责人',
`gmt_create` datetime DEFAULT NULL COMMENT '创建时间',
`gmt_modified` datetime DEFAULT NULL COMMENT '修改时间',
`del_flag` tinyint(1) DEFAULT NULL COMMENT '是否删除',
PRIMARY KEY (`id`)
);
CREATE TABLE IF NOT EXISTS `config` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`tenant_id` varchar(128) DEFAULT NULL COMMENT '租户ID',
`item_id` varchar(256) DEFAULT NULL COMMENT '项目ID',
`tp_id` varchar(56) DEFAULT NULL COMMENT '线程池ID',
`tp_name` varchar(56) DEFAULT NULL COMMENT '线程池名称',
`core_size` int(11) DEFAULT NULL COMMENT '核心线程数',
`max_size` int(11) DEFAULT NULL COMMENT '最大线程数',
`queue_type` int(11) DEFAULT NULL COMMENT '队列类型...',
`capacity` int(11) DEFAULT NULL COMMENT '队列大小',
`rejected_type` int(11) DEFAULT NULL COMMENT '拒绝策略',
`keep_alive_time` int(11) DEFAULT NULL COMMENT '线程存活时间(秒)',
`execute_time_out` int(11) DEFAULT NULL COMMENT '执行超时时间(毫秒)',
`allow_core_thread_time_out` tinyint(1) DEFAULT NULL COMMENT '允许核心线程超时',
`content` longtext COMMENT '线程池内容',
`md5` varchar(32) NOT NULL COMMENT 'MD5',
`is_alarm` tinyint(1) DEFAULT NULL COMMENT '是否报警',
`capacity_alarm` int(11) DEFAULT NULL COMMENT '容量报警',
`liveness_alarm` int(11) DEFAULT NULL COMMENT '活跃度报警',
`gmt_create` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`gmt_modified` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',
`del_flag` tinyint(1) DEFAULT NULL COMMENT '是否删除',
PRIMARY KEY (`id`)
);
CREATE TABLE IF NOT EXISTS `inst_config` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`tenant_id` varchar(128) DEFAULT NULL COMMENT '租户ID',
`item_id` varchar(256) DEFAULT NULL COMMENT '项目ID',
`tp_id` varchar(56) DEFAULT NULL COMMENT '线程池ID',
`instance_id` varchar(256) DEFAULT NULL COMMENT '实例ID',
`content` longtext COMMENT '线程池内容',
`md5` varchar(32) NOT NULL COMMENT 'MD5',
`gmt_create` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`gmt_modified` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',
PRIMARY KEY (`id`)
);
CREATE TABLE IF NOT EXISTS `his_run_data` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
`tenant_id` varchar(128) DEFAULT NULL COMMENT '租户ID',
`item_id` varchar(256) DEFAULT NULL COMMENT '项目ID',
`tp_id` varchar(56) DEFAULT NULL COMMENT '线程池ID',
`instance_id` varchar(256) DEFAULT NULL COMMENT '实例ID',
`current_load` bigint(20) DEFAULT NULL COMMENT '当前负载',
`peak_load` bigint(20) DEFAULT NULL COMMENT '峰值负载',
`pool_size` bigint(20) DEFAULT NULL COMMENT '线程数',
`active_size` bigint(20) DEFAULT NULL COMMENT '活跃线程数',
`queue_capacity` bigint(20) DEFAULT NULL COMMENT '队列容量',
`queue_size` bigint(20) DEFAULT NULL COMMENT '队列元素',
`queue_remaining_capacity` bigint(20) DEFAULT NULL COMMENT '队列剩余容量',
`completed_task_count` bigint(20) DEFAULT NULL COMMENT '已完成任务计数',
`reject_count` bigint(20) DEFAULT NULL COMMENT '拒绝次数',
`timestamp` bigint(20) DEFAULT NULL COMMENT '时间戳',
`gmt_create` datetime DEFAULT NULL COMMENT '创建时间',
`gmt_modified` datetime DEFAULT NULL COMMENT '修改时间',
PRIMARY KEY (`id`)
);
CREATE TABLE IF NOT EXISTS `log_record_info` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
`tenant` varchar(128) NOT NULL DEFAULT '' COMMENT '租户标识',
`biz_key` varchar(128) NOT NULL DEFAULT '' COMMENT '日志业务标识',
`biz_no` varchar(128) NOT NULL DEFAULT '' COMMENT '业务码标识',
`operator` varchar(64) NOT NULL DEFAULT '' COMMENT '操作人',
`action` varchar(128) NOT NULL DEFAULT '' COMMENT '动作',
`category` varchar(128) NOT NULL DEFAULT '' COMMENT '种类',
`detail` varchar(2048) NOT NULL DEFAULT '' COMMENT '修改的详细信息可以为json',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
PRIMARY KEY (`id`)
);
CREATE TABLE IF NOT EXISTS `user` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
`user_name` varchar(64) NOT NULL COMMENT '用户名',
`password` varchar(512) NOT NULL COMMENT '用户密码',
`role` varchar(50) NOT NULL COMMENT '角色',
`gmt_create` datetime NOT NULL COMMENT '创建时间',
`gmt_modified` datetime NOT NULL COMMENT '修改时间',
`del_flag` tinyint(1) NOT NULL COMMENT '是否删除',
PRIMARY KEY (`id`)
);
CREATE TABLE IF NOT EXISTS `role` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
`role` varchar(64) NOT NULL COMMENT '角色',
`user_name` varchar(64) NOT NULL COMMENT '用户名',
`gmt_create` datetime NOT NULL COMMENT '创建时间',
`gmt_modified` datetime NOT NULL COMMENT '修改时间',
`del_flag` tinyint(1) NOT NULL COMMENT '是否删除',
PRIMARY KEY (`id`)
);
CREATE TABLE IF NOT EXISTS `permission` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
`role` varchar(512) NOT NULL COMMENT '角色',
`resource` varchar(512) NOT NULL COMMENT '资源',
`action` varchar(8) NOT NULL COMMENT '读写权限',
`gmt_create` datetime NOT NULL COMMENT '创建时间',
`gmt_modified` datetime NOT NULL COMMENT '修改时间',
`del_flag` tinyint(1) NOT NULL COMMENT '是否删除',
PRIMARY KEY (`id`)
);
CREATE TABLE IF NOT EXISTS `notify` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
`tenant_id` varchar(128) NOT NULL DEFAULT '' COMMENT '租户ID',
`item_id` varchar(128) NOT NULL COMMENT '项目ID',
`tp_id` varchar(128) NOT NULL COMMENT '线程池ID',
`platform` varchar(32) NOT NULL COMMENT '通知平台',
`type` varchar(32) NOT NULL COMMENT '通知类型',
`secret_key` varchar(256) NOT NULL COMMENT '密钥',
`interval` int(11) DEFAULT NULL COMMENT '报警间隔',
`receives` varchar(512) NOT NULL COMMENT '接收者',
`enable` tinyint(1) DEFAULT NULL COMMENT '是否启用',
`gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',
`del_flag` tinyint(1) NOT NULL COMMENT '是否删除',
PRIMARY KEY (`id`)
);
/******************************************/
/* 数据库全名 = hippo4j_manager */
/* 表名称 = item */
/******************************************/
DROP TABLE IF EXISTS `item`, `item_info`;
CREATE TABLE `item` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`tenant_id` varchar(128) DEFAULT NULL COMMENT '租户ID',
`item_id` varchar(128) DEFAULT NULL COMMENT '项目ID',
`item_name` varchar(128) DEFAULT NULL COMMENT '项目名称',
`item_desc` varchar(256) DEFAULT NULL COMMENT '项目介绍',
`owner` varchar(32) DEFAULT NULL COMMENT '负责人',
`gmt_create` datetime DEFAULT NULL COMMENT '创建时间',
`gmt_modified` datetime DEFAULT NULL COMMENT '修改时间',
`del_flag` tinyint(1) DEFAULT NULL COMMENT '是否删除',
PRIMARY KEY (`id`),
UNIQUE KEY `item_id` (`id`),
UNIQUE KEY `item_uk_iteminfo_tenantitem` (`tenant_id`,`item_id`,`del_flag`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='项目表';
/******************************************/
/* 数据库全名 = hippo4j_manager */
/* 表名称 = config */
/******************************************/
DROP TABLE IF EXISTS `config`, `config_info`;
CREATE TABLE `config` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`tenant_id` varchar(128) DEFAULT NULL COMMENT '租户ID',
`item_id` varchar(256) DEFAULT NULL COMMENT '项目ID',
`tp_id` varchar(56) DEFAULT NULL COMMENT '线程池ID',
`tp_name` varchar(56) DEFAULT NULL COMMENT '线程池名称',
`core_size` int(11) DEFAULT NULL COMMENT '核心线程数',
`max_size` int(11) DEFAULT NULL COMMENT '最大线程数',
`queue_type` int(11) DEFAULT NULL COMMENT '队列类型...',
`capacity` int(11) DEFAULT NULL COMMENT '队列大小',
`rejected_type` int(11) DEFAULT NULL COMMENT '拒绝策略',
`keep_alive_time` int(11) DEFAULT NULL COMMENT '线程存活时间',
`allow_core_thread_time_out` tinyint(1) DEFAULT NULL COMMENT '允许核心线程超时',
`content` longtext COMMENT '线程池内容',
`md5` varchar(32) NOT NULL COMMENT 'MD5',
`is_alarm` tinyint(1) DEFAULT NULL COMMENT '是否报警',
`capacity_alarm` int(11) DEFAULT NULL COMMENT '容量报警',
`liveness_alarm` int(11) DEFAULT NULL COMMENT '活跃度报警',
`gmt_create` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`gmt_modified` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',
`del_flag` tinyint(1) DEFAULT NULL COMMENT '是否删除',
PRIMARY KEY (`id`),
UNIQUE KEY `config_id` (`id`),
UNIQUE KEY `config_uk_configinfo_datagrouptenant` (`tenant_id`,`item_id`,`tp_id`,`del_flag`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='线程池配置表';
/******************************************/
/* 数据库全名 = hippo4j_manager */
/* 表名称 = inst_config */
/******************************************/
DROP TABLE IF EXISTS `inst_config`;
CREATE TABLE `inst_config` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`tenant_id` varchar(128) DEFAULT NULL COMMENT '租户ID',
`item_id` varchar(256) DEFAULT NULL COMMENT '项目ID',
`tp_id` varchar(56) DEFAULT NULL COMMENT '线程池ID',
`instance_id` varchar(256) DEFAULT NULL COMMENT '实例ID',
`content` longtext COMMENT '线程池内容',
`md5` varchar(32) NOT NULL COMMENT 'MD5',
`gmt_create` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`gmt_modified` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',
PRIMARY KEY (`id`),
UNIQUE KEY `inst_config_id` (`id`),
KEY `idx_config_instance` (`tenant_id`,`item_id`,`tp_id`,`instance_id`) USING BTREE,
KEY `idx_instance` (`instance_id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='线程池配置实例表';
/******************************************/
/* 数据库全名 = hippo4j_manager */
/* 表名称 = his_run_data */
/******************************************/
DROP TABLE IF EXISTS `his_run_data`;
CREATE TABLE `his_run_data` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
`tenant_id` varchar(128) DEFAULT NULL COMMENT '租户ID',
`item_id` varchar(256) DEFAULT NULL COMMENT '项目ID',
`tp_id` varchar(56) DEFAULT NULL COMMENT '线程池ID',
`instance_id` varchar(256) DEFAULT NULL COMMENT '实例ID',
`current_load` bigint(20) DEFAULT NULL COMMENT '当前负载',
`peak_load` bigint(20) DEFAULT NULL COMMENT '峰值负载',
`pool_size` bigint(20) DEFAULT NULL COMMENT '线程数',
`active_size` bigint(20) DEFAULT NULL COMMENT '活跃线程数',
`queue_capacity` bigint(20) DEFAULT NULL COMMENT '队列容量',
`queue_size` bigint(20) DEFAULT NULL COMMENT '队列元素',
`queue_remaining_capacity` bigint(20) DEFAULT NULL COMMENT '队列剩余容量',
`completed_task_count` bigint(20) DEFAULT NULL COMMENT '已完成任务计数',
`reject_count` bigint(20) DEFAULT NULL COMMENT '拒绝次数',
`timestamp` bigint(20) DEFAULT NULL COMMENT '时间戳',
`gmt_create` datetime DEFAULT NULL COMMENT '创建时间',
`gmt_modified` datetime DEFAULT NULL COMMENT '修改时间',
PRIMARY KEY (`id`),
KEY `idx_group_key` (`tenant_id`,`item_id`,`tp_id`,`instance_id`) USING BTREE,
KEY `idx_timestamp` (`timestamp`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='历史运行数据表';
/******************************************/
/* 数据库全名 = hippo4j_manager */
/* 表名称 = log_record_info */
/******************************************/
DROP TABLE IF EXISTS `log_record_info`;
CREATE TABLE `log_record_info` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
`tenant` varchar(128) NOT NULL DEFAULT '' COMMENT '租户标识',
`biz_key` varchar(128) NOT NULL DEFAULT '' COMMENT '日志业务标识',
`biz_no` varchar(128) NOT NULL DEFAULT '' COMMENT '业务码标识',
`operator` varchar(64) NOT NULL DEFAULT '' COMMENT '操作人',
`action` varchar(128) NOT NULL DEFAULT '' COMMENT '动作',
`category` varchar(128) NOT NULL DEFAULT '' COMMENT '种类',
`detail` varchar(2048) NOT NULL DEFAULT '' COMMENT '修改的详细信息可以为json',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
PRIMARY KEY (`id`),
KEY `idx_biz_key` (`biz_key`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='操作日志表';
/******************************************/
/* 数据库全名 = hippo4j_manager */
/* 表名称 = user */
/******************************************/
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
`user_name` varchar(64) NOT NULL COMMENT '用户名',
`password` varchar(512) NOT NULL COMMENT '用户密码',
`role` varchar(50) NOT NULL COMMENT '角色',
`gmt_create` datetime NOT NULL COMMENT '创建时间',
`gmt_modified` datetime NOT NULL COMMENT '修改时间',
`del_flag` tinyint(1) NOT NULL COMMENT '是否删除',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='用户表';
/******************************************/
/* 数据库全名 = hippo4j_manager */
/* 表名称 = role */
/******************************************/
DROP TABLE IF EXISTS `role`;
CREATE TABLE `role` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
`role` varchar(64) NOT NULL COMMENT '角色',
`user_name` varchar(64) NOT NULL COMMENT '用户名',
`gmt_create` datetime NOT NULL COMMENT '创建时间',
`gmt_modified` datetime NOT NULL COMMENT '修改时间',
`del_flag` tinyint(1) NOT NULL COMMENT '是否删除',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='角色表';
/******************************************/
/* 数据库全名 = hippo4j_manager */
/* 表名称 = permission */
/******************************************/
DROP TABLE IF EXISTS `permission`;
CREATE TABLE `permission` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
`role` varchar(512) NOT NULL COMMENT '角色',
`resource` varchar(512) NOT NULL COMMENT '资源',
`action` varchar(8) NOT NULL COMMENT '读写权限',
`gmt_create` datetime NOT NULL COMMENT '创建时间',
`gmt_modified` datetime NOT NULL COMMENT '修改时间',
`del_flag` tinyint(1) NOT NULL COMMENT '是否删除',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='权限表';
/******************************************/
/* 数据库全名 = hippo4j_manager */
/* 表名称 = notify */
/******************************************/
DROP TABLE IF EXISTS `alarm`, `notify`;
CREATE TABLE `notify` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
`tenant_id` varchar(128) NOT NULL DEFAULT '' COMMENT '租户ID',
`item_id` varchar(128) NOT NULL COMMENT '项目ID',
`tp_id` varchar(128) NOT NULL COMMENT '线程池ID',
`platform` varchar(32) NOT NULL COMMENT '通知平台',
`type` varchar(32) NOT NULL COMMENT '通知类型',
`secret_key` varchar(256) NOT NULL COMMENT '密钥',
`interval` int(11) DEFAULT NULL COMMENT '报警间隔',
`receives` varchar(512) NOT NULL COMMENT '接收者',
`enable` tinyint(1) DEFAULT NULL COMMENT '是否启用',
`gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',
`del_flag` tinyint(1) NOT NULL COMMENT '是否删除',
PRIMARY KEY (`id`),
UNIQUE KEY `notify_uk_notify_biz_key` (`tenant_id`,`item_id`,`tp_id`,`platform`,`type`,`del_flag`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='通知表';
/* 租户 */
INSERT INTO `tenant` (`id`, `tenant_id`, `tenant_name`, `tenant_desc`, `owner`, `gmt_create`, `gmt_modified`, `del_flag`) VALUES ('1', 'prescription', '处方组', '负责维护处方服务, 包括不限于电子处方等业务', '谢良辰', '2021-10-24 13:42:11', '2021-10-24 13:42:11', '0'); INSERT INTO `tenant` (`id`, `tenant_id`, `tenant_name`, `tenant_desc`, `owner`, `gmt_create`, `gmt_modified`, `del_flag`) VALUES ('1', 'prescription', '处方组', '负责维护处方服务, 包括不限于电子处方等业务', '谢良辰', '2021-10-24 13:42:11', '2021-10-24 13:42:11', '0');
/* 项目 */
INSERT INTO `item` (`id`, `tenant_id`, `item_id`, `item_name`, `item_desc`, `owner`, `gmt_create`, `gmt_modified`, `del_flag`) VALUES ('1', 'prescription', 'dynamic-threadpool-example', '动态线程池示例项目', '动态线程池示例项目,对应 Hippo 项目的 example 模块', '马称', '2021-10-24 16:11:00', '2021-10-24 16:11:00', '0'); INSERT INTO `item` (`id`, `tenant_id`, `item_id`, `item_name`, `item_desc`, `owner`, `gmt_create`, `gmt_modified`, `del_flag`) VALUES ('1', 'prescription', 'dynamic-threadpool-example', '动态线程池示例项目', '动态线程池示例项目,对应 Hippo 项目的 example 模块', '马称', '2021-10-24 16:11:00', '2021-10-24 16:11:00', '0');
/* 线程池 */ INSERT INTO `config` (`id`, `tenant_id`, `item_id`, `tp_id`, `tp_name`, `core_size`, `max_size`, `queue_type`, `capacity`, `rejected_type`, `keep_alive_time`, `allow_core_thread_time_out`, `content`, `md5`, `is_alarm`, `capacity_alarm`, `liveness_alarm`, `gmt_create`, `gmt_modified`, `del_flag`) VALUES ('1', 'prescription', 'dynamic-threadpool-example', 'message-consume', '示例消费者线程池', '5', '10', '9', '1024', '2', '9999', '0', '{\"tenantId\":\"prescription\",\"itemId\":\"dynamic-threadpool-example\",\"tpId\":\"message-consume\",\"coreSize\":5,\"maxSize\":10,\"queueType\":9,\"capacity\":1024,\"keepAliveTime\":9999,\"rejectedType\":2,\"isAlarm\":0,\"capacityAlarm\":80,\"livenessAlarm\":80,\"allowCoreThreadTimeOut\":0}', 'f80ea89044889fb6cec20e1a517f2ec3', '0', '80', '80', '2021-10-24 10:24:00', '2021-12-22 08:58:55', '0'), ('2', 'prescription', 'dynamic-threadpool-example', 'message-produce', '示例生产者线程池', '5', '15', '9', '1024', '1', '9999', '0', '{\"tenantId\":\"prescription\",\"itemId\":\"dynamic-threadpool-example\",\"tpId\":\"message-produce\",\"coreSize\":5,\"maxSize\":15,\"queueType\":9,\"capacity\":1024,\"keepAliveTime\":9999,\"rejectedType\":1,\"isAlarm\":0,\"capacityAlarm\":30,\"livenessAlarm\":30,\"allowCoreThreadTimeOut\":0}', '525e1429468bcfe98df7e70a75710051', '0', '30', '30', '2021-10-24 10:24:00', '2021-12-22 08:59:02', '0');
INSERT INTO `config` (`id`, `tenant_id`, `item_id`, `tp_id`, `tp_name`, `core_size`, `max_size`, `queue_type`, `capacity`, `rejected_type`, `keep_alive_time`, `allow_core_thread_time_out`, `content`, `md5`, `is_alarm`, `capacity_alarm`, `liveness_alarm`, `gmt_create`, `gmt_modified`, `del_flag`) VALUES ('1', 'prescription', 'dynamic-threadpool-example', 'message-consume', '示例消费者线程池', '5', '10', '9', '1024', '2', '9999', '0', '{\"tenantId\":\"prescription\",\"itemId\":\"dynamic-threadpool-example\",\"tpId\":\"message-consume\",\"coreSize\":5,\"maxSize\":10,\"queueType\":9,\"capacity\":1024,\"keepAliveTime\":9999,\"rejectedType\":2,\"isAlarm\":0,\"capacityAlarm\":80,\"livenessAlarm\":80,\"allowCoreThreadTimeOut\":0}', 'f80ea89044889fb6cec20e1a517f2ec3', '0', '80', '80', '2021-10-24 10:24:00', '2021-12-22 08:58:55', '0'),
('2', 'prescription', 'dynamic-threadpool-example', 'message-produce', '示例生产者线程池', '5', '15', '9', '1024', '1', '9999', '0', '{\"tenantId\":\"prescription\",\"itemId\":\"dynamic-threadpool-example\",\"tpId\":\"message-produce\",\"coreSize\":5,\"maxSize\":15,\"queueType\":9,\"capacity\":1024,\"keepAliveTime\":9999,\"rejectedType\":1,\"isAlarm\":0,\"capacityAlarm\":30,\"livenessAlarm\":30,\"allowCoreThreadTimeOut\":0}', '525e1429468bcfe98df7e70a75710051', '0', '30', '30', '2021-10-24 10:24:00', '2021-12-22 08:59:02', '0');
/* 用户 */
INSERT INTO `user` (`id`, `user_name`, `password`, `role`, `gmt_create`, `gmt_modified`, `del_flag`) VALUES ('1', 'admin', '$2a$10$2KCqRbra0Yn2TwvkZxtfLuWuUP5KyCWsljO/ci5pLD27pqR3TV1vy', 'ROLE_ADMIN', '2021-11-04 21:35:17', '2021-11-15 23:04:59', '0'); INSERT INTO `user` (`id`, `user_name`, `password`, `role`, `gmt_create`, `gmt_modified`, `del_flag`) VALUES ('1', 'admin', '$2a$10$2KCqRbra0Yn2TwvkZxtfLuWuUP5KyCWsljO/ci5pLD27pqR3TV1vy', 'ROLE_ADMIN', '2021-11-04 21:35:17', '2021-11-15 23:04:59', '0');
/* 通知表 */ INSERT INTO `notify` (`id`, `tenant_id`, `item_id`, `tp_id`, `platform`, `type`, `secret_key`, `interval`, `receives`, `enable`, `gmt_create`, `gmt_modified`, `del_flag`) VALUES ('1', 'prescription', 'dynamic-threadpool-example', 'message-produce', 'DING', 'CONFIG', '4a582a588a161d6e3a1bd1de7eea9ee9f562cdfcbe56b6e72029e7fd512b2eae', NULL, '15601166691', '0', '2021-11-18 22:49:50', '2021-11-18 22:49:50', '0'), ('2', 'prescription', 'dynamic-threadpool-example', 'message-produce', 'DING', 'ALARM', '4a582a588a161d6e3a1bd1de7eea9ee9f562cdfcbe56b6e72029e7fd512b2eae', '30', '15601166691', '0', '2021-11-18 22:50:06', '2021-11-18 22:50:06', '0');
INSERT INTO `notify` (`id`, `tenant_id`, `item_id`, `tp_id`, `platform`, `type`, `secret_key`, `interval`, `receives`, `enable`, `gmt_create`, `gmt_modified`, `del_flag`) VALUES ('1', 'prescription', 'dynamic-threadpool-example', 'message-produce', 'DING', 'CONFIG', '4a582a588a161d6e3a1bd1de7eea9ee9f562cdfcbe56b6e72029e7fd512b2eae', NULL, '15601166691', '0', '2021-11-18 22:49:50', '2021-11-18 22:49:50', '0'),
('2', 'prescription', 'dynamic-threadpool-example', 'message-produce', 'DING', 'ALARM', '4a582a588a161d6e3a1bd1de7eea9ee9f562cdfcbe56b6e72029e7fd512b2eae', '30', '15601166691', '0', '2021-11-18 22:50:06', '2021-11-18 22:50:06', '0');
/* 1.1.0 Upgrade Start */
ALTER TABLE `config` DROP INDEX `config_uk_configinfo_datagrouptenant`;
ALTER TABLE `item` DROP INDEX `item_uk_iteminfo_tenantitem`;
ALTER TABLE `tenant` DROP INDEX `uk_tenantinfo_tenantid`;
/* 1.1.0 Upgrade End */
/* 1.4.0 Upgrade Start */
ALTER TABLE config Modify COLUMN keep_alive_time int(11) COMMENT '线程存活时间(秒)';
ALTER TABLE config Add execute_time_out int(11) COMMENT '执行超时时间(毫秒)' AFTER keep_alive_time;
/* 1.4.0 Upgrade Start */

@ -0,0 +1,214 @@
CREATE DATABASE /*!32312 IF NOT EXISTS*/ `hippo4j_manager` /*!40100 DEFAULT CHARACTER SET utf8 COLLATE utf8_bin */;
USE `hippo4j_manager`;
/******************************************/
/* 数据库全名 = hippo4j_manager */
/* 表名称 = tenant */
/******************************************/
CREATE TABLE IF NOT EXISTS `tenant` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`tenant_id` varchar(128) DEFAULT NULL COMMENT '租户ID',
`tenant_name` varchar(128) DEFAULT NULL COMMENT '租户名称',
`tenant_desc` varchar(256) DEFAULT NULL COMMENT '租户介绍',
`owner` varchar(32) DEFAULT '-' COMMENT '负责人',
`gmt_create` datetime DEFAULT NULL COMMENT '创建时间',
`gmt_modified` datetime DEFAULT NULL COMMENT '修改时间',
`del_flag` tinyint(1) DEFAULT NULL COMMENT '是否删除',
PRIMARY KEY (`id`),
UNIQUE KEY `id` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='租户表';
/******************************************/
/* 数据库全名 = hippo4j_manager */
/* 表名称 = item */
/******************************************/
CREATE TABLE IF NOT EXISTS `item` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`tenant_id` varchar(128) DEFAULT NULL COMMENT '租户ID',
`item_id` varchar(128) DEFAULT NULL COMMENT '项目ID',
`item_name` varchar(128) DEFAULT NULL COMMENT '项目名称',
`item_desc` varchar(256) DEFAULT NULL COMMENT '项目介绍',
`owner` varchar(32) DEFAULT NULL COMMENT '负责人',
`gmt_create` datetime DEFAULT NULL COMMENT '创建时间',
`gmt_modified` datetime DEFAULT NULL COMMENT '修改时间',
`del_flag` tinyint(1) DEFAULT NULL COMMENT '是否删除',
PRIMARY KEY (`id`),
UNIQUE KEY `id` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='项目表';
/******************************************/
/* 数据库全名 = hippo4j_manager */
/* 表名称 = config */
/******************************************/
CREATE TABLE IF NOT EXISTS `config` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`tenant_id` varchar(128) DEFAULT NULL COMMENT '租户ID',
`item_id` varchar(256) DEFAULT NULL COMMENT '项目ID',
`tp_id` varchar(56) DEFAULT NULL COMMENT '线程池ID',
`tp_name` varchar(56) DEFAULT NULL COMMENT '线程池名称',
`core_size` int(11) DEFAULT NULL COMMENT '核心线程数',
`max_size` int(11) DEFAULT NULL COMMENT '最大线程数',
`queue_type` int(11) DEFAULT NULL COMMENT '队列类型...',
`capacity` int(11) DEFAULT NULL COMMENT '队列大小',
`rejected_type` int(11) DEFAULT NULL COMMENT '拒绝策略',
`keep_alive_time` int(11) DEFAULT NULL COMMENT '线程存活时间(秒)',
`execute_time_out` int(11) DEFAULT NULL COMMENT '执行超时时间(毫秒)',
`allow_core_thread_time_out` tinyint(1) DEFAULT NULL COMMENT '允许核心线程超时',
`content` longtext COMMENT '线程池内容',
`md5` varchar(32) NOT NULL COMMENT 'MD5',
`is_alarm` tinyint(1) DEFAULT NULL COMMENT '是否报警',
`capacity_alarm` int(11) DEFAULT NULL COMMENT '容量报警',
`liveness_alarm` int(11) DEFAULT NULL COMMENT '活跃度报警',
`gmt_create` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`gmt_modified` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',
`del_flag` tinyint(1) DEFAULT NULL COMMENT '是否删除',
PRIMARY KEY (`id`),
UNIQUE KEY `id` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='线程池配置表';
/******************************************/
/* 数据库全名 = hippo4j_manager */
/* 表名称 = inst_config */
/******************************************/
CREATE TABLE IF NOT EXISTS `inst_config` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`tenant_id` varchar(128) DEFAULT NULL COMMENT '租户ID',
`item_id` varchar(256) DEFAULT NULL COMMENT '项目ID',
`tp_id` varchar(56) DEFAULT NULL COMMENT '线程池ID',
`instance_id` varchar(256) DEFAULT NULL COMMENT '实例ID',
`content` longtext COMMENT '线程池内容',
`md5` varchar(32) NOT NULL COMMENT 'MD5',
`gmt_create` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`gmt_modified` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',
PRIMARY KEY (`id`),
UNIQUE KEY `id` (`id`),
KEY `idx_config_instance` (`tenant_id`,`item_id`,`tp_id`,`instance_id`) USING BTREE,
KEY `idx_instance` (`instance_id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='线程池配置实例表';
/******************************************/
/* 数据库全名 = hippo4j_manager */
/* 表名称 = his_run_data */
/******************************************/
CREATE TABLE IF NOT EXISTS `his_run_data` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
`tenant_id` varchar(128) DEFAULT NULL COMMENT '租户ID',
`item_id` varchar(256) DEFAULT NULL COMMENT '项目ID',
`tp_id` varchar(56) DEFAULT NULL COMMENT '线程池ID',
`instance_id` varchar(256) DEFAULT NULL COMMENT '实例ID',
`current_load` bigint(20) DEFAULT NULL COMMENT '当前负载',
`peak_load` bigint(20) DEFAULT NULL COMMENT '峰值负载',
`pool_size` bigint(20) DEFAULT NULL COMMENT '线程数',
`active_size` bigint(20) DEFAULT NULL COMMENT '活跃线程数',
`queue_capacity` bigint(20) DEFAULT NULL COMMENT '队列容量',
`queue_size` bigint(20) DEFAULT NULL COMMENT '队列元素',
`queue_remaining_capacity` bigint(20) DEFAULT NULL COMMENT '队列剩余容量',
`completed_task_count` bigint(20) DEFAULT NULL COMMENT '已完成任务计数',
`reject_count` bigint(20) DEFAULT NULL COMMENT '拒绝次数',
`timestamp` bigint(20) DEFAULT NULL COMMENT '时间戳',
`gmt_create` datetime DEFAULT NULL COMMENT '创建时间',
`gmt_modified` datetime DEFAULT NULL COMMENT '修改时间',
PRIMARY KEY (`id`),
KEY `idx_group_key` (`tenant_id`,`item_id`,`tp_id`,`instance_id`) USING BTREE,
KEY `idx_timestamp` (`timestamp`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='历史运行数据表';
/******************************************/
/* 数据库全名 = hippo4j_manager */
/* 表名称 = log_record_info */
/******************************************/
CREATE TABLE IF NOT EXISTS `log_record_info` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
`tenant` varchar(128) NOT NULL DEFAULT '' COMMENT '租户标识',
`biz_key` varchar(128) NOT NULL DEFAULT '' COMMENT '日志业务标识',
`biz_no` varchar(128) NOT NULL DEFAULT '' COMMENT '业务码标识',
`operator` varchar(64) NOT NULL DEFAULT '' COMMENT '操作人',
`action` varchar(128) NOT NULL DEFAULT '' COMMENT '动作',
`category` varchar(128) NOT NULL DEFAULT '' COMMENT '种类',
`detail` varchar(2048) NOT NULL DEFAULT '' COMMENT '修改的详细信息可以为json',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
PRIMARY KEY (`id`),
KEY `idx_biz_key` (`biz_key`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='操作日志表';
/******************************************/
/* 数据库全名 = hippo4j_manager */
/* 表名称 = user */
/******************************************/
CREATE TABLE IF NOT EXISTS `user` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
`user_name` varchar(64) NOT NULL COMMENT '用户名',
`password` varchar(512) NOT NULL COMMENT '用户密码',
`role` varchar(50) NOT NULL COMMENT '角色',
`gmt_create` datetime NOT NULL COMMENT '创建时间',
`gmt_modified` datetime NOT NULL COMMENT '修改时间',
`del_flag` tinyint(1) NOT NULL COMMENT '是否删除',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='用户表';
/******************************************/
/* 数据库全名 = hippo4j_manager */
/* 表名称 = role */
/******************************************/
CREATE TABLE IF NOT EXISTS `role` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
`role` varchar(64) NOT NULL COMMENT '角色',
`user_name` varchar(64) NOT NULL COMMENT '用户名',
`gmt_create` datetime NOT NULL COMMENT '创建时间',
`gmt_modified` datetime NOT NULL COMMENT '修改时间',
`del_flag` tinyint(1) NOT NULL COMMENT '是否删除',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='角色表';
/******************************************/
/* 数据库全名 = hippo4j_manager */
/* 表名称 = permission */
/******************************************/
CREATE TABLE IF NOT EXISTS `permission` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
`role` varchar(512) NOT NULL COMMENT '角色',
`resource` varchar(512) NOT NULL COMMENT '资源',
`action` varchar(8) NOT NULL COMMENT '读写权限',
`gmt_create` datetime NOT NULL COMMENT '创建时间',
`gmt_modified` datetime NOT NULL COMMENT '修改时间',
`del_flag` tinyint(1) NOT NULL COMMENT '是否删除',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='权限表';
/******************************************/
/* 数据库全名 = hippo4j_manager */
/* 表名称 = notify */
/******************************************/
CREATE TABLE IF NOT EXISTS `notify` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
`tenant_id` varchar(128) NOT NULL DEFAULT '' COMMENT '租户ID',
`item_id` varchar(128) NOT NULL COMMENT '项目ID',
`tp_id` varchar(128) NOT NULL COMMENT '线程池ID',
`platform` varchar(32) NOT NULL COMMENT '通知平台',
`type` varchar(32) NOT NULL COMMENT '通知类型',
`secret_key` varchar(256) NOT NULL COMMENT '密钥',
`interval` int(11) DEFAULT NULL COMMENT '报警间隔',
`receives` varchar(512) NOT NULL COMMENT '接收者',
`enable` tinyint(1) DEFAULT NULL COMMENT '是否启用',
`gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',
`del_flag` tinyint(1) NOT NULL COMMENT '是否删除',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_notify_biz_key` (`tenant_id`,`item_id`,`tp_id`,`platform`,`type`,`del_flag`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='通知表';
/* 租户 */
INSERT IGNORE INTO `tenant` (`id`, `tenant_id`, `tenant_name`, `tenant_desc`, `owner`, `gmt_create`, `gmt_modified`, `del_flag`) VALUES ('1', 'prescription', '处方组', '负责维护处方服务, 包括不限于电子处方等业务', '谢良辰', '2021-10-24 13:42:11', '2021-10-24 13:42:11', '0');
/* 项目 */
INSERT IGNORE INTO `item` (`id`, `tenant_id`, `item_id`, `item_name`, `item_desc`, `owner`, `gmt_create`, `gmt_modified`, `del_flag`) VALUES ('1', 'prescription', 'dynamic-threadpool-example', '动态线程池示例项目', '动态线程池示例项目,对应 Hippo 项目的 example 模块', '马称', '2021-10-24 16:11:00', '2021-10-24 16:11:00', '0');
/* 线程池 */
INSERT IGNORE INTO `config` (`id`, `tenant_id`, `item_id`, `tp_id`, `tp_name`, `core_size`, `max_size`, `queue_type`, `capacity`, `rejected_type`, `keep_alive_time`, `allow_core_thread_time_out`, `content`, `md5`, `is_alarm`, `capacity_alarm`, `liveness_alarm`, `gmt_create`, `gmt_modified`, `del_flag`) VALUES ('1', 'prescription', 'dynamic-threadpool-example', 'message-consume', '示例消费者线程池', '5', '10', '9', '1024', '2', '9999', '0', '{\"tenantId\":\"prescription\",\"itemId\":\"dynamic-threadpool-example\",\"tpId\":\"message-consume\",\"coreSize\":5,\"maxSize\":10,\"queueType\":9,\"capacity\":1024,\"keepAliveTime\":9999,\"rejectedType\":2,\"isAlarm\":0,\"capacityAlarm\":80,\"livenessAlarm\":80,\"allowCoreThreadTimeOut\":0}', 'f80ea89044889fb6cec20e1a517f2ec3', '0', '80', '80', '2021-10-24 10:24:00', '2021-12-22 08:58:55', '0'), ('2', 'prescription', 'dynamic-threadpool-example', 'message-produce', '示例生产者线程池', '5', '15', '9', '1024', '1', '9999', '0', '{\"tenantId\":\"prescription\",\"itemId\":\"dynamic-threadpool-example\",\"tpId\":\"message-produce\",\"coreSize\":5,\"maxSize\":15,\"queueType\":9,\"capacity\":1024,\"keepAliveTime\":9999,\"rejectedType\":1,\"isAlarm\":0,\"capacityAlarm\":30,\"livenessAlarm\":30,\"allowCoreThreadTimeOut\":0}', '525e1429468bcfe98df7e70a75710051', '0', '30', '30', '2021-10-24 10:24:00', '2021-12-22 08:59:02', '0');
/* 用户 */
INSERT IGNORE INTO `user` (`id`, `user_name`, `password`, `role`, `gmt_create`, `gmt_modified`, `del_flag`) VALUES ('1', 'admin', '$2a$10$2KCqRbra0Yn2TwvkZxtfLuWuUP5KyCWsljO/ci5pLD27pqR3TV1vy', 'ROLE_ADMIN', '2021-11-04 21:35:17', '2021-11-15 23:04:59', '0');
/* 通知表 */
INSERT IGNORE INTO `notify` (`id`, `tenant_id`, `item_id`, `tp_id`, `platform`, `type`, `secret_key`, `interval`, `receives`, `enable`, `gmt_create`, `gmt_modified`, `del_flag`) VALUES ('1', 'prescription', 'dynamic-threadpool-example', 'message-produce', 'DING', 'CONFIG', '4a582a588a161d6e3a1bd1de7eea9ee9f562cdfcbe56b6e72029e7fd512b2eae', NULL, '15601166691', '0', '2021-11-18 22:49:50', '2021-11-18 22:49:50', '0'), ('2', 'prescription', 'dynamic-threadpool-example', 'message-produce', 'DING', 'ALARM', '4a582a588a161d6e3a1bd1de7eea9ee9f562cdfcbe56b6e72029e7fd512b2eae', '30', '15601166691', '0', '2021-11-18 22:50:06', '2021-11-18 22:50:06', '0');

@ -49,4 +49,9 @@ public class AdapterExecutorProperties {
* Nodes, application startup is not affect, change properties is effect * Nodes, application startup is not affect, change properties is effect
*/ */
private String nodes; private String nodes;
/**
* these propertied is enabled?
*/
private Boolean enable = true;
} }

@ -44,4 +44,9 @@ public class WebThreadPoolProperties {
* Nodes, application startup is not affect, change properties is effect * Nodes, application startup is not affect, change properties is effect
*/ */
private String nodes; private String nodes;
/**
* these propertied is enabled?
*/
private Boolean enable = true;
} }

@ -18,6 +18,7 @@
package cn.hippo4j.config.springboot.starter.refresher; package cn.hippo4j.config.springboot.starter.refresher;
import cn.hippo4j.common.api.ThreadPoolDynamicRefresh; import cn.hippo4j.common.api.ThreadPoolDynamicRefresh;
import cn.hippo4j.common.api.ThreadPoolInitRefresh;
import cn.hippo4j.common.config.ApplicationContextHolder; import cn.hippo4j.common.config.ApplicationContextHolder;
import cn.hippo4j.common.toolkit.CollectionUtil; import cn.hippo4j.common.toolkit.CollectionUtil;
import cn.hippo4j.config.springboot.starter.config.BootstrapConfigProperties; import cn.hippo4j.config.springboot.starter.config.BootstrapConfigProperties;
@ -37,7 +38,11 @@ import java.util.concurrent.ExecutorService;
*/ */
@Slf4j @Slf4j
@RequiredArgsConstructor @RequiredArgsConstructor
public abstract class AbstractConfigThreadPoolDynamicRefresh implements ThreadPoolDynamicRefresh, InitializingBean { public abstract class AbstractConfigThreadPoolDynamicRefresh
implements
ThreadPoolDynamicRefresh,
ThreadPoolInitRefresh,
InitializingBean {
protected final BootstrapConfigProperties bootstrapConfigProperties; protected final BootstrapConfigProperties bootstrapConfigProperties;
@ -47,6 +52,11 @@ public abstract class AbstractConfigThreadPoolDynamicRefresh implements ThreadPo
bootstrapConfigProperties = ApplicationContextHolder.getBean(BootstrapConfigProperties.class); bootstrapConfigProperties = ApplicationContextHolder.getBean(BootstrapConfigProperties.class);
} }
@Override
public void initRefresh(String context) {
dynamicRefresh(context);
}
@Override @Override
public void dynamicRefresh(String configContent) { public void dynamicRefresh(String configContent) {
dynamicRefresh(configContent, null); dynamicRefresh(configContent, null);

@ -41,6 +41,16 @@ public class ApolloRefresherHandler extends AbstractConfigThreadPoolDynamicRefre
@Value(APOLLO_PROPERTY) @Value(APOLLO_PROPERTY)
private String namespace; private String namespace;
@Override
public String getProperties() {
String[] apolloNamespaces = this.namespace.split(",");
this.namespace = apolloNamespaces[0];
String copyNamespace = this.namespace.replaceAll("." + bootstrapConfigProperties.getConfigFileType().getValue(), "");
ConfigFileFormat configFileFormat = ConfigFileFormat.fromString(bootstrapConfigProperties.getConfigFileType().getValue());
ConfigFile configFile = ConfigService.getConfigFile(copyNamespace, configFileFormat);
return configFile.getContent();
}
@Override @Override
public void afterPropertiesSet() { public void afterPropertiesSet() {
String[] apolloNamespaces = this.namespace.split(","); String[] apolloNamespaces = this.namespace.split(",");

@ -52,22 +52,25 @@ public class EtcdRefresherHandler extends AbstractConfigThreadPoolDynamicRefresh
private static final String KEY = "key"; private static final String KEY = "key";
@Override
public String getProperties() throws Exception {
Map<String, String> etcd = bootstrapConfigProperties.getEtcd();
Charset charset = StringUtil.isBlank(etcd.get(CHARSET)) ? StandardCharsets.UTF_8 : Charset.forName(etcd.get(CHARSET));
initClient(etcd, charset);
String key = etcd.get(KEY);
GetResponse getResponse = client.getKVClient().get(ByteSequence.from(key, charset)).get();
KeyValue keyValue = getResponse.getKvs().get(0);
return Objects.isNull(keyValue) ? null : keyValue.getValue().toString(charset);
}
@Override @Override
public void afterPropertiesSet() throws Exception { public void afterPropertiesSet() throws Exception {
Map<String, String> etcd = bootstrapConfigProperties.getEtcd(); Map<String, String> etcd = bootstrapConfigProperties.getEtcd();
String user = etcd.get(USER);
String password = etcd.get(PASSWORD);
String endpoints = etcd.get(ENDPOINTS);
String authority = etcd.get(AUTHORITY);
String key = etcd.get(KEY); String key = etcd.get(KEY);
Charset charset = StringUtil.isBlank(etcd.get(CHARSET)) ? StandardCharsets.UTF_8 : Charset.forName(etcd.get(CHARSET)); Charset charset = StringUtil.isBlank(etcd.get(CHARSET)) ? StandardCharsets.UTF_8 : Charset.forName(etcd.get(CHARSET));
ClientBuilder clientBuilder = Client.builder().endpoints(endpoints.split(",")); initClient(etcd, charset);
// todo
if (Objects.isNull(client)) {
client = StringUtil.isAllNotEmpty(user, password) ? clientBuilder.user(ByteSequence.from(user, charset))
.password(ByteSequence.from(password, charset)).authority(authority)
.build() : clientBuilder.build();
}
// todo Currently only supports json // todo Currently only supports json
GetResponse getResponse = client.getKVClient().get(ByteSequence.from(key, charset)).get(); GetResponse getResponse = client.getKVClient().get(ByteSequence.from(key, charset)).get();
KeyValue keyValue = getResponse.getKvs().get(0); KeyValue keyValue = getResponse.getKvs().get(0);
@ -100,4 +103,25 @@ public class EtcdRefresherHandler extends AbstractConfigThreadPoolDynamicRefresh
} }
}); });
} }
/**
* if client is null, init it
*
* @param etcd etcd configuration item
* @param charset charset
*/
private void initClient(Map<String, String> etcd, Charset charset) {
// todo
if (Objects.isNull(client)) {
String user = etcd.get(USER);
String password = etcd.get(PASSWORD);
String authority = etcd.get(AUTHORITY);
String endpoints = etcd.get(ENDPOINTS);
ClientBuilder clientBuilder = Client.builder().endpoints(endpoints.split(","));
client = StringUtil.isAllNotEmpty(user, password) ? clientBuilder.user(ByteSequence.from(user, charset))
.password(ByteSequence.from(password, charset)).authority(authority)
.build() : clientBuilder.build();
}
}
} }

@ -31,17 +31,28 @@ import java.util.concurrent.Executor;
@Slf4j @Slf4j
public class NacosCloudRefresherHandler extends AbstractConfigThreadPoolDynamicRefresh { public class NacosCloudRefresherHandler extends AbstractConfigThreadPoolDynamicRefresh {
static final String DATA_ID = "data-id";
static final String GROUP = "group";
private final NacosConfigManager nacosConfigManager; private final NacosConfigManager nacosConfigManager;
public NacosCloudRefresherHandler() { public NacosCloudRefresherHandler() {
nacosConfigManager = ApplicationContextHolder.getBean(NacosConfigManager.class); nacosConfigManager = ApplicationContextHolder.getBean(NacosConfigManager.class);
} }
@Override
public String getProperties() throws Exception {
Map<String, String> nacosConfig = bootstrapConfigProperties.getNacos();
String dataId = nacosConfig.get(DATA_ID);
String group = nacosConfig.get(GROUP);
return nacosConfigManager.getConfigService().getConfig(dataId, group, 5000L);
}
@Override @Override
public void afterPropertiesSet() throws Exception { public void afterPropertiesSet() throws Exception {
Map<String, String> nacosConfig = bootstrapConfigProperties.getNacos(); Map<String, String> nacosConfig = bootstrapConfigProperties.getNacos();
nacosConfigManager.getConfigService().addListener(nacosConfig.get("data-id"), nacosConfigManager.getConfigService().addListener(nacosConfig.get(DATA_ID),
nacosConfig.get("group"), new Listener() { nacosConfig.get(GROUP), new Listener() {
@Override @Override
public Executor getExecutor() { public Executor getExecutor() {
@ -53,6 +64,6 @@ public class NacosCloudRefresherHandler extends AbstractConfigThreadPoolDynamicR
dynamicRefresh(configInfo); dynamicRefresh(configInfo);
} }
}); });
log.info("Dynamic thread pool refresher, add nacos cloud listener success. data-id: {}, group: {}", nacosConfig.get("data-id"), nacosConfig.get("group")); log.info("Dynamic thread pool refresher, add nacos cloud listener success. data-id: {}, group: {}", nacosConfig.get(DATA_ID), nacosConfig.get(GROUP));
} }
} }

@ -32,6 +32,9 @@ import java.util.concurrent.Executor;
@Slf4j @Slf4j
public class NacosRefresherHandler extends AbstractConfigThreadPoolDynamicRefresh { public class NacosRefresherHandler extends AbstractConfigThreadPoolDynamicRefresh {
static final String DATA_ID = "data-id";
static final String GROUP = "group";
@NacosInjected @NacosInjected
private ConfigService configService; private ConfigService configService;
@ -39,11 +42,19 @@ public class NacosRefresherHandler extends AbstractConfigThreadPoolDynamicRefres
super(bootstrapConfigProperties); super(bootstrapConfigProperties);
} }
@Override
public String getProperties() throws Exception {
Map<String, String> nacosConfig = bootstrapConfigProperties.getNacos();
String dataId = nacosConfig.get(DATA_ID);
String group = nacosConfig.get(GROUP);
return configService.getConfig(dataId, group, Long.MAX_VALUE);
}
@Override @Override
public void afterPropertiesSet() throws Exception { public void afterPropertiesSet() throws Exception {
Map<String, String> nacosConfig = bootstrapConfigProperties.getNacos(); Map<String, String> nacosConfig = bootstrapConfigProperties.getNacos();
configService.addListener(nacosConfig.get("data-id"), nacosConfig.get("group"), configService.addListener(nacosConfig.get(DATA_ID), nacosConfig.get(GROUP),
new Listener() { new Listener() {
@Override @Override
@ -56,6 +67,6 @@ public class NacosRefresherHandler extends AbstractConfigThreadPoolDynamicRefres
dynamicRefresh(configInfo); dynamicRefresh(configInfo);
} }
}); });
log.info("Dynamic thread pool refresher, add nacos listener success. data-id: {}, group: {}", nacosConfig.get("data-id"), nacosConfig.get("group")); log.info("Dynamic thread pool refresher, add nacos listener success. data-id: {}, group: {}", nacosConfig.get(DATA_ID), nacosConfig.get(GROUP));
} }
} }

@ -41,15 +41,31 @@ import java.util.Map;
@Slf4j @Slf4j
public class ZookeeperRefresherHandler extends AbstractConfigThreadPoolDynamicRefresh { public class ZookeeperRefresherHandler extends AbstractConfigThreadPoolDynamicRefresh {
static final String ZK_CONNECT_STR = "zk-connect-str";
static final String ROOT_NODE = "root-node";
static final String CONFIG_VERSION = "config-version";
static final String NODE = "node";
private CuratorFramework curatorFramework; private CuratorFramework curatorFramework;
@Override
public String getProperties() {
Map<String, String> zkConfigs = bootstrapConfigProperties.getZookeeper();
String nodePath = ZKPaths.makePath(ZKPaths.makePath(zkConfigs.get(ROOT_NODE),
zkConfigs.get(CONFIG_VERSION)), zkConfigs.get(NODE));
return nodePathResolver(nodePath);
}
@Override @Override
public void afterPropertiesSet() { public void afterPropertiesSet() {
Map<String, String> zkConfigs = bootstrapConfigProperties.getZookeeper(); Map<String, String> zkConfigs = bootstrapConfigProperties.getZookeeper();
curatorFramework = CuratorFrameworkFactory.newClient(zkConfigs.get("zk-connect-str"), curatorFramework = CuratorFrameworkFactory.newClient(zkConfigs.get(ZK_CONNECT_STR),
new ExponentialBackoffRetry(1000, 3)); new ExponentialBackoffRetry(1000, 3));
String nodePath = ZKPaths.makePath(ZKPaths.makePath(zkConfigs.get("root-node"), String nodePath = ZKPaths.makePath(ZKPaths.makePath(zkConfigs.get(ROOT_NODE),
zkConfigs.get("config-version")), zkConfigs.get("node")); zkConfigs.get(CONFIG_VERSION)), zkConfigs.get(NODE));
final ConnectionStateListener connectionStateListener = (client, newState) -> { final ConnectionStateListener connectionStateListener = (client, newState) -> {
if (newState == ConnectionState.CONNECTED) { if (newState == ConnectionState.CONNECTED) {
loadNode(nodePath); loadNode(nodePath);
@ -81,6 +97,20 @@ public class ZookeeperRefresherHandler extends AbstractConfigThreadPoolDynamicRe
* @param nodePath zk config node path. * @param nodePath zk config node path.
*/ */
public void loadNode(String nodePath) { public void loadNode(String nodePath) {
String content = nodePathResolver(nodePath);
if (content != null) {
dynamicRefresh(content);
registerNotifyAlarmManage();
}
}
/**
* resolver for zk config
*
* @param nodePath zk config node path
* @return resolver result
*/
private String nodePathResolver(String nodePath) {
try { try {
final GetChildrenBuilder childrenBuilder = curatorFramework.getChildren(); final GetChildrenBuilder childrenBuilder = curatorFramework.getChildren();
final List<String> children = childrenBuilder.watched().forPath(nodePath); final List<String> children = childrenBuilder.watched().forPath(nodePath);
@ -97,10 +127,10 @@ public class ZookeeperRefresherHandler extends AbstractConfigThreadPoolDynamicRe
} }
content.append(nodeName).append("=").append(value).append("\n"); content.append(nodeName).append("=").append(value).append("\n");
}); });
dynamicRefresh(content.toString()); return content.toString();
registerNotifyAlarmManage();
} catch (Exception ex) { } catch (Exception ex) {
log.error("Load zookeeper node error, nodePath is: {}", nodePath, ex); log.error("Load zookeeper node error, nodePath is: {}", nodePath, ex);
return null;
} }
} }

@ -17,55 +17,15 @@
package cn.hippo4j.config.springboot.starter.refresher.event; package cn.hippo4j.config.springboot.starter.refresher.event;
import cn.hippo4j.adapter.web.WebThreadPoolHandlerChoose; import cn.hippo4j.adapter.web.WebIpAndPortHolder;
import cn.hippo4j.adapter.web.WebThreadPoolService;
import cn.hippo4j.common.config.ApplicationContextHolder;
import cn.hippo4j.common.model.WebIpAndPortInfo;
import cn.hippo4j.common.toolkit.Assert;
import cn.hippo4j.common.toolkit.StringUtil;
import cn.hippo4j.core.toolkit.inet.InetUtils;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import java.util.Arrays;
import java.util.Objects;
/** /**
* Refresh listener abstract base class. * Refresh listener abstract base class.
*/ */
@Slf4j @Slf4j
public abstract class AbstractRefreshListener<M> implements RefreshListener<Hippo4jConfigDynamicRefreshEvent, M> { public abstract class AbstractRefreshListener<M> implements RefreshListener<Hippo4jConfigDynamicRefreshEvent, M> {
protected static final String ALL = "*";
protected static final String SEPARATOR = ",";
/**
* Application ip and application post
*/
protected static volatile WebIpAndPortInfo webIpAndPort;
protected void initIpAndPort() {
if (webIpAndPort == null) {
synchronized (AbstractRefreshListener.class) {
if (webIpAndPort == null) {
webIpAndPort = getWebIpAndPortInfo();
}
}
}
}
private WebIpAndPortInfo getWebIpAndPortInfo() {
InetUtils inetUtils = ApplicationContextHolder.getBean(InetUtils.class);
InetUtils.HostInfo loopBackHostInfo = inetUtils.findFirstNonLoopBackHostInfo();
Assert.notNull(loopBackHostInfo, "Unable to get the application IP address");
String ip = loopBackHostInfo.getIpAddress();
WebThreadPoolHandlerChoose webThreadPoolHandlerChoose = ApplicationContextHolder.getBean(WebThreadPoolHandlerChoose.class);
WebThreadPoolService webThreadPoolService = webThreadPoolHandlerChoose.choose();
// When get the port at startup, can get the message: "port xxx was already in use" or use two ports
String port = String.valueOf(webThreadPoolService.getWebServer().getPort());
return new WebIpAndPortInfo(ip, port);
}
/** /**
* Matching nodes<br> * Matching nodes<br>
* nodes is ip + port.Get 'nodes' in the new Properties,Compare this with the ip + port of Application.<br> * nodes is ip + port.Get 'nodes' in the new Properties,Compare this with the ip + port of Application.<br>
@ -82,19 +42,8 @@ public abstract class AbstractRefreshListener<M> implements RefreshListener<Hipp
*/ */
@Override @Override
public boolean match(M properties) { public boolean match(M properties) {
if (webIpAndPort == null) {
initIpAndPort();
}
String nodes = getNodes(properties); String nodes = getNodes(properties);
if (StringUtil.isEmpty(nodes) || ALL.equals(nodes)) { return WebIpAndPortHolder.check(nodes);
return true;
}
String[] splitNodes = nodes.split(SEPARATOR);
return Arrays.stream(splitNodes)
.distinct()
.map(WebIpAndPortInfo::build)
.filter(Objects::nonNull)
.anyMatch(each -> each.check(webIpAndPort.getIpSegment(), webIpAndPort.getPort()));
} }
/** /**
@ -104,6 +53,6 @@ public abstract class AbstractRefreshListener<M> implements RefreshListener<Hipp
* @return nodes in properties * @return nodes in properties
*/ */
protected String getNodes(M properties) { protected String getNodes(M properties) {
return ALL; return WebIpAndPortHolder.ALL;
} }
} }

@ -56,7 +56,7 @@ public class AdapterExecutorsRefreshListener extends AbstractRefreshListener<Ada
for (AdapterExecutorProperties each : adapterExecutors) { for (AdapterExecutorProperties each : adapterExecutors) {
String buildKey = each.getMark() + IDENTIFY_SLICER_SYMBOL + each.getThreadPoolKey(); String buildKey = each.getMark() + IDENTIFY_SLICER_SYMBOL + each.getThreadPoolKey();
AdapterExecutorProperties adapterExecutorProperties = DynamicThreadPoolAdapterRegister.ADAPTER_EXECUTORS_MAP.get(buildKey); AdapterExecutorProperties adapterExecutorProperties = DynamicThreadPoolAdapterRegister.ADAPTER_EXECUTORS_MAP.get(buildKey);
if (adapterExecutorProperties == null || !match(adapterExecutorProperties)) { if (adapterExecutorProperties == null || !adapterExecutorProperties.getEnable() || !match(adapterExecutorProperties)) {
continue; continue;
} }
if (!Objects.equals(adapterExecutorProperties.getCorePoolSize(), each.getCorePoolSize()) if (!Objects.equals(adapterExecutorProperties.getCorePoolSize(), each.getCorePoolSize())

@ -79,7 +79,7 @@ public class WebExecutorRefreshListener extends AbstractRefreshListener<WebThrea
} else if (bindableCoreProperties.getJetty() != null) { } else if (bindableCoreProperties.getJetty() != null) {
webThreadPoolProperties = bindableCoreProperties.getJetty(); webThreadPoolProperties = bindableCoreProperties.getJetty();
} }
if (webThreadPoolProperties != null && match(webThreadPoolProperties)) { if (webThreadPoolProperties != null && webThreadPoolProperties.getEnable() && match(webThreadPoolProperties)) {
threadPoolParameterInfo = ThreadPoolParameterInfo.builder() threadPoolParameterInfo = ThreadPoolParameterInfo.builder()
.coreSize(webThreadPoolProperties.getCorePoolSize()) .coreSize(webThreadPoolProperties.getCorePoolSize())
.maximumPoolSize(webThreadPoolProperties.getMaximumPoolSize()) .maximumPoolSize(webThreadPoolProperties.getMaximumPoolSize())

@ -338,7 +338,7 @@
<developer> <developer>
<name>chen.ma</name> <name>chen.ma</name>
<email>machen@apache.org</email> <email>machen@apache.org</email>
<url>https://github.com/mabaiwan</url> <url>https://github.com/itmachen</url>
<organization>OpenGoofy</organization> <organization>OpenGoofy</organization>
<organizationUrl>https://github.com/opengoofy</organizationUrl> <organizationUrl>https://github.com/opengoofy</organizationUrl>
<roles> <roles>

Loading…
Cancel
Save