[fix] change
92
CloudClientInternalNetworkPenetration.README.md
Normal file
@ -0,0 +1,92 @@
|
||||
### 内网穿透使用
|
||||
|
||||
#### 模块说明
|
||||
|
||||
| 模块 | 所属层级 | 描述 | 端口 |
|
||||
|------------------------------------------------------------------------------------|------|------------------------|----------------------------------------------------------------|
|
||||
| [wu-smart-agent-network-heartbeat-common](wu-smart-agent-network-heartbeat-common) | 基础模块 | 基于Netty数据解码、编码、通道处理器声明 | 无 |
|
||||
| [wu-smart-agent-network-heartbeat-server](wu-smart-agent-network-heartbeat-server) | 启动模块 | 内网穿透服务端 | http端口:6001、tcp端口:7001 (默认tcp端口=http端口+1000 如:6001+1000=7001) |
|
||||
| [wu-smart-agent-network-heartbeat-client](wu-smart-agent-network-heartbeat-client) | 启动模块 | 内网穿透客户端 | 6004 |
|
||||
|
||||
#### 功能
|
||||
|
||||
1.将局域网IP映射到公网IP
|
||||
2. 支持tcp、http映射
|
||||
|
||||
#### 使用
|
||||
|
||||
```text
|
||||
客户端配置信息
|
||||
```
|
||||
|
||||
```yaml
|
||||
spring:
|
||||
middleground:
|
||||
netty:
|
||||
inet-host: 127.0.0.1 # 服务端地址
|
||||
inet-port: 7001 #服务端端口
|
||||
client-id: local # 客户端ID
|
||||
```
|
||||
|
||||
```text
|
||||
服务端配置客户端映射地址
|
||||
数据库表【internal_network_penetration_mapping】 添加数据
|
||||
```
|
||||
|
||||
| 客户端ID | 客户端真实地址 | 客户端真实端口 | 创建时间 | id | 是否删除 | 更新时间 | 访客端口 | 描述 |
|
||||
|--------------|----------------|---------|------|----|------|------|-------|------------------------------------------------------------|
|
||||
| local | 127.0.0.1 | 18080 | null | 1 | 0 | null | 19080 | 访客通过 --> 19080 --> 访问 --> 客户端 local本地的 18080 |
|
||||
| local | 127.0.0.1 | 28080 | null | 2 | 0 | null | 29080 | 访客通过 --> 29080 --> 访问 --> 客户端 local本地的 28080 |
|
||||
| local | 127.0.0.1 | 3306 | null | 3 | 0 | null | 4306 | 访客通过 --> 4306 --> 访问 --> 客户端 local本地的 3306 |
|
||||
| local | 192.168.17.185 | 80 | null | 4 | 0 | null | 30080 | 访客通过 --> 30080 --> 访问 --> 客户端 local局域网内192.168.17.185的 80 |
|
||||
| middleground | web-nginx | 80 | null | 5 | 0 | null | 31570 | 访客通过 --> 31570 --> 访问 --> 客户端 local局域网内web-nginx的 80 |
|
||||
|
||||
|
||||
|
||||
#### 部署
|
||||
|
||||
##### 云端部署
|
||||
|
||||
```text
|
||||
云端部署:内网穿透服务端
|
||||
如果云端需要部署云上暂存+内网穿透功能:需要部署 内网穿透服务端、暂存服务、内网穿透客户端、云上离线网关
|
||||
```
|
||||
|
||||
| 模块 | 说明 | 部署内网穿透必须 | 部署内网穿透+云上暂存必须 |
|
||||
|------------------------------------------------------------------|------------|----------|---------------|
|
||||
| [wu-smart-agent-network-heartbeat-server](wu-smart-agent-network-heartbeat-server) | 内网穿透+心跳服务端 | ☑️ | ☑️ |
|
||||
| [wu-smart-agent-network-heartbeat-client](wu-smart-agent-network-heartbeat-client) | 内网穿透+心跳客户端 | ✖️ | ☑️ |
|
||||
| [wu-lazy-cloud-staging-provider](wu-lazy-cloud-staging-provider) | 暂存服务 | ✖️ | ☑️ |
|
||||
| [wu-lazy-cloud-central-gateway](wu-lazy-cloud-central-gateway) | 云上暂存网关 | ✖️ | ☑️ |
|
||||
| [wu-lazy-cloud-central-gateway](wu-lazy-cloud-central-gateway) | 云下暂存网关 | ✖️ | ✖️ |
|
||||
|
||||
##### 云网关部署
|
||||
|
||||
```text
|
||||
云网关部署内网穿透客户端
|
||||
```
|
||||
|
||||
| 模块 | 说明 | 部署内网穿透必须 | 部署内网穿透+云上暂存必须 |
|
||||
|------------------------------------------------------------------|------------|----------|---------------|
|
||||
| [wu-smart-agent-network-heartbeat-server](wu-smart-agent-network-heartbeat-server) | 内网穿透+心跳服务端 | ✖️ | ✖️ |
|
||||
| [wu-smart-agent-network-heartbeat-client](wu-smart-agent-network-heartbeat-client) | 内网穿透+心跳客户端 | ✖️ | ☑️ |
|
||||
| [wu-lazy-cloud-staging-provider](wu-lazy-cloud-staging-provider) | 暂存服务 | ✖️ | ✖️ |
|
||||
| [wu-lazy-cloud-central-gateway](wu-lazy-cloud-central-gateway) | 云上暂存网关 | ✖️ | ☑️ |
|
||||
| [wu-lazy-cloud-central-gateway](wu-lazy-cloud-central-gateway) | 云下暂存网关 | ✖️ | ✖️ |
|
||||
|
||||
##### 独立租户部署
|
||||
|
||||
```text
|
||||
拥有内网穿透能力:需要部署内网穿透客户端
|
||||
内网穿透+离线暂存能力: 需要部署内网穿透客户端、离线网关、离线暂存服务
|
||||
```
|
||||
|
||||
| 模块 | 说明 | 部署内网穿透必须 | 部署内网穿透+云上暂存必须 |
|
||||
|------------------------------------------------------------------|------------|----------|---------------|
|
||||
| [wu-smart-agent-network-heartbeat-server](wu-smart-agent-network-heartbeat-server) | 内网穿透+心跳服务端 | ✖️ | ✖️ |
|
||||
| [wu-smart-agent-network-heartbeat-client](wu-smart-agent-network-heartbeat-client) | 内网穿透+心跳客户端 | ☑️ | ☑️ |
|
||||
| [wu-lazy-cloud-staging-provider](wu-lazy-cloud-staging-provider) | 暂存服务 | ✖️ | ☑️ |
|
||||
| [wu-lazy-cloud-central-gateway](wu-lazy-cloud-central-gateway) | 云上暂存网关 | ✖️ | ✖️ |
|
||||
| [wu-lazy-cloud-central-gateway](wu-lazy-cloud-central-gateway) | 云下暂存网关 | ✖️ | ☑️ |
|
||||
|
||||
|
BIN
CloudClientInternalNetworkPenetration1.0-.png
Normal file
After Width: | Height: | Size: 43 KiB |
77
CloudClientInternalNetworkPenetration1.0.puml
Normal file
@ -0,0 +1,77 @@
|
||||
|
||||
|
||||
@startuml
|
||||
|
||||
title 内网穿透
|
||||
|
||||
actor 访客
|
||||
|
||||
package "客户端"{
|
||||
|
||||
|
||||
|
||||
node "Netty客户端" {
|
||||
component [客户端当前通道]{
|
||||
[客户端心跳通道]
|
||||
component [客户端代理通信通道]{
|
||||
[客户端通信通道读数据]
|
||||
[客户端通信通道返回数据]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
' [客户端当前通道] <...right... [客户端真实代理通道]: 返回真实服务请求结果
|
||||
' [客户端当前通道] ...right..> [客户端真实代理通道]: 转发二进制请求到真实服务通道
|
||||
}
|
||||
node “客户端真实服务”{
|
||||
component [客户端需要代理的真实服务A]{
|
||||
[客户端真实通道读数据]
|
||||
[客户端真实通道返回数据]
|
||||
}
|
||||
}
|
||||
|
||||
' [客户端真实代理通道] ...right...> [客户端真实服务]: 发送真实二进制请求到真实服务
|
||||
|
||||
}
|
||||
package "服务端"{
|
||||
node "Netty服务端" {
|
||||
|
||||
component [Netty服务端通道] {
|
||||
component [服务端心跳通道]{
|
||||
|
||||
}
|
||||
component [服务端代理通信通道]{
|
||||
[服务端通信通道读数据]
|
||||
[服务端通信通道返回数据]
|
||||
}
|
||||
}
|
||||
|
||||
component [Netty服务端绑定访客端口] {
|
||||
component [服务端访客真实通道]{
|
||||
[服务端访客真实通道读数据]
|
||||
[服务端访客真实通道返回数据]
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
[服务端心跳通道] <----> [客户端心跳通道]:长连接channel
|
||||
|
||||
|
||||
[访客] ..> [服务端访客真实通道读数据]: 访客访问数据
|
||||
[服务端访客真实通道读数据] ...> [服务端通信通道读数据]: 服务端访客数据转发到通信通道
|
||||
[服务端通信通道读数据] ..down..> [客户端通信通道读数据]: 服务端通信将数据转发到客户端通信通道
|
||||
[客户端通信通道读数据] ..down..> [客户端真实通道读数据]: 客户端通信通道将数据转发道客户端端真实代理通道
|
||||
[客户端真实通道读数据] ..left..> [客户端真实通道返回数据]: 处理数据。。。
|
||||
[客户端真实通道返回数据] ..up..> [客户端通信通道返回数据]: 客户端真实服务返回数据
|
||||
[客户端通信通道返回数据] ..up..> [服务端通信通道返回数据]: 将客户端返回的数据发送给访客真实通道
|
||||
[服务端通信通道返回数据] ..up..> [服务端访客真实通道返回数据]: 返回数据
|
||||
|
||||
|
||||
|
||||
|
||||
@enduml
|
55
Cluster.puml
Normal file
@ -0,0 +1,55 @@
|
||||
@startuml
|
||||
'https://plantuml.com/component-diagram
|
||||
title 网络代理集群模式设计集群初始化 node1 初始化后自动初始化node2
|
||||
|
||||
package "Network Cluster" {
|
||||
|
||||
database "Network DB" {
|
||||
|
||||
}
|
||||
|
||||
node "node1"{
|
||||
|
||||
node "Network Server Node1" {
|
||||
|
||||
}
|
||||
node "Network Client Node1" {
|
||||
|
||||
}
|
||||
|
||||
"Network Server Node1" ----> "Network Server Node1" : 5. rescan node config and register
|
||||
|
||||
"Network Server Node1" --left--> "Network DB" :node1 config story get and use
|
||||
|
||||
' "Network DB" --down-- "Network Client Node1" :node1 config get and use
|
||||
|
||||
"Network Client Node1" --up--> "Network Server Node1" :node1 register
|
||||
|
||||
' "Network Server Node2" --> "Network Client Node1" :scan node config and register
|
||||
}
|
||||
node "node2"{
|
||||
|
||||
node "Network Server Node2" {
|
||||
|
||||
}
|
||||
node "Network Client Node2" {
|
||||
|
||||
}
|
||||
|
||||
"Network Server Node2" ----> "Network Server Node2" : rescan node config and register
|
||||
|
||||
"Network Server Node2" --right--> "Network DB" :1. node2 config story get and use
|
||||
|
||||
' "Network DB" --down--> "Network Client Node2" :node2 config get and use
|
||||
|
||||
"Network Client Node2" --up--> "Network Server Node2" :2. node2 register..
|
||||
"Network Server Node2" --down--> "Network Client Node2" :3. node2 register success
|
||||
|
||||
"Network Client Node2" --left-> "Network Server Node1" :4. send msg to all register server ,tail it scan node config and register
|
||||
' "Network Client Node2" ---> "Network Server Node2" :send msg to all register server ,tail it scan node config and register
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@enduml
|
201
LICENSE
Normal file
@ -0,0 +1,201 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed 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.
|
320
README.md
Normal file
@ -0,0 +1,320 @@
|
||||
<p align="center">
|
||||
<a target="_blank" href="https://search.maven.org/search?q=wu-smart-agent-network%20wu-smart-agent-network">
|
||||
<img src="https://img.shields.io/nexus/s/top.wu2020/wu-smart-agent-network?server=https%3A%2F%2Foss.sonatype.org&style=flat&logo=log" alt="Maven" />
|
||||
</a>
|
||||
<a target="_blank" href="https://search.maven.org/search?q=wu-smart-agent-network%20wu-smart-agent-network">
|
||||
<img src="https://img.shields.io/maven-central/v/top.wu2020/wu-smart-agent-network" alt="Maven" />
|
||||
</a>
|
||||
<a target="_blank" href="https://www.apache.org/licenses/LICENSE-2.0.txt">
|
||||
<img src="https://img.shields.io/:license-Apache2-blue.svg" alt="Apache 2" />
|
||||
</a>
|
||||
<a target="_blank" href="https://www.oracle.com/java/technologies/javase/jdk11-archive-downloads.html">
|
||||
<img src="https://img.shields.io/badge/JDK-11-green.svg" alt="jdk-11" />
|
||||
</a>
|
||||
<a target="_blank" href="https://www.oracle.com/java/technologies/javase/jdk17-archive-downloads.html">
|
||||
<img src="https://img.shields.io/badge/JDK-17-green.svg" alt="jdk-17" />
|
||||
</a>
|
||||
<br />
|
||||
<img src="https://img.shields.io/badge/SpringBoot-v3.x-blue">
|
||||
<br />
|
||||
<a target="_blank" href='https://gitee.com/wujiawei1207537021/wu-smart-agent-network'>
|
||||
<img src='https://gitee.com/wujiawei1207537021/wu-smart-agent-network/badge/star.svg' alt='Gitee star'/>
|
||||
</a>
|
||||
<a target="_blank" href='https://gitee.com/wujiawei1207537021/wu-smart-agent-network'>
|
||||
<img src='https://img.shields.io/github/stars/wujiawei1207537021/wu-smart-agent-network?style=flat&logo=github' alt='GitHub star'/>
|
||||
</a>
|
||||
<a target="_blank" href='https://gitee.com/wujiawei1207537021/wu-smart-agent-network'>
|
||||
<img src='https://img.shields.io/github/forks/wujiawei1207537021/wu-smart-agent-network?style=flat&logo=github' alt='GitHub star'/>
|
||||
</a>
|
||||
|
||||
</p>
|
||||
|
||||
#### 项目介绍
|
||||
|
||||
wu-smart-agent-network
|
||||
是一款基于([wu-framework-parent](https://gitee.com/wujiawei1207537021/wu-framework-parent))孵化出的项目,内部使用Lazy
|
||||
ORM操作数据库,主要功能是网络穿透,对于没有公网IP的服务进行公网IP映射
|
||||
使用环境JDK17 Spring Boot 3.0.2
|
||||
|
||||
#### 项目地址
|
||||
|
||||
[Gitee](https://gitee.com/wujiawei1207537021/wu-smart-agent-network)
|
||||
|
||||
[GitHub](https://github.com/wujiawei1207537021/wu-smart-agent-network)
|
||||
|
||||
#### 架构图
|
||||
|
||||

|
||||
|
||||
#### 实现原理
|
||||
|
||||
##### 服务端创建socket服务端绑定本地端口(用于客户端连接)
|
||||
|
||||
```java
|
||||
package org.framework.smart.agent.network.heartbeat.server.netty.socket;
|
||||
|
||||
|
||||
import io.netty.bootstrap.ServerBootstrap;
|
||||
import io.netty.channel.ChannelFuture;
|
||||
import io.netty.channel.ChannelFutureListener;
|
||||
import io.netty.channel.ChannelOption;
|
||||
import io.netty.channel.EventLoopGroup;
|
||||
import io.netty.channel.nio.NioEventLoopGroup;
|
||||
import io.netty.channel.socket.nio.NioServerSocketChannel;
|
||||
import org.framework.smart.agent.network.heartbeat.server.netty.filter.NettyServerFilter;
|
||||
|
||||
public class NettyOnCloudNettyServerSocket {
|
||||
private final EventLoopGroup bossGroup = new NioEventLoopGroup();
|
||||
private final EventLoopGroup workerGroup = new NioEventLoopGroup();
|
||||
private final NettyServerFilter nettyServerFilter;// 通道业务处理
|
||||
private ChannelFuture channelFuture;
|
||||
|
||||
public NettyOnCloudNettyServerSocket(NettyServerFilter nettyServerFilter) {
|
||||
this.nettyServerFilter = nettyServerFilter;
|
||||
}
|
||||
|
||||
/**
|
||||
* 启动服务端
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public void startServer(int serverPort) throws Exception {
|
||||
try {
|
||||
|
||||
ServerBootstrap b = new ServerBootstrap();
|
||||
b.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class)
|
||||
// 给服务端channel设置属性
|
||||
.option(ChannelOption.SO_BACKLOG, 128)
|
||||
|
||||
.childOption(ChannelOption.SO_KEEPALIVE, true)
|
||||
.childHandler(nettyServerFilter)
|
||||
;
|
||||
channelFuture = b.bind(serverPort).sync();
|
||||
|
||||
channelFuture.addListener((ChannelFutureListener) channelFuture -> {
|
||||
// 服务器已启动
|
||||
});
|
||||
channelFuture.channel().closeFuture().sync();
|
||||
} finally {
|
||||
shutdown();
|
||||
// 服务器已关闭
|
||||
}
|
||||
}
|
||||
|
||||
public void shutdown() {
|
||||
if (channelFuture != null) {
|
||||
channelFuture.channel().close().syncUninterruptibly();
|
||||
}
|
||||
if ((bossGroup != null) && (!bossGroup.isShutdown())) {
|
||||
bossGroup.shutdownGracefully();
|
||||
}
|
||||
if ((workerGroup != null) && (!workerGroup.isShutdown())) {
|
||||
workerGroup.shutdownGracefully();
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
##### 客户端通过class NettyClientSocket 连接服务端
|
||||
|
||||
```java
|
||||
package org.framework.smart.agent.network.heartbeat.client.netty.socket;
|
||||
|
||||
|
||||
import io.netty.bootstrap.Bootstrap;
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelFuture;
|
||||
import io.netty.channel.ChannelFutureListener;
|
||||
import io.netty.channel.EventLoopGroup;
|
||||
import io.netty.channel.nio.NioEventLoopGroup;
|
||||
import io.netty.channel.socket.nio.NioSocketChannel;
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.framework.smart.agent.network.heartbeat.client.application.ClientChangeEvent;
|
||||
import org.framework.smart.agent.network.heartbeat.client.netty.filter.NettyClientFilter;
|
||||
import org.framework.smart.agent.network.heartbeat.common.MessageType;
|
||||
import org.framework.smart.agent.network.heartbeat.common.NettyProxyMsg;
|
||||
import org.framework.smart.agent.network.heartbeat.common.adapter.ChannelTypeAdapter;
|
||||
import org.framework.smart.agent.network.heartbeat.common.advanced.HandleChannelTypeAdvanced;
|
||||
import org.framework.smart.agent.network.heartbeat.common.utils.ChannelAttributeKeyUtils;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* 客户端连接服务端
|
||||
*/
|
||||
@Slf4j
|
||||
public class NettyClientSocket {
|
||||
private static final EventLoopGroup eventLoopGroup = new NioEventLoopGroup();
|
||||
/**
|
||||
* 服务端host
|
||||
*/
|
||||
private final String inetHost;
|
||||
/**
|
||||
* 服务端端口
|
||||
*/
|
||||
private final int inetPort;
|
||||
/**
|
||||
* 当前客户端id
|
||||
*/
|
||||
@Getter
|
||||
private final String clientId;
|
||||
/**
|
||||
* nacos配置信息处理应用
|
||||
*/
|
||||
@Getter
|
||||
private final ClientNettyConfigApplication clientChangeEvent;
|
||||
private final List<HandleChannelTypeAdvanced> handleChannelTypeAdvancedList; // 处理服务端发送过来的数据类型
|
||||
|
||||
public NettyClientSocket(String inetHost, int inetPort, String clientId, ClientNettyConfigApplication clientChangeEvent, List<HandleChannelTypeAdvanced> handleChannelTypeAdvancedList) {
|
||||
this.inetHost = inetHost;
|
||||
this.inetPort = inetPort;
|
||||
this.clientId = clientId;
|
||||
this.clientChangeEvent = clientChangeEvent;
|
||||
this.handleChannelTypeAdvancedList = handleChannelTypeAdvancedList;
|
||||
}
|
||||
|
||||
public void newConnect2Server() throws InterruptedException {
|
||||
newConnect2Server(inetHost, inetPort, clientId, clientChangeEvent);
|
||||
}
|
||||
|
||||
protected void newConnect2Server(String inetHost, int inetPort, String clientId, ClientNettyConfigApplication clientChangeEvent) throws InterruptedException {
|
||||
Bootstrap bootstrap = new Bootstrap();
|
||||
bootstrap.group(eventLoopGroup)
|
||||
.channel(NioSocketChannel.class)
|
||||
.handler(new NettyClientFilter(new ChannelTypeAdapter(handleChannelTypeAdvancedList), this))
|
||||
;
|
||||
|
||||
log.info("连接服务端IP:{},连接服务端端口:{}", inetHost, inetPort);
|
||||
ChannelFuture future = bootstrap.connect(inetHost, inetPort);
|
||||
Channel channel = future.channel();
|
||||
|
||||
log.info("使用的客户端ID:" + clientId);
|
||||
future.addListener((ChannelFutureListener) futureListener -> {
|
||||
if (futureListener.isSuccess()) {
|
||||
|
||||
log.info("连接服务端成功");
|
||||
// 告诉服务端这条连接是client的连接
|
||||
NettyProxyMsg nettyMsg = new NettyProxyMsg();
|
||||
nettyMsg.setType(MessageType.REPORT_CLIENT_CONNECT_SUCCESS);
|
||||
nettyMsg.setClientId(clientId);
|
||||
nettyMsg.setData((clientId).getBytes());
|
||||
ChannelAttributeKeyUtils.buildClientId(channel, clientId);
|
||||
channel.writeAndFlush(nettyMsg);
|
||||
// 在线
|
||||
clientChangeEvent.clientOnLine(clientId);
|
||||
} else {
|
||||
log.info("每隔2s重连....");
|
||||
// 离线
|
||||
clientChangeEvent.clientOffLine(clientId);
|
||||
futureListener.channel().eventLoop().schedule(() -> {
|
||||
try {
|
||||
newConnect2Server(inetHost, inetPort, clientId, clientChangeEvent);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}, 2, TimeUnit.SECONDS);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭连接
|
||||
*/
|
||||
|
||||
public void shutdown() {
|
||||
if ((eventLoopGroup != null) && (!eventLoopGroup.isShutdown())) {
|
||||
eventLoopGroup.shutdownGracefully();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
##### 通过客户端与服务端建立的连接进行访客端口绑定
|
||||
|
||||
上述连接会形成一个channel,我们称之为通道(本文中简单叫**心跳通道**)
|
||||
第一步 页面GUI进行新增访客端口而后将访客端口与客户端绑定(如果客户端已经启动,使用页面客户端下线触发第二步)
|
||||
第二步 客户端与访客端口绑定后使用**心跳通道** 发送客户端告诉客户端,你帮我绑定你本地真实端口
|
||||
第三步 访客访问,访客通过访客端口访问数据,此时访客通道打开截取访客发送的数据,然后将数据发送给客户真实通道,数据返回后再返回给访客通道
|
||||
|
||||
### 功能
|
||||
|
||||
1.内网穿透
|
||||
2.服务端自主下发数据到客户端
|
||||
3.流量监控
|
||||
|
||||
### 项目结构
|
||||
|
||||
| 模块 | 版本 | 描述 |
|
||||
|-----------------------------------------------------------------------------------------------------------------------------------------|----------------------|------------------------------|
|
||||
| [wu-smart-agent-network-heartbeat-common](wu-smart-agent-network-heartbeat-common) | 1.2.6-JDK17-SNAPSHOT | 内网穿透公共模块(声明接口、枚举、常量、适配器、解析器) |
|
||||
| [wu-smart-agent-network-heartbeat-client](wu-smart-agent-network-heartbeat-client) | 1.2.6-JDK17-SNAPSHOT | 客户端(支持二次开发) |
|
||||
| [wu-smart-agent-network-heartbeat-server](wu-smart-agent-network-heartbeat-server) | 1.2.6-JDK17-SNAPSHOT | 服务端(支持二次开发) |
|
||||
| [wu-smart-agent-network-ui](wu-smart-agent-network-heartbeat-server-ui) | 1.2.6-JDK17-SNAPSHOT | 服务端页面 |
|
||||
| [wu-smart-agent-network-heartbeat-client-start](wu-smart-agent-network-heartbeat-sample/wu-smart-agent-network-heartbeat-client-sample) | 1.2.6-JDK17-SNAPSHOT | 客户端样例 |
|
||||
| [wu-smart-agent-network-heartbeat-server-start](wu-smart-agent-network-heartbeat-sample/wu-smart-agent-network-heartbeat-server-sample) | 1.2.6-JDK17-SNAPSHOT | 服务端样例 |
|
||||
|
||||
### 使用技术
|
||||
|
||||
| 框架 | 版本 | 描述 |
|
||||
|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------|--------------|
|
||||
| spring-boot | 3.0.7 | springboot框架 |
|
||||
| [wu-framework-web](https://gitee.com/wujiawei1207537021/wu-framework-parent/tree/master/wu-framework-web) | 1.2.6-JDK17-SNAPSHOT | web容器 |
|
||||
| [Lazy -ORM](https://gitee.com/wujiawei1207537021/wu-framework-parent/tree/master/wu-inner-intergration/wu-database-parent) | 1.2.6-JDK17-SNAPSHOT | ORM |
|
||||
| mysql-connector-j | 8.0.33 | mysql驱动 |
|
||||
| [wu-authorization-server-platform-starter](https://gitee.com/wujiawei1207537021/wu-framework-parent/tree/master/wu-smart-platform/wu-authorization-server-platform-starter) | 1.2.6-JDK17-SNAPSHOT | 用户授权体系 |
|
||||
|
||||
### 使用环境
|
||||
|
||||
IDEA
|
||||
Mac、Windows
|
||||
JAVA >=13
|
||||
MAVEN
|
||||
|
||||
### 启动
|
||||
|
||||
docker启动
|
||||
|
||||
docker run -d -it -p 18080:18080 --name wu-smart-agent-network-heartbeat-server registry.cn-hangzhou.aliyuncs.com/wu-lazy/wu-smart-agent-network-heartbeat-server:1.2.6-JDK17-SNAPSHOT
|
||||
|
||||
http://127.0.0.1:18080/swagger-ui/index.html
|
||||
|
||||
源码启动
|
||||
|
||||
#### 页面操作
|
||||
|
||||
启动项目后打开服务端界面
|
||||

|
||||
|
||||
默认账号密码:admin/admin
|
||||

|
||||
|
||||
初始化项目
|
||||

|
||||
添加角色
|
||||

|
||||
为用户授权
|
||||

|
||||
|
||||
刷新页面
|
||||

|
||||
|
||||
客户端管理(客户端会自动注册)
|
||||

|
||||
|
||||
网络映射管理(修改后者新增需要映射的客户端)
|
||||

|
||||
|
||||
访客端口池管理(服务器端需要开放的端口)
|
||||

|
||||
|
||||
流量管理(每个客户端使用的流量)
|
||||

|
||||
|
||||
流量日统计报表
|
||||

|
||||
|
||||
客户端近七天使用流量
|
||||

|
BIN
architecture.png
Normal file
After Width: | Height: | Size: 108 KiB |
BIN
authRoe2User.png
Normal file
After Width: | Height: | Size: 93 KiB |
BIN
clientPerDayFlow.png
Normal file
After Width: | Height: | Size: 200 KiB |
BIN
clientPortPerDayFlow.png
Normal file
After Width: | Height: | Size: 219 KiB |
BIN
cloud_client.png
Normal file
After Width: | Height: | Size: 113 KiB |
BIN
init_menu.png
Normal file
After Width: | Height: | Size: 84 KiB |
BIN
init_role.png
Normal file
After Width: | Height: | Size: 124 KiB |
BIN
k8s-node-pod-network-k8snodepod.png
Normal file
After Width: | Height: | Size: 34 KiB |
50
k8s-node-pod-network.puml
Normal file
@ -0,0 +1,50 @@
|
||||
@startuml
|
||||
'https://plantuml.com/component-diagram
|
||||
title k8s中node中的pod之间通讯
|
||||
|
||||
package "k8s node pod" {
|
||||
|
||||
node "node1 "{
|
||||
|
||||
node "node1-pod1" {
|
||||
|
||||
}
|
||||
node "node1-pod2" {
|
||||
|
||||
}
|
||||
"node1-pod1" ---- "node1-pod2" :正常
|
||||
|
||||
}
|
||||
node "node2(问题节点)"{
|
||||
|
||||
node "node2-pod1" {
|
||||
|
||||
|
||||
}
|
||||
node "node2-pod2" {
|
||||
|
||||
}
|
||||
"node2-pod1" --right-- "node2-pod2" :正常
|
||||
"node1-pod1" -- "node2-pod1" :无法通信
|
||||
"node1-pod1" -- "node2-pod2" :无法通信
|
||||
|
||||
}
|
||||
node "node3"{
|
||||
|
||||
node "node3-pod1" {
|
||||
|
||||
|
||||
}
|
||||
node "node3-pod2" {
|
||||
|
||||
}
|
||||
"node3-pod1" ---- "node3-pod2" :正常
|
||||
"node3-pod1" -- "node2-pod1" :正常
|
||||
"node3-pod1" -- "node2-pod2" :正常
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@enduml
|
BIN
mapping.png
Normal file
After Width: | Height: | Size: 148 KiB |
259
pom.xml
Normal file
@ -0,0 +1,259 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
<parent>
|
||||
<artifactId>wu-framework-parent</artifactId>
|
||||
<groupId>top.wu2020</groupId>
|
||||
<version>1.2.6-JDK17-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>wu-smart-agent-network</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
<version>1.2.6-JDK17-SNAPSHOT</version>
|
||||
<description>云上云下</description>
|
||||
|
||||
|
||||
<modules>
|
||||
<!-- 云上服务组件 -->
|
||||
<module>wu-smart-agent-network-heartbeat-server</module>
|
||||
<module>wu-smart-agent-network-heartbeat-server-cluster</module>
|
||||
<module>wu-smart-agent-network-heartbeat-client</module>
|
||||
<module>wu-smart-agent-network-heartbeat-common</module>
|
||||
|
||||
<!-- 样例 -->
|
||||
<module>wu-smart-agent-network-heartbeat-start</module>
|
||||
</modules>
|
||||
|
||||
<properties>
|
||||
|
||||
</properties>
|
||||
<dependencies>
|
||||
<!-- mapstruct -->
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>1.18.32</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok-mapstruct-binding</artifactId>
|
||||
<version>0.2.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mapstruct</groupId>
|
||||
<artifactId>mapstruct</artifactId>
|
||||
<version>1.6.0.Beta1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mapstruct</groupId>
|
||||
<artifactId>mapstruct-processor</artifactId>
|
||||
<version>1.6.0.Beta1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-configuration-processor</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>top.wu2020</groupId>
|
||||
<artifactId>wu-framework-dependencies</artifactId>
|
||||
<version>1.2.6-JDK17-SNAPSHOT</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>maven_central</id>
|
||||
<name>Maven Central</name>
|
||||
<url>https://repo.maven.apache.org/maven2/</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>oss</id>
|
||||
<build>
|
||||
<plugins>
|
||||
<!-- Source -->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-source-plugin</artifactId>
|
||||
<version>3.2.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>jar-no-fork</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<!-- Javadoc -->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<version>3.2.0</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>jar</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<locale>en_US</locale>
|
||||
<encoding>UTF-8</encoding>
|
||||
<charset>UTF-8</charset>
|
||||
<doclint>none</doclint>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<!-- GPG -->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-gpg-plugin</artifactId>
|
||||
<version>${maven-gpg-plugin.version}</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>verify</phase>
|
||||
<goals>
|
||||
<goal>sign</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<!-- flatten -->
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>flatten-maven-plugin</artifactId>
|
||||
<version>${flatten-maven-plugin.version}</version>
|
||||
<configuration>
|
||||
<updatePomFile>true</updatePomFile>
|
||||
<flattenMode>resolveCiFriendliesOnly</flattenMode>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>flatten</id>
|
||||
<phase>process-resources</phase>
|
||||
<goals>
|
||||
<goal>flatten</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>flatten.clean</id>
|
||||
<phase>clean</phase>
|
||||
<goals>
|
||||
<goal>clean</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<!-->发布的地址<-->
|
||||
<distributionManagement>
|
||||
<snapshotRepository>
|
||||
<id>snapshots</id>
|
||||
<url>https://oss.sonatype.org/content/repositories/snapshots/</url>
|
||||
</snapshotRepository>
|
||||
<repository>
|
||||
<id>snapshots</id>
|
||||
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
|
||||
</repository>
|
||||
</distributionManagement>
|
||||
</profile>
|
||||
|
||||
|
||||
<profile>
|
||||
<id>snapshots</id>
|
||||
<!-->发布的地址<-->
|
||||
<distributionManagement>
|
||||
<snapshotRepository>
|
||||
<id>maven-snapshots</id>
|
||||
<name>deployment</name>
|
||||
<url>http://192.168.17.221:31004/repository/maven-snapshots/</url>
|
||||
</snapshotRepository>
|
||||
<repository>
|
||||
<id>maven-releases</id>
|
||||
<name>deployment</name>
|
||||
<url>http://192.168.17.221:31004/repository/maven-releases/</url>
|
||||
</repository>
|
||||
</distributionManagement>
|
||||
</profile>
|
||||
<profile>
|
||||
<id>native</id>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.graalvm.buildtools</groupId>
|
||||
<artifactId>native-maven-plugin</artifactId>
|
||||
<version>0.9.28</version>
|
||||
<!-- 使用graalvm提供的可达性元数据,很多第三方库就直接可以构建成可执行文件了 -->
|
||||
<configuration>
|
||||
<!-- for agent -->
|
||||
<agent>
|
||||
<defaultMode>Standard</defaultMode>
|
||||
<options>
|
||||
<builtinCallerFilter>true</builtinCallerFilter>
|
||||
<builtinHeuristicFilter>true</builtinHeuristicFilter>
|
||||
<enableExperimentalPredefinedClasses>true
|
||||
</enableExperimentalPredefinedClasses>
|
||||
<enableExperimentalUnsafeAllocationTracing>true
|
||||
</enableExperimentalUnsafeAllocationTracing>
|
||||
<trackReflectionMetadata>true</trackReflectionMetadata>
|
||||
</options>
|
||||
<metadataCopy>
|
||||
<merge>true</merge>
|
||||
</metadataCopy>
|
||||
</agent>
|
||||
<!-- for metadata repository -->
|
||||
<metadataRepository>
|
||||
<enabled>true</enabled>
|
||||
</metadataRepository>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>add-reachability-metadata</id>
|
||||
<goals>
|
||||
<goal>add-reachability-metadata</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>test-native</id>
|
||||
<goals>
|
||||
<goal>test</goal>
|
||||
</goals>
|
||||
<phase>test</phase>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>build-native</id>
|
||||
<goals>
|
||||
<goal>compile-no-fork</goal>
|
||||
</goals>
|
||||
<phase>package</phase>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
</profiles>
|
||||
|
||||
|
||||
</project>
|
BIN
url_info.png
Normal file
After Width: | Height: | Size: 428 KiB |
11
version.md
Normal file
@ -0,0 +1,11 @@
|
||||
### 版本更新
|
||||
#### 1.2.3-JDK17-SNAPSHOT
|
||||
【fix】修正流量计算保存两位小数
|
||||
[fix] 添加配置spring.lazy.netty.enable 控制是否开启客户端默认是自动连接服务端的 需要手动关闭
|
||||
|
||||
|
||||
#### 1.2.6-JDK17-SNAPSHOT
|
||||
[fix] 客户端添加按钮删除
|
||||
[fix] 修改浏览器title内网穿透
|
||||
[fix] HandleChannelTypeAdvanced 添加权重 order 越小越靠前
|
||||
[fix] 新增网络映射新增、修改、删除、自动变更
|
BIN
visitor_port.png
Normal file
After Width: | Height: | Size: 115 KiB |
22
wu-smart-agent-network-heartbeat-client/Dockerfile
Normal file
@ -0,0 +1,22 @@
|
||||
FROM registry.cn-hangzhou.aliyuncs.com/wu-lazy/wu-framework-parent:jdk-17.0.7-x64
|
||||
MAINTAINER wujiawei <1207537021@qq.com>
|
||||
|
||||
RUN echo "Asia/Shanghai" > /etc/timezone
|
||||
|
||||
|
||||
|
||||
ENV APP_JAR_NAME=$APP_NAME \
|
||||
JAVA_OPTS="-Xms512m -Xmx1024m -Djava.security.egd=file:/dev/./urandom" \
|
||||
PARAMS=""
|
||||
|
||||
|
||||
COPY target/*.jar /app.jar
|
||||
|
||||
|
||||
|
||||
ENTRYPOINT exec java -server $JAVA_OPTS -jar /app.jar $PARAMS
|
||||
|
||||
|
||||
|
||||
|
||||
|
16
wu-smart-agent-network-heartbeat-client/Native-Dockerfile
Normal file
@ -0,0 +1,16 @@
|
||||
FROM alpine
|
||||
|
||||
MAINTAINER wujiawei <1207537021@qq.com>
|
||||
|
||||
RUN echo "Asia/Shanghai" > /etc/timezone
|
||||
|
||||
|
||||
COPY target/lazy-cloud-heartbeat-client /native-app
|
||||
|
||||
ENTRYPOINT ["/bin/sh" ,"-c", "exec ./native-app"]
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
55
wu-smart-agent-network-heartbeat-client/README.md
Normal file
@ -0,0 +1,55 @@
|
||||
#### 构建native 镜像
|
||||
|
||||
```shell
|
||||
mvn clean compile
|
||||
mvn spring-boot:process-aot -Pnative
|
||||
|
||||
mvn native:build -Pnative
|
||||
```
|
||||
|
||||
### 构建docker镜像
|
||||
|
||||
```shell
|
||||
docker build -t docker-registry.wujiawei.com/lazy/lazy-under-cloud-heartbeat-client:lazy-2.4.2-native-SNAPSHOT_latest -f Native-Dockerfile .
|
||||
docker push docker-registry.wujiawei.com/lazy/lazy-under-cloud-heartbeat-client:lazy-2.4.2-native-SNAPSHOT_latest
|
||||
```
|
||||
|
||||
## BUILD IMAGE
|
||||
|
||||
```shell
|
||||
|
||||
#docker login --username=1207537021@qq.com registry.cn-hangzhou.aliyuncs.com
|
||||
|
||||
docker build -t registry.cn-hangzhou.aliyuncs.com/wu-lazy/wu-smart-agent-network-heartbeat-client:server-jdk17-master .
|
||||
docker push registry.cn-hangzhou.aliyuncs.com/wu-lazy/wu-smart-agent-network-heartbeat-client:server-jdk17-master
|
||||
|
||||
```
|
||||
|
||||
### run
|
||||
|
||||
```shell
|
||||
docker run -d -it --name client -e spring.lazy.netty.inet-host=124.222.48.62 -e spring.lazy.netty.inet-port=30676 -e spring.lazy.netty.client-id=node1 registry.cn-hangzhou.aliyuncs.com/wu-lazy/wu-smart-agent-network-heartbeat-client:server-jdk17-master
|
||||
|
||||
|
||||
|
||||
```
|
||||
|
||||
```shell
|
||||
gu install native-image
|
||||
|
||||
gu list
|
||||
|
||||
mvn native:build
|
||||
```
|
||||
|
||||
```shell
|
||||
mvn clean native:compile -Pnative
|
||||
```
|
||||
|
||||
```RUN
|
||||
docker run -d -it -p 18080:18080 --name wu-smart-agent-network-heartbeat-client registry.cn-hangzhou.aliyuncs.com/wu-lazy/wu-smart-agent-network-heartbeat-client:server-jdk17-master
|
||||
|
||||
http://127.0.0.1:18080/swagger-ui/index.html
|
||||
|
||||
|
||||
```
|
56
wu-smart-agent-network-heartbeat-client/pom.xml
Normal file
@ -0,0 +1,56 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<groupId>top.wu2020</groupId>
|
||||
<artifactId>wu-smart-agent-network</artifactId>
|
||||
<version>1.2.6-JDK17-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>wu-smart-agent-network-heartbeat-client</artifactId>
|
||||
<description>云下心跳客户端</description>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<!-- 通用心跳包 -->
|
||||
<dependency>
|
||||
<groupId>top.wu2020</groupId>
|
||||
<artifactId>wu-smart-agent-network-heartbeat-common</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>fastjson</artifactId>
|
||||
<version>2.0.50</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>top.wu2020</groupId>
|
||||
<artifactId>wu-framework-web-spring-starter</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- h2数据库驱动 -->
|
||||
<dependency>
|
||||
<groupId>com.h2database</groupId>
|
||||
<artifactId>h2</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>top.wu2020</groupId>
|
||||
<artifactId>wu-database-lazy-plus-starter</artifactId>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>maven_central</id>
|
||||
<name>Maven Central</name>
|
||||
<url>https://repo.maven.apache.org/maven2/</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
|
||||
</project>
|
@ -0,0 +1,9 @@
|
||||
package org.framework.smart.agent.network.heartbeat.client;
|
||||
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.wu.framework.lazy.orm.core.stereotype.LazyScan;
|
||||
|
||||
@ComponentScan(basePackages = "org.framework.smart.agent.network.heartbeat.client")
|
||||
@LazyScan(scanBasePackages = "org.framework.smart.agent.network.heartbeat.client.infrastructure.entity")
|
||||
public class EnableHeartbeatClientAutoConfiguration {
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
package org.framework.smart.agent.network.heartbeat.client.application;
|
||||
|
||||
|
||||
import org.framework.smart.agent.network.heartbeat.client.netty.event.ClientChangeEvent;
|
||||
|
||||
/**
|
||||
* 客户端状态变更事件
|
||||
* @see ClientChangeEvent
|
||||
*/
|
||||
@Deprecated
|
||||
public interface ClientChangeApplication {
|
||||
|
||||
|
||||
/**
|
||||
* 推送客户端在线
|
||||
*/
|
||||
void clientOnLine(String clientId);
|
||||
|
||||
/**
|
||||
* 推送客户端在线
|
||||
* @param clientId 客户端
|
||||
* @param inetHost 服务端ip
|
||||
* @param inetPort 服务端端口
|
||||
*/
|
||||
void clientOnLine(String inetHost, int inetPort,String clientId);
|
||||
|
||||
/**
|
||||
* 推送客户端离线
|
||||
*/
|
||||
void clientOffLine(String clientId);
|
||||
|
||||
/**
|
||||
* 推送客户端离线
|
||||
* @param clientId 客户端
|
||||
* @param inetHost 服务端ip
|
||||
* @param inetPort 服务端端口
|
||||
*/
|
||||
void clientOffLine(String inetHost, int inetPort,String clientId);
|
||||
|
||||
/**
|
||||
* 暂存开启
|
||||
*
|
||||
* @param clientId 租户ID
|
||||
*/
|
||||
void stagingOpen(String clientId);
|
||||
|
||||
|
||||
/**
|
||||
* 暂存关闭
|
||||
*
|
||||
* @param clientId 客户端ID 对应的租户
|
||||
*/
|
||||
void stagingClose(String clientId);
|
||||
}
|
@ -0,0 +1,128 @@
|
||||
package org.framework.smart.agent.network.heartbeat.client.application;
|
||||
|
||||
import org.wu.framework.web.response.Result;
|
||||
import org.framework.smart.agent.network.heartbeat.client.domain.model.lazy.netty.server.properties.LazyNettyServerProperties;
|
||||
import org.framework.smart.agent.network.heartbeat.client.application.command.lazy.netty.server.properties.LazyNettyServerPropertiesRemoveCommand;
|
||||
import org.framework.smart.agent.network.heartbeat.client.application.command.lazy.netty.server.properties.LazyNettyServerPropertiesStoryCommand;
|
||||
import org.framework.smart.agent.network.heartbeat.client.application.command.lazy.netty.server.properties.LazyNettyServerPropertiesUpdateCommand;
|
||||
import org.framework.smart.agent.network.heartbeat.client.application.command.lazy.netty.server.properties.LazyNettyServerPropertiesQueryListCommand;
|
||||
import org.framework.smart.agent.network.heartbeat.client.application.command.lazy.netty.server.properties.LazyNettyServerPropertiesQueryOneCommand;
|
||||
import org.framework.smart.agent.network.heartbeat.client.application.dto.LazyNettyServerPropertiesDTO;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.wu.framework.lazy.orm.database.lambda.domain.LazyPage;
|
||||
|
||||
/**
|
||||
* describe 服务端配置信息
|
||||
*
|
||||
* @author Jia wei Wu
|
||||
* @date 2024/04/03 03:00 下午
|
||||
* @see org.wu.framework.lazy.orm.core.persistence.reverse.lazy.ddd.DefaultDDDLazyApplication
|
||||
**/
|
||||
|
||||
public interface LazyNettyServerPropertiesApplication {
|
||||
|
||||
|
||||
/**
|
||||
* describe 新增服务端配置信息
|
||||
*
|
||||
* @param lazyNettyServerPropertiesStoryCommand 新增服务端配置信息
|
||||
* @return {@link Result<LazyNettyServerProperties>} 服务端配置信息新增后领域对象
|
||||
* @author Jia wei Wu
|
||||
* @date 2024/04/03 03:00 下午
|
||||
**/
|
||||
|
||||
Result<LazyNettyServerProperties> story(LazyNettyServerPropertiesStoryCommand lazyNettyServerPropertiesStoryCommand);
|
||||
|
||||
/**
|
||||
* describe 批量新增服务端配置信息
|
||||
*
|
||||
* @param lazyNettyServerPropertiesStoryCommandList 批量新增服务端配置信息
|
||||
* @return {@link Result<List<LazyNettyServerProperties>>} 服务端配置信息新增后领域对象集合
|
||||
* @author Jia wei Wu
|
||||
* @date 2024/04/03 03:00 下午
|
||||
**/
|
||||
|
||||
Result<List<LazyNettyServerProperties>> batchStory(List<LazyNettyServerPropertiesStoryCommand> lazyNettyServerPropertiesStoryCommandList);
|
||||
|
||||
/**
|
||||
* describe 更新服务端配置信息
|
||||
*
|
||||
* @param lazyNettyServerPropertiesUpdateCommand 更新服务端配置信息
|
||||
* @return {@link Result<LazyNettyServerProperties>} 服务端配置信息领域对象
|
||||
* @author Jia wei Wu
|
||||
* @date 2024/04/03 03:00 下午
|
||||
**/
|
||||
|
||||
Result<LazyNettyServerProperties> updateOne(LazyNettyServerPropertiesUpdateCommand lazyNettyServerPropertiesUpdateCommand);
|
||||
|
||||
/**
|
||||
* describe 查询单个服务端配置信息
|
||||
*
|
||||
* @param lazyNettyServerPropertiesQueryOneCommand 查询单个服务端配置信息
|
||||
* @return {@link Result<LazyNettyServerPropertiesDTO>} 服务端配置信息DTO对象
|
||||
* @author Jia wei Wu
|
||||
* @date 2024/04/03 03:00 下午
|
||||
**/
|
||||
|
||||
Result<LazyNettyServerPropertiesDTO> findOne(LazyNettyServerPropertiesQueryOneCommand lazyNettyServerPropertiesQueryOneCommand);
|
||||
|
||||
/**
|
||||
* describe 查询多个服务端配置信息
|
||||
*
|
||||
* @param lazyNettyServerPropertiesQueryListCommand 查询多个服务端配置信息
|
||||
* @return {@link Result <List<LazyNettyServerPropertiesDTO>>} 服务端配置信息DTO对象
|
||||
* @author Jia wei Wu
|
||||
* @date 2024/04/03 03:00 下午
|
||||
**/
|
||||
|
||||
Result<List<LazyNettyServerPropertiesDTO>> findList(LazyNettyServerPropertiesQueryListCommand lazyNettyServerPropertiesQueryListCommand);
|
||||
|
||||
/**
|
||||
* describe 分页查询多个服务端配置信息
|
||||
*
|
||||
* @param lazyNettyServerPropertiesQueryListCommand 分页查询多个服务端配置信息
|
||||
* @return {@link Result <LazyPage<LazyNettyServerPropertiesDTO>>} 分页服务端配置信息DTO对象
|
||||
* @author Jia wei Wu
|
||||
* @date 2024/04/03 03:00 下午
|
||||
**/
|
||||
|
||||
Result<LazyPage<LazyNettyServerPropertiesDTO>> findPage(int size, int current, LazyNettyServerPropertiesQueryListCommand lazyNettyServerPropertiesQueryListCommand);
|
||||
|
||||
/**
|
||||
* describe 删除服务端配置信息
|
||||
*
|
||||
* @param lazyNettyServerPropertiesRemoveCommand 删除服务端配置信息
|
||||
* @return {@link Result<LazyNettyServerProperties>} 服务端配置信息
|
||||
* @author Jia wei Wu
|
||||
* @date 2024/04/03 03:00 下午
|
||||
**/
|
||||
|
||||
Result<LazyNettyServerProperties> remove(LazyNettyServerPropertiesRemoveCommand lazyNettyServerPropertiesRemoveCommand);
|
||||
|
||||
/**
|
||||
* 启动socket
|
||||
*
|
||||
* @param lazyNettyServerProperties 配置
|
||||
*/
|
||||
void starterOneClientSocket(LazyNettyServerProperties lazyNettyServerProperties);
|
||||
|
||||
/**
|
||||
* 启动所有 配置的socket
|
||||
*/
|
||||
void starterAllClientSocket();
|
||||
|
||||
/**
|
||||
* 关闭 客户端socket
|
||||
* @param needCloseLazyNettyServerProperties 配置
|
||||
*/
|
||||
void destroyOneClientSocket(LazyNettyServerProperties needCloseLazyNettyServerProperties);
|
||||
|
||||
/**
|
||||
* 关闭 客户端socket
|
||||
*/
|
||||
void destroyClientSocket();
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,93 @@
|
||||
package org.framework.smart.agent.network.heartbeat.client.application.assembler;
|
||||
|
||||
import org.framework.smart.agent.network.heartbeat.client.domain.model.lazy.netty.server.properties.LazyNettyServerProperties;
|
||||
import org.framework.smart.agent.network.heartbeat.client.application.command.lazy.netty.server.properties.LazyNettyServerPropertiesRemoveCommand;
|
||||
import org.framework.smart.agent.network.heartbeat.client.application.command.lazy.netty.server.properties.LazyNettyServerPropertiesStoryCommand;
|
||||
import org.framework.smart.agent.network.heartbeat.client.application.command.lazy.netty.server.properties.LazyNettyServerPropertiesUpdateCommand;
|
||||
import org.framework.smart.agent.network.heartbeat.client.application.command.lazy.netty.server.properties.LazyNettyServerPropertiesQueryListCommand;
|
||||
import org.framework.smart.agent.network.heartbeat.client.application.command.lazy.netty.server.properties.LazyNettyServerPropertiesQueryOneCommand;
|
||||
import org.framework.smart.agent.network.heartbeat.client.application.dto.LazyNettyServerPropertiesDTO;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
import org.mapstruct.Mapper;
|
||||
/**
|
||||
* describe 服务端配置信息
|
||||
*
|
||||
* @author Jia wei Wu
|
||||
* @date 2024/04/03 03:00 下午
|
||||
* @see org.wu.framework.lazy.orm.core.persistence.reverse.lazy.ddd.DefaultDDDLazyAssembler
|
||||
**/
|
||||
@Mapper
|
||||
public interface LazyNettyServerPropertiesDTOAssembler {
|
||||
|
||||
|
||||
/**
|
||||
* describe MapStruct 创建的代理对象
|
||||
*
|
||||
|
||||
|
||||
|
||||
* @author Jia wei Wu
|
||||
* @date 2024/04/03 03:00 下午
|
||||
**/
|
||||
LazyNettyServerPropertiesDTOAssembler INSTANCE = Mappers.getMapper(LazyNettyServerPropertiesDTOAssembler.class);
|
||||
/**
|
||||
* describe 应用层存储入参转换成 领域对象
|
||||
*
|
||||
* @param lazyNettyServerPropertiesStoryCommand 保存服务端配置信息对象
|
||||
* @return {@link LazyNettyServerProperties} 服务端配置信息领域对象
|
||||
|
||||
* @author Jia wei Wu
|
||||
* @date 2024/04/03 03:00 下午
|
||||
**/
|
||||
LazyNettyServerProperties toLazyNettyServerProperties(LazyNettyServerPropertiesStoryCommand lazyNettyServerPropertiesStoryCommand);
|
||||
/**
|
||||
* describe 应用层更新入参转换成 领域对象
|
||||
*
|
||||
* @param lazyNettyServerPropertiesUpdateCommand 更新服务端配置信息对象
|
||||
* @return {@link LazyNettyServerProperties} 服务端配置信息领域对象
|
||||
|
||||
* @author Jia wei Wu
|
||||
* @date 2024/04/03 03:00 下午
|
||||
**/
|
||||
LazyNettyServerProperties toLazyNettyServerProperties(LazyNettyServerPropertiesUpdateCommand lazyNettyServerPropertiesUpdateCommand);
|
||||
/**
|
||||
* describe 应用层查询入参转换成 领域对象
|
||||
*
|
||||
* @param lazyNettyServerPropertiesQueryOneCommand 查询单个服务端配置信息对象参数
|
||||
* @return {@link LazyNettyServerProperties} 服务端配置信息领域对象
|
||||
|
||||
* @author Jia wei Wu
|
||||
* @date 2024/04/03 03:00 下午
|
||||
**/
|
||||
LazyNettyServerProperties toLazyNettyServerProperties(LazyNettyServerPropertiesQueryOneCommand lazyNettyServerPropertiesQueryOneCommand);
|
||||
/**
|
||||
* describe 应用层查询入参转换成 领域对象
|
||||
*
|
||||
* @param lazyNettyServerPropertiesQueryListCommand 查询集合服务端配置信息对象参数
|
||||
* @return {@link LazyNettyServerProperties} 服务端配置信息领域对象
|
||||
|
||||
* @author Jia wei Wu
|
||||
* @date 2024/04/03 03:00 下午
|
||||
**/
|
||||
LazyNettyServerProperties toLazyNettyServerProperties(LazyNettyServerPropertiesQueryListCommand lazyNettyServerPropertiesQueryListCommand);
|
||||
/**
|
||||
* describe 应用层删除入参转换成 领域对象
|
||||
*
|
||||
* @param lazyNettyServerPropertiesRemoveCommand 删除服务端配置信息对象参数
|
||||
* @return {@link LazyNettyServerProperties} 服务端配置信息领域对象
|
||||
|
||||
* @author Jia wei Wu
|
||||
* @date 2024/04/03 03:00 下午
|
||||
**/
|
||||
LazyNettyServerProperties toLazyNettyServerProperties(LazyNettyServerPropertiesRemoveCommand lazyNettyServerPropertiesRemoveCommand);
|
||||
/**
|
||||
* describe 持久层领域对象转换成DTO对象
|
||||
*
|
||||
* @param lazyNettyServerProperties 服务端配置信息领域对象
|
||||
* @return {@link LazyNettyServerPropertiesDTO} 服务端配置信息DTO对象
|
||||
|
||||
* @author Jia wei Wu
|
||||
* @date 2024/04/03 03:00 下午
|
||||
**/
|
||||
LazyNettyServerPropertiesDTO fromLazyNettyServerProperties(LazyNettyServerProperties lazyNettyServerProperties);
|
||||
}
|
@ -0,0 +1,77 @@
|
||||
package org.framework.smart.agent.network.heartbeat.client.application.command.lazy.netty.server.properties;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import org.framework.smart.agent.network.heartbeat.common.enums.NettyClientStatus;
|
||||
import org.framework.smart.agent.network.heartbeat.client.config.PropertiesType;
|
||||
|
||||
import java.lang.String;
|
||||
import java.time.LocalDateTime;
|
||||
import java.lang.Integer;
|
||||
/**
|
||||
* describe 服务端配置信息
|
||||
*
|
||||
* @author Jia wei Wu
|
||||
* @date 2024/04/03 03:00 下午
|
||||
* @see org.wu.framework.lazy.orm.core.persistence.reverse.lazy.ddd.DefaultDDDLazyQueryListCommand
|
||||
**/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@Schema(title = "lazy_netty_server_properties_query_List_command",description = "服务端配置信息")
|
||||
public class LazyNettyServerPropertiesQueryListCommand {
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* 客户身份ID
|
||||
*/
|
||||
@Schema(description ="客户身份ID",name ="clientId",example = "")
|
||||
private String clientId;
|
||||
|
||||
/**
|
||||
*
|
||||
* 状态(on_line、off_line)
|
||||
*/
|
||||
@Schema(description ="状态(on_line、off_line)",name ="connectStatus",example = "")
|
||||
private NettyClientStatus connectStatus;
|
||||
|
||||
/**
|
||||
*
|
||||
* 创建时间
|
||||
*/
|
||||
@Schema(description ="创建时间",name ="createTime",example = "")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* 服务端host
|
||||
*/
|
||||
@Schema(description ="服务端host",name ="inetHost",example = "")
|
||||
private String inetHost;
|
||||
|
||||
/**
|
||||
*
|
||||
* 服务端端口
|
||||
*/
|
||||
@Schema(description ="服务端端口",name ="inetPort",example = "")
|
||||
private Integer inetPort;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* 类型(配置、DB)
|
||||
*/
|
||||
@Schema(description ="类型(配置、DB)",name ="type",example = "")
|
||||
private PropertiesType type;
|
||||
|
||||
/**
|
||||
*
|
||||
* 更新时间
|
||||
*/
|
||||
@Schema(description ="更新时间",name ="updateTime",example = "")
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
}
|
@ -0,0 +1,76 @@
|
||||
package org.framework.smart.agent.network.heartbeat.client.application.command.lazy.netty.server.properties;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import org.framework.smart.agent.network.heartbeat.common.enums.NettyClientStatus;
|
||||
import org.framework.smart.agent.network.heartbeat.client.config.PropertiesType;
|
||||
|
||||
import java.lang.String;
|
||||
import java.time.LocalDateTime;
|
||||
import java.lang.Integer;
|
||||
/**
|
||||
* describe 服务端配置信息
|
||||
*
|
||||
* @author Jia wei Wu
|
||||
* @date 2024/04/03 03:00 下午
|
||||
* @see org.wu.framework.lazy.orm.core.persistence.reverse.lazy.ddd.DefaultDDDLazyQueryOneCommand
|
||||
**/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@Schema(title = "lazy_netty_server_properties_query_one_command",description = "服务端配置信息")
|
||||
public class LazyNettyServerPropertiesQueryOneCommand {
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* 客户身份ID
|
||||
*/
|
||||
@Schema(description ="客户身份ID",name ="clientId",example = "")
|
||||
private String clientId;
|
||||
|
||||
/**
|
||||
*
|
||||
* 状态(on_line、off_line)
|
||||
*/
|
||||
@Schema(description ="状态(on_line、off_line)",name ="connectStatus",example = "")
|
||||
private NettyClientStatus connectStatus;
|
||||
|
||||
/**
|
||||
*
|
||||
* 创建时间
|
||||
*/
|
||||
@Schema(description ="创建时间",name ="createTime",example = "")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
/**
|
||||
*
|
||||
* 服务端host
|
||||
*/
|
||||
@Schema(description ="服务端host",name ="inetHost",example = "")
|
||||
private String inetHost;
|
||||
|
||||
/**
|
||||
*
|
||||
* 服务端端口
|
||||
*/
|
||||
@Schema(description ="服务端端口",name ="inetPort",example = "")
|
||||
private Integer inetPort;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* 类型(配置、DB)
|
||||
*/
|
||||
@Schema(description ="类型(配置、DB)",name ="type",example = "")
|
||||
private PropertiesType type;
|
||||
|
||||
/**
|
||||
*
|
||||
* 更新时间
|
||||
*/
|
||||
@Schema(description ="更新时间",name ="updateTime",example = "")
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
}
|
@ -0,0 +1,77 @@
|
||||
package org.framework.smart.agent.network.heartbeat.client.application.command.lazy.netty.server.properties;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import org.framework.smart.agent.network.heartbeat.common.enums.NettyClientStatus;
|
||||
import org.framework.smart.agent.network.heartbeat.client.config.PropertiesType;
|
||||
|
||||
import java.lang.String;
|
||||
import java.time.LocalDateTime;
|
||||
import java.lang.Integer;
|
||||
/**
|
||||
* describe 服务端配置信息
|
||||
*
|
||||
* @author Jia wei Wu
|
||||
* @date 2024/04/03 03:00 下午
|
||||
* @see org.wu.framework.lazy.orm.core.persistence.reverse.lazy.ddd.DefaultDDDLazyRemoveCommand
|
||||
**/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@Schema(title = "lazy_netty_server_properties_remove_command",description = "服务端配置信息")
|
||||
public class LazyNettyServerPropertiesRemoveCommand {
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* 客户身份ID
|
||||
*/
|
||||
@Schema(description ="客户身份ID",name ="clientId",example = "")
|
||||
private String clientId;
|
||||
|
||||
/**
|
||||
*
|
||||
* 状态(on_line、off_line)
|
||||
*/
|
||||
@Schema(description ="状态(on_line、off_line)",name ="connectStatus",example = "")
|
||||
private NettyClientStatus connectStatus;
|
||||
|
||||
/**
|
||||
*
|
||||
* 创建时间
|
||||
*/
|
||||
@Schema(description ="创建时间",name ="createTime",example = "")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* 服务端host
|
||||
*/
|
||||
@Schema(description ="服务端host",name ="inetHost",example = "")
|
||||
private String inetHost;
|
||||
|
||||
/**
|
||||
*
|
||||
* 服务端端口
|
||||
*/
|
||||
@Schema(description ="服务端端口",name ="inetPort",example = "")
|
||||
private Integer inetPort;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* 类型(配置、DB)
|
||||
*/
|
||||
@Schema(description ="类型(配置、DB)",name ="type",example = "")
|
||||
private PropertiesType type;
|
||||
|
||||
/**
|
||||
*
|
||||
* 更新时间
|
||||
*/
|
||||
@Schema(description ="更新时间",name ="updateTime",example = "")
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
}
|
@ -0,0 +1,76 @@
|
||||
package org.framework.smart.agent.network.heartbeat.client.application.command.lazy.netty.server.properties;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import org.framework.smart.agent.network.heartbeat.common.enums.NettyClientStatus;
|
||||
import org.framework.smart.agent.network.heartbeat.client.config.PropertiesType;
|
||||
|
||||
import java.lang.String;
|
||||
import java.time.LocalDateTime;
|
||||
import java.lang.Integer;
|
||||
/**
|
||||
* describe 服务端配置信息
|
||||
*
|
||||
* @author Jia wei Wu
|
||||
* @date 2024/04/03 03:00 下午
|
||||
* @see org.wu.framework.lazy.orm.core.persistence.reverse.lazy.ddd.DefaultDDDLazyStoryCommand
|
||||
**/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@Schema(title = "lazy_netty_server_properties_story_command",description = "服务端配置信息")
|
||||
public class LazyNettyServerPropertiesStoryCommand {
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* 客户身份ID
|
||||
*/
|
||||
@Schema(description ="客户身份ID",name ="clientId",example = "")
|
||||
private String clientId;
|
||||
|
||||
/**
|
||||
*
|
||||
* 状态(on_line、off_line)
|
||||
*/
|
||||
@Schema(description ="状态(on_line、off_line)",name ="connectStatus",example = "")
|
||||
private NettyClientStatus connectStatus;
|
||||
|
||||
/**
|
||||
*
|
||||
* 创建时间
|
||||
*/
|
||||
@Schema(description ="创建时间",name ="createTime",example = "")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
/**
|
||||
*
|
||||
* 服务端host
|
||||
*/
|
||||
@Schema(description ="服务端host",name ="inetHost",example = "")
|
||||
private String inetHost;
|
||||
|
||||
/**
|
||||
*
|
||||
* 服务端端口
|
||||
*/
|
||||
@Schema(description ="服务端端口",name ="inetPort",example = "")
|
||||
private Integer inetPort;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* 类型(配置、DB)
|
||||
*/
|
||||
@Schema(description ="类型(配置、DB)",name ="type",example = "")
|
||||
private PropertiesType type;
|
||||
|
||||
/**
|
||||
*
|
||||
* 更新时间
|
||||
*/
|
||||
@Schema(description ="更新时间",name ="updateTime",example = "")
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
}
|
@ -0,0 +1,76 @@
|
||||
package org.framework.smart.agent.network.heartbeat.client.application.command.lazy.netty.server.properties;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import org.framework.smart.agent.network.heartbeat.common.enums.NettyClientStatus;
|
||||
import org.framework.smart.agent.network.heartbeat.client.config.PropertiesType;
|
||||
|
||||
import java.lang.String;
|
||||
import java.time.LocalDateTime;
|
||||
import java.lang.Integer;
|
||||
/**
|
||||
* describe 服务端配置信息
|
||||
*
|
||||
* @author Jia wei Wu
|
||||
* @date 2024/04/03 03:00 下午
|
||||
* @see org.wu.framework.lazy.orm.core.persistence.reverse.lazy.ddd.DefaultDDDLazyUpdateCommand
|
||||
**/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@Schema(title = "lazy_netty_server_properties_update_command",description = "服务端配置信息")
|
||||
public class LazyNettyServerPropertiesUpdateCommand {
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* 客户身份ID
|
||||
*/
|
||||
@Schema(description ="客户身份ID",name ="clientId",example = "")
|
||||
private String clientId;
|
||||
|
||||
/**
|
||||
*
|
||||
* 状态(on_line、off_line)
|
||||
*/
|
||||
@Schema(description ="状态(on_line、off_line)",name ="connectStatus",example = "")
|
||||
private NettyClientStatus connectStatus;
|
||||
|
||||
/**
|
||||
*
|
||||
* 创建时间
|
||||
*/
|
||||
@Schema(description ="创建时间",name ="createTime",example = "")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
/**
|
||||
*
|
||||
* 服务端host
|
||||
*/
|
||||
@Schema(description ="服务端host",name ="inetHost",example = "")
|
||||
private String inetHost;
|
||||
|
||||
/**
|
||||
*
|
||||
* 服务端端口
|
||||
*/
|
||||
@Schema(description ="服务端端口",name ="inetPort",example = "")
|
||||
private Integer inetPort;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* 类型(配置、DB)
|
||||
*/
|
||||
@Schema(description ="类型(配置、DB)",name ="type",example = "")
|
||||
private PropertiesType type;
|
||||
|
||||
/**
|
||||
*
|
||||
* 更新时间
|
||||
*/
|
||||
@Schema(description ="更新时间",name ="updateTime",example = "")
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
}
|
@ -0,0 +1,76 @@
|
||||
package org.framework.smart.agent.network.heartbeat.client.application.dto;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import org.framework.smart.agent.network.heartbeat.common.enums.NettyClientStatus;
|
||||
import org.framework.smart.agent.network.heartbeat.client.config.PropertiesType;
|
||||
|
||||
import java.lang.String;
|
||||
import java.time.LocalDateTime;
|
||||
import java.lang.Integer;
|
||||
/**
|
||||
* describe 服务端配置信息
|
||||
*
|
||||
* @author Jia wei Wu
|
||||
* @date 2024/04/03 03:00 下午
|
||||
* @see org.wu.framework.lazy.orm.core.persistence.reverse.lazy.ddd.DefaultDDDLazyDTO
|
||||
**/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@Schema(title = "lazy_netty_server_properties_command_dto",description = "服务端配置信息")
|
||||
public class LazyNettyServerPropertiesDTO {
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* 客户身份ID
|
||||
*/
|
||||
@Schema(description ="客户身份ID",name ="clientId",example = "")
|
||||
private String clientId;
|
||||
|
||||
/**
|
||||
*
|
||||
* 状态(on_line、off_line)
|
||||
*/
|
||||
@Schema(description ="状态(on_line、off_line)",name ="connectStatus",example = "")
|
||||
private NettyClientStatus connectStatus;
|
||||
|
||||
/**
|
||||
*
|
||||
* 创建时间
|
||||
*/
|
||||
@Schema(description ="创建时间",name ="createTime",example = "")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
/**
|
||||
*
|
||||
* 服务端host
|
||||
*/
|
||||
@Schema(description ="服务端host",name ="inetHost",example = "")
|
||||
private String inetHost;
|
||||
|
||||
/**
|
||||
*
|
||||
* 服务端端口
|
||||
*/
|
||||
@Schema(description ="服务端端口",name ="inetPort",example = "")
|
||||
private Integer inetPort;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* 类型(配置、DB)
|
||||
*/
|
||||
@Schema(description ="类型(配置、DB)",name ="type",example = "")
|
||||
private PropertiesType type;
|
||||
|
||||
/**
|
||||
*
|
||||
* 更新时间
|
||||
*/
|
||||
@Schema(description ="更新时间",name ="updateTime",example = "")
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
}
|
@ -0,0 +1,270 @@
|
||||
package org.framework.smart.agent.network.heartbeat.client.application.impl;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.framework.smart.agent.network.heartbeat.client.application.LazyNettyServerPropertiesApplication;
|
||||
import org.framework.smart.agent.network.heartbeat.client.application.assembler.LazyNettyServerPropertiesDTOAssembler;
|
||||
import org.framework.smart.agent.network.heartbeat.client.application.command.lazy.netty.server.properties.*;
|
||||
import org.framework.smart.agent.network.heartbeat.client.application.dto.LazyNettyServerPropertiesDTO;
|
||||
import org.framework.smart.agent.network.heartbeat.client.config.NettyClientProperties;
|
||||
import org.framework.smart.agent.network.heartbeat.client.config.PropertiesType;
|
||||
import org.framework.smart.agent.network.heartbeat.client.domain.model.lazy.netty.server.properties.LazyNettyServerProperties;
|
||||
import org.framework.smart.agent.network.heartbeat.client.domain.model.lazy.netty.server.properties.LazyNettyServerPropertiesRepository;
|
||||
import org.framework.smart.agent.network.heartbeat.client.netty.event.ClientChangeEvent;
|
||||
import org.framework.smart.agent.network.heartbeat.client.netty.socket.NettyClientSocket;
|
||||
import org.framework.smart.agent.network.heartbeat.common.advanced.HandleChannelTypeAdvanced;
|
||||
import org.framework.smart.agent.network.heartbeat.common.enums.NettyClientStatus;
|
||||
import org.wu.framework.core.NormalUsedString;
|
||||
import org.wu.framework.database.lazy.web.plus.stereotype.LazyApplication;
|
||||
import org.wu.framework.lazy.orm.database.lambda.domain.LazyPage;
|
||||
import org.wu.framework.web.response.Result;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.ArrayBlockingQueue;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* describe 服务端配置信息
|
||||
*
|
||||
* @author Jia wei Wu
|
||||
* @date 2024/04/03 03:00 下午
|
||||
* @see org.wu.framework.lazy.orm.core.persistence.reverse.lazy.ddd.DefaultDDDLazyApplicationImpl
|
||||
**/
|
||||
@Slf4j
|
||||
@LazyApplication
|
||||
public class LazyNettyServerPropertiesApplicationImpl implements LazyNettyServerPropertiesApplication {
|
||||
|
||||
@Resource
|
||||
LazyNettyServerPropertiesRepository lazyNettyServerPropertiesRepository;
|
||||
|
||||
@Resource
|
||||
private ClientChangeEvent clientChangeEvent;
|
||||
|
||||
@Resource
|
||||
private List<HandleChannelTypeAdvanced> handleChannelTypeAdvancedList; // 处理服务端发送过来的数据类型
|
||||
|
||||
@Resource
|
||||
private NettyClientProperties nettyClientProperties;// 默认配置文件配置
|
||||
|
||||
|
||||
// 缓存连接socket
|
||||
private final ConcurrentHashMap<LazyNettyServerProperties, NettyClientSocket> cacheNettyClientSocketMap = new ConcurrentHashMap<>();
|
||||
|
||||
public static final ThreadPoolExecutor NETTY_CLIENT_EXECUTOR =
|
||||
new ThreadPoolExecutor(20, 50, 200, TimeUnit.MILLISECONDS,
|
||||
new ArrayBlockingQueue<>(1));
|
||||
|
||||
/**
|
||||
* describe 新增服务端配置信息
|
||||
*
|
||||
* @param lazyNettyServerPropertiesStoryCommand 新增服务端配置信息
|
||||
* @return {@link Result<LazyNettyServerProperties>} 服务端配置信息新增后领域对象
|
||||
* @author Jia wei Wu
|
||||
* @date 2024/04/03 03:00 下午
|
||||
**/
|
||||
|
||||
@Override
|
||||
public Result<LazyNettyServerProperties> story(LazyNettyServerPropertiesStoryCommand lazyNettyServerPropertiesStoryCommand) {
|
||||
LazyNettyServerProperties lazyNettyServerProperties = LazyNettyServerPropertiesDTOAssembler.INSTANCE.toLazyNettyServerProperties(lazyNettyServerPropertiesStoryCommand);
|
||||
|
||||
// 如果状态正在运行中直接忽略
|
||||
lazyNettyServerPropertiesRepository.exists(lazyNettyServerProperties)
|
||||
.accept(exists -> {
|
||||
if (!exists) {
|
||||
starterOneClientSocket(lazyNettyServerProperties);
|
||||
}
|
||||
});
|
||||
lazyNettyServerProperties.setType(PropertiesType.DB);
|
||||
return lazyNettyServerPropertiesRepository.story(lazyNettyServerProperties);
|
||||
}
|
||||
|
||||
/**
|
||||
* describe 批量新增服务端配置信息
|
||||
*
|
||||
* @param lazyNettyServerPropertiesStoryCommandList 批量新增服务端配置信息
|
||||
* @return {@link Result<List<LazyNettyServerProperties>>} 服务端配置信息新增后领域对象集合
|
||||
* @author Jia wei Wu
|
||||
* @date 2024/04/03 03:00 下午
|
||||
**/
|
||||
|
||||
@Override
|
||||
public Result<List<LazyNettyServerProperties>> batchStory(List<LazyNettyServerPropertiesStoryCommand> lazyNettyServerPropertiesStoryCommandList) {
|
||||
List<LazyNettyServerProperties> lazyNettyServerPropertiesList = lazyNettyServerPropertiesStoryCommandList.stream().map(LazyNettyServerPropertiesDTOAssembler.INSTANCE::toLazyNettyServerProperties).collect(Collectors.toList());
|
||||
return lazyNettyServerPropertiesRepository.batchStory(lazyNettyServerPropertiesList);
|
||||
}
|
||||
|
||||
/**
|
||||
* describe 更新服务端配置信息
|
||||
*
|
||||
* @param lazyNettyServerPropertiesUpdateCommand 更新服务端配置信息
|
||||
* @return {@link Result<LazyNettyServerProperties>} 服务端配置信息领域对象
|
||||
* @author Jia wei Wu
|
||||
* @date 2024/04/03 03:00 下午
|
||||
**/
|
||||
|
||||
@Override
|
||||
public Result<LazyNettyServerProperties> updateOne(LazyNettyServerPropertiesUpdateCommand lazyNettyServerPropertiesUpdateCommand) {
|
||||
LazyNettyServerProperties lazyNettyServerProperties = LazyNettyServerPropertiesDTOAssembler.INSTANCE.toLazyNettyServerProperties(lazyNettyServerPropertiesUpdateCommand);
|
||||
return lazyNettyServerPropertiesRepository.story(lazyNettyServerProperties);
|
||||
}
|
||||
|
||||
/**
|
||||
* describe 查询单个服务端配置信息
|
||||
*
|
||||
* @param lazyNettyServerPropertiesQueryOneCommand 查询单个服务端配置信息
|
||||
* @return {@link Result<LazyNettyServerPropertiesDTO>} 服务端配置信息DTO对象
|
||||
* @author Jia wei Wu
|
||||
* @date 2024/04/03 03:00 下午
|
||||
**/
|
||||
|
||||
@Override
|
||||
public Result<LazyNettyServerPropertiesDTO> findOne(LazyNettyServerPropertiesQueryOneCommand lazyNettyServerPropertiesQueryOneCommand) {
|
||||
LazyNettyServerProperties lazyNettyServerProperties = LazyNettyServerPropertiesDTOAssembler.INSTANCE.toLazyNettyServerProperties(lazyNettyServerPropertiesQueryOneCommand);
|
||||
return lazyNettyServerPropertiesRepository.findOne(lazyNettyServerProperties).convert(LazyNettyServerPropertiesDTOAssembler.INSTANCE::fromLazyNettyServerProperties);
|
||||
}
|
||||
|
||||
/**
|
||||
* describe 查询多个服务端配置信息
|
||||
*
|
||||
* @param lazyNettyServerPropertiesQueryListCommand 查询多个服务端配置信息
|
||||
* @return {@link Result<List<LazyNettyServerPropertiesDTO>>} 服务端配置信息DTO对象
|
||||
* @author Jia wei Wu
|
||||
* @date 2024/04/03 03:00 下午
|
||||
**/
|
||||
|
||||
@Override
|
||||
public Result<List<LazyNettyServerPropertiesDTO>> findList(LazyNettyServerPropertiesQueryListCommand lazyNettyServerPropertiesQueryListCommand) {
|
||||
LazyNettyServerProperties lazyNettyServerProperties = LazyNettyServerPropertiesDTOAssembler.INSTANCE.toLazyNettyServerProperties(lazyNettyServerPropertiesQueryListCommand);
|
||||
return lazyNettyServerPropertiesRepository.findList(lazyNettyServerProperties).convert(lazyNettyServerPropertiess -> lazyNettyServerPropertiess.stream().map(LazyNettyServerPropertiesDTOAssembler.INSTANCE::fromLazyNettyServerProperties).collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
/**
|
||||
* describe 分页查询多个服务端配置信息
|
||||
*
|
||||
* @param lazyNettyServerPropertiesQueryListCommand 分页查询多个服务端配置信息
|
||||
* @return {@link Result<LazyPage<LazyNettyServerPropertiesDTO>>} 分页服务端配置信息DTO对象
|
||||
* @author Jia wei Wu
|
||||
* @date 2024/04/03 03:00 下午
|
||||
**/
|
||||
|
||||
@Override
|
||||
public Result<LazyPage<LazyNettyServerPropertiesDTO>> findPage(int size, int current, LazyNettyServerPropertiesQueryListCommand lazyNettyServerPropertiesQueryListCommand) {
|
||||
LazyNettyServerProperties lazyNettyServerProperties = LazyNettyServerPropertiesDTOAssembler.INSTANCE.toLazyNettyServerProperties(lazyNettyServerPropertiesQueryListCommand);
|
||||
return lazyNettyServerPropertiesRepository.findPage(size, current, lazyNettyServerProperties).convert(page -> page.convert(LazyNettyServerPropertiesDTOAssembler.INSTANCE::fromLazyNettyServerProperties));
|
||||
}
|
||||
|
||||
/**
|
||||
* describe 删除服务端配置信息
|
||||
*
|
||||
* @param lazyNettyServerPropertiesRemoveCommand 删除服务端配置信息
|
||||
* @return {@link Result<LazyNettyServerProperties>} 服务端配置信息
|
||||
* @author Jia wei Wu
|
||||
* @date 2024/04/03 03:00 下午
|
||||
**/
|
||||
|
||||
@Override
|
||||
public Result<LazyNettyServerProperties> remove(LazyNettyServerPropertiesRemoveCommand lazyNettyServerPropertiesRemoveCommand) {
|
||||
LazyNettyServerProperties lazyNettyServerProperties = LazyNettyServerPropertiesDTOAssembler.INSTANCE.toLazyNettyServerProperties(lazyNettyServerPropertiesRemoveCommand);
|
||||
// 关闭连接
|
||||
destroyOneClientSocket(lazyNettyServerProperties);
|
||||
return lazyNettyServerPropertiesRepository.remove(lazyNettyServerProperties);
|
||||
}
|
||||
|
||||
/**
|
||||
* 启动socket
|
||||
*
|
||||
* @param lazyNettyServerProperties 配置
|
||||
*/
|
||||
@Override
|
||||
public void starterOneClientSocket(LazyNettyServerProperties lazyNettyServerProperties) {
|
||||
boolean enabled = nettyClientProperties.isEnabled();
|
||||
if (enabled) {
|
||||
String inetHost = lazyNettyServerProperties.getInetHost();
|
||||
Integer inetPort = lazyNettyServerProperties.getInetPort();
|
||||
String clientId = lazyNettyServerProperties.getClientId();
|
||||
|
||||
NettyClientSocket nettyClientSocket = new
|
||||
NettyClientSocket(inetHost, inetPort, clientId,
|
||||
NormalUsedString.DEFAULT,
|
||||
clientChangeEvent, handleChannelTypeAdvancedList);
|
||||
cacheNettyClientSocketMap.put(lazyNettyServerProperties, nettyClientSocket);
|
||||
|
||||
// 更新状态为运行中
|
||||
lazyNettyServerProperties.setConnectStatus(NettyClientStatus.RUNNING);
|
||||
lazyNettyServerPropertiesRepository.story(lazyNettyServerProperties);
|
||||
Thread thread = new Thread(() -> {
|
||||
try {
|
||||
nettyClientSocket.newConnect2Server();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
});
|
||||
// 当前服务连接Netty客户端:{},Netty端口:{}
|
||||
log.info("Current service connection Netty client: {}, Netty port: {}", inetHost, inetPort);
|
||||
NETTY_CLIENT_EXECUTOR.execute(thread);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 启动所有 配置的socket
|
||||
*/
|
||||
@Override
|
||||
public void starterAllClientSocket() {
|
||||
boolean enabled = nettyClientProperties.isEnabled();
|
||||
if (enabled) {
|
||||
// 查询所有配置
|
||||
lazyNettyServerPropertiesRepository.findList(new LazyNettyServerProperties()).accept(lazyNettyServerPropertiesDTOS -> {
|
||||
for (LazyNettyServerProperties nettyServerProperties : lazyNettyServerPropertiesDTOS) {
|
||||
starterOneClientSocket(nettyServerProperties);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭 客户端socket
|
||||
*
|
||||
* @param needCloseLazyNettyServerProperties 配置
|
||||
*/
|
||||
@Override
|
||||
public void destroyOneClientSocket(LazyNettyServerProperties needCloseLazyNettyServerProperties) {
|
||||
// 关闭指定socket
|
||||
cacheNettyClientSocketMap.forEach(((nettyServerProperties, nettyClientSocket) -> {
|
||||
String clientId = nettyServerProperties.getClientId();
|
||||
String inetHost = nettyServerProperties.getInetHost();
|
||||
Integer inetPort = nettyServerProperties.getInetPort();
|
||||
String needCloseInetHost = needCloseLazyNettyServerProperties.getInetHost();
|
||||
Integer needCloseInetPort = needCloseLazyNettyServerProperties.getInetPort();
|
||||
String needCloseClientId = needCloseLazyNettyServerProperties.getClientId();
|
||||
if (Objects.equals(clientId, needCloseClientId)
|
||||
&& Objects.equals(inetPort, needCloseInetPort)
|
||||
&& Objects.equals(inetHost, needCloseInetHost)) {
|
||||
nettyClientSocket.shutdown();
|
||||
// 关闭客户端:{}与服务端连接:{}:{}
|
||||
log.warn("Close client: {} Connect to server: {}: {}", clientId, inetHost, inetPort);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭 客户端socket
|
||||
*/
|
||||
@Override
|
||||
public void destroyClientSocket() {
|
||||
// 关闭socket
|
||||
cacheNettyClientSocketMap.forEach(((nettyServerProperties, nettyClientSocket) -> {
|
||||
nettyClientSocket.shutdown();
|
||||
String clientId = nettyServerProperties.getClientId();
|
||||
String inetHost = nettyServerProperties.getInetHost();
|
||||
Integer inetPort = nettyServerProperties.getInetPort();
|
||||
// 关闭客户端:{}与服务端连接:{}:{}
|
||||
log.warn("Close client: {} Connect to server: {}: {}", clientId, inetHost, inetPort);
|
||||
}));
|
||||
}
|
||||
}
|
@ -0,0 +1,82 @@
|
||||
package org.framework.smart.agent.network.heartbeat.client.config;
|
||||
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.framework.smart.agent.network.heartbeat.client.netty.socket.NettyClientSocket;
|
||||
import org.springframework.boot.CommandLineRunner;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.framework.smart.agent.network.heartbeat.client.netty.event.ClientChangeEvent;
|
||||
import org.framework.smart.agent.network.heartbeat.common.advanced.HandleChannelTypeAdvanced;
|
||||
import org.wu.framework.core.NormalUsedString;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ArrayBlockingQueue;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* description 自动配置
|
||||
*
|
||||
* @author 吴佳伟
|
||||
* @date 2023/09/12 18:22
|
||||
* @see InitConfig
|
||||
*/
|
||||
@Deprecated
|
||||
@Slf4j
|
||||
public class ClientAutoConfiguration implements CommandLineRunner {
|
||||
|
||||
private final NettyClientProperties nettyClientProperties;
|
||||
private final ClientChangeEvent clientChangeEvent;
|
||||
|
||||
private final List<HandleChannelTypeAdvanced> handleChannelTypeAdvancedList; // 处理服务端发送过来的数据类型
|
||||
|
||||
|
||||
public static final ThreadPoolExecutor NETTY_CLIENT_EXECUTOR = new ThreadPoolExecutor(1, 1, 200, TimeUnit.MILLISECONDS,
|
||||
new ArrayBlockingQueue<>(1));
|
||||
|
||||
public ClientAutoConfiguration(NettyClientProperties nettyClientProperties,
|
||||
ClientChangeEvent clientChangeEvent,
|
||||
List<HandleChannelTypeAdvanced> handleChannelTypeAdvancedList) {
|
||||
this.nettyClientProperties = nettyClientProperties;
|
||||
this.clientChangeEvent = clientChangeEvent;
|
||||
this.handleChannelTypeAdvancedList = handleChannelTypeAdvancedList;
|
||||
}
|
||||
|
||||
|
||||
@Bean(destroyMethod = "shutdown")
|
||||
public NettyClientSocket nettyClientSocket() {
|
||||
String inetHost = nettyClientProperties.getInetHost();
|
||||
int inetPort = nettyClientProperties.getInetPort();
|
||||
String clientId = nettyClientProperties.getClientId();
|
||||
return new NettyClientSocket(inetHost, inetPort, clientId, NormalUsedString.DEFAULT, clientChangeEvent, handleChannelTypeAdvancedList);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param args
|
||||
* @throws Exception
|
||||
*/
|
||||
@Override
|
||||
public void run(String... args) throws Exception {
|
||||
|
||||
|
||||
String inetHost = nettyClientProperties.getInetHost();
|
||||
int inetPort = nettyClientProperties.getInetPort();
|
||||
String clientId = nettyClientProperties.getClientId();
|
||||
NettyClientSocket nettyClientSocket = new NettyClientSocket(
|
||||
inetHost, inetPort,
|
||||
clientId, NormalUsedString.DEFAULT,
|
||||
clientChangeEvent, handleChannelTypeAdvancedList);
|
||||
Thread thread = new Thread(() -> {
|
||||
try {
|
||||
nettyClientSocket.newConnect2Server();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
});
|
||||
log.info("当前服务连接Netty客户端:{},Netty端口:{}", inetHost, inetPort);
|
||||
NETTY_CLIENT_EXECUTOR.execute(thread);
|
||||
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,89 @@
|
||||
package org.framework.smart.agent.network.heartbeat.client.config;
|
||||
|
||||
|
||||
import org.framework.smart.agent.network.heartbeat.client.netty.advanced.*;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Role;
|
||||
import org.framework.smart.agent.network.heartbeat.client.netty.event.ClientChangeEvent;
|
||||
import org.framework.smart.agent.network.heartbeat.common.advanced.HandleChannelTypeAdvanced;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||
@ConditionalOnProperty(prefix = NettyClientProperties.PREFIX, name = "enabled", havingValue = "true", matchIfMissing = true)
|
||||
public class HeartbeatClientConfiguration {
|
||||
|
||||
/**
|
||||
* 服务端 处理客户端心跳
|
||||
*
|
||||
* @return ClientHandleChannelHeartbeatTypeAdvanced
|
||||
*/
|
||||
@Bean
|
||||
public ClientHandleChannelHeartbeatTypeAdvanced clientChannelHeartbeatTypeAdvanced() {
|
||||
return new ClientHandleChannelHeartbeatTypeAdvanced();
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理 客户端代理的真实端口自动读写
|
||||
*
|
||||
* @return ClientHandleDistributeSingleClientRealAutoReadConnectTypeAdvanced
|
||||
*/
|
||||
@Bean
|
||||
public ClientHandleDistributeSingleClientRealAutoReadConnectTypeAdvanced handleDistributeSingleClientRealAutoReadConnectTypeAdvanced() {
|
||||
return new ClientHandleDistributeSingleClientRealAutoReadConnectTypeAdvanced();
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理 接收服务端发送过来的聊天信息
|
||||
*
|
||||
* @return ClientHandleDistributeSingleClientMessageTypeAdvanced
|
||||
*/
|
||||
@Bean
|
||||
public ClientHandleDistributeSingleClientMessageTypeAdvanced handleDistributeSingleClientMessageTypeAdvanced() {
|
||||
return new ClientHandleDistributeSingleClientMessageTypeAdvanced();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ClientHandleDistributeSingleClientRealCloseVisitorTypeAdvanced handleDistributeSingleClientRealCloseVisitorTypeAdvanced() {
|
||||
return new ClientHandleDistributeSingleClientRealCloseVisitorTypeAdvanced();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ClientReportHandleChannelTransferTypeAdvancedHandleDistribute handleChannelTransferTypeAdvancedHandleDistribute(NettyClientProperties nettyClientProperties) {
|
||||
return new ClientReportHandleChannelTransferTypeAdvancedHandleDistribute(nettyClientProperties);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public HandleDistributeConnectSuccessNotificationTypeAdvancedHandle handleDistributeConnectSuccessNotificationTypeAdvancedHandle(ClientChangeEvent clientChangeEvent) {
|
||||
return new HandleDistributeConnectSuccessNotificationTypeAdvancedHandle(clientChangeEvent);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public HandleClientChannelActiveAdvanced handleClientChannelActiveAdvanced(NettyClientProperties nettyClientProperties) {
|
||||
return new HandleClientChannelActiveAdvanced(nettyClientProperties);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public HandleDistributeDisconnectTypeAdvancedHandle handleDistributeDisconnectTypeAdvancedHandle(ClientChangeEvent clientChangeEvent) {
|
||||
return new HandleDistributeDisconnectTypeAdvancedHandle(clientChangeEvent);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public HandleDistributeStagingClosedTypeAdvanced handleDistributeStagingClosedTypeAdvanced() {
|
||||
return new HandleDistributeStagingClosedTypeAdvanced();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public HandleDistributeStagingOpenedTypeAdvanced handleDistributeStagingOpenedTypeAdvanced() {
|
||||
return new HandleDistributeStagingOpenedTypeAdvanced();
|
||||
}
|
||||
|
||||
|
||||
@Bean
|
||||
public ClientHandleDistributeSingleClientRealConnectTypeAdvanced clientHandleDistributeSingleClientRealConnectTypeAdvanced(NettyClientProperties nettyClientProperties,
|
||||
List<HandleChannelTypeAdvanced> handleChannelTypeAdvancedList) {
|
||||
return new ClientHandleDistributeSingleClientRealConnectTypeAdvanced(nettyClientProperties, handleChannelTypeAdvancedList);
|
||||
}
|
||||
}
|
@ -0,0 +1,87 @@
|
||||
package org.framework.smart.agent.network.heartbeat.client.config;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.framework.smart.agent.network.heartbeat.client.application.LazyNettyServerPropertiesApplication;
|
||||
import org.framework.smart.agent.network.heartbeat.client.infrastructure.entity.LazyNettyServerPropertiesDO;
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.boot.CommandLineRunner;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Role;
|
||||
import org.wu.framework.lazy.orm.database.lambda.stream.lambda.LazyLambdaStream;
|
||||
import org.wu.framework.lazy.orm.database.lambda.stream.wrapper.LazyWrappers;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 初始化配置
|
||||
*/
|
||||
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||
@Slf4j
|
||||
@Configuration
|
||||
public class InitConfig implements CommandLineRunner, DisposableBean {
|
||||
|
||||
private final NettyClientProperties nettyClientProperties;
|
||||
private final LazyLambdaStream lazyLambdaStream;
|
||||
|
||||
private final LazyNettyServerPropertiesApplication lazyNettyServerPropertiesApplication;
|
||||
|
||||
public InitConfig(NettyClientProperties nettyClientProperties, LazyLambdaStream lazyLambdaStream, LazyNettyServerPropertiesApplication lazyNettyServerPropertiesApplication) {
|
||||
this.nettyClientProperties = nettyClientProperties;
|
||||
this.lazyLambdaStream = lazyLambdaStream;
|
||||
this.lazyNettyServerPropertiesApplication = lazyNettyServerPropertiesApplication;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void run(String... args) throws Exception {
|
||||
try {
|
||||
// 存储配置到db
|
||||
initDb2Config();
|
||||
// 启动客户端连接
|
||||
lazyNettyServerPropertiesApplication.starterAllClientSocket();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 存储配置到db
|
||||
*/
|
||||
public void initDb2Config() {
|
||||
|
||||
String clientId = nettyClientProperties.getClientId();
|
||||
String inetHost = nettyClientProperties.getInetHost();
|
||||
int inetPort = nettyClientProperties.getInetPort();
|
||||
if (Objects.isNull(clientId) ||
|
||||
Objects.isNull(inetHost)) {
|
||||
log.warn("配置信息为空,请通过页面添加配置信息:{}", nettyClientProperties);
|
||||
return;
|
||||
}
|
||||
LazyNettyServerPropertiesDO lazyNettyServerPropertiesDO = new LazyNettyServerPropertiesDO();
|
||||
lazyNettyServerPropertiesDO.setClientId(clientId);
|
||||
lazyNettyServerPropertiesDO.setInetHost(inetHost);
|
||||
lazyNettyServerPropertiesDO.setInetPort(inetPort);
|
||||
lazyNettyServerPropertiesDO.setType(PropertiesType.CONFIG);
|
||||
lazyNettyServerPropertiesDO.setIsDeleted(false);
|
||||
// 根据服务端端口、port 唯一性验证
|
||||
boolean exists = lazyLambdaStream.exists(LazyWrappers.<LazyNettyServerPropertiesDO>lambdaWrapper()
|
||||
.eq(LazyNettyServerPropertiesDO::getInetHost, inetHost)
|
||||
.eq(LazyNettyServerPropertiesDO::getInetPort, inetPort)
|
||||
.eq(LazyNettyServerPropertiesDO::getClientId, clientId)
|
||||
);
|
||||
if (!exists) {
|
||||
lazyLambdaStream.insert(lazyNettyServerPropertiesDO);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 程序关闭后执行
|
||||
*/
|
||||
@Override
|
||||
public void destroy() {
|
||||
lazyNettyServerPropertiesApplication.destroyClientSocket();
|
||||
}
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
package org.framework.smart.agent.network.heartbeat.client.config;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* netty 客户服务端地址配置属性
|
||||
*/
|
||||
@ConfigurationProperties(prefix = NettyClientProperties.PREFIX, ignoreUnknownFields = true)
|
||||
@Configuration
|
||||
@Data
|
||||
public class NettyClientProperties {
|
||||
public static final String PREFIX = "spring.lazy.netty.client";
|
||||
/**
|
||||
* 服务端地址 如:127.0.0.1
|
||||
*/
|
||||
private String inetHost;
|
||||
/**
|
||||
* 服务端端口 如:7001
|
||||
*/
|
||||
private int inetPort;
|
||||
/**
|
||||
* 服务端path
|
||||
*/
|
||||
private String inetPath = "lazy-cloud-heartbeat-server";
|
||||
/**
|
||||
* 客户端ID 如:1024
|
||||
*/
|
||||
private String clientId;
|
||||
|
||||
/**
|
||||
* 是否开启 默认是
|
||||
*/
|
||||
private boolean enabled = true;
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
package org.framework.smart.agent.network.heartbeat.client.config;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 属性类型
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
public enum PropertiesType {
|
||||
DB,
|
||||
CONFIG
|
||||
}
|
@ -0,0 +1,141 @@
|
||||
package org.framework.smart.agent.network.heartbeat.client.controller;
|
||||
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import org.wu.framework.web.spring.EasyController;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.wu.framework.web.response.Result;
|
||||
import org.wu.framework.web.response.ResultFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.framework.smart.agent.network.heartbeat.client.domain.model.lazy.netty.server.properties.LazyNettyServerProperties;
|
||||
import org.framework.smart.agent.network.heartbeat.client.application.command.lazy.netty.server.properties.LazyNettyServerPropertiesRemoveCommand;
|
||||
import org.framework.smart.agent.network.heartbeat.client.application.command.lazy.netty.server.properties.LazyNettyServerPropertiesStoryCommand;
|
||||
import org.framework.smart.agent.network.heartbeat.client.application.command.lazy.netty.server.properties.LazyNettyServerPropertiesUpdateCommand;
|
||||
import org.framework.smart.agent.network.heartbeat.client.application.command.lazy.netty.server.properties.LazyNettyServerPropertiesQueryListCommand;
|
||||
import org.framework.smart.agent.network.heartbeat.client.application.command.lazy.netty.server.properties.LazyNettyServerPropertiesQueryOneCommand;
|
||||
import org.framework.smart.agent.network.heartbeat.client.application.LazyNettyServerPropertiesApplication;
|
||||
import org.framework.smart.agent.network.heartbeat.client.application.dto.LazyNettyServerPropertiesDTO;
|
||||
import java.util.List;
|
||||
import org.wu.framework.lazy.orm.database.lambda.domain.LazyPage;
|
||||
/**
|
||||
* describe 服务端配置信息
|
||||
*
|
||||
* @author Jia wei Wu
|
||||
* @date 2024/04/03 03:00 下午
|
||||
* @see org.wu.framework.lazy.orm.core.persistence.reverse.lazy.ddd.DefaultDDDLazyController
|
||||
**/
|
||||
@Tag(name = "服务端配置信息提供者")
|
||||
@EasyController("/v1/api/lazy/netty/server/properties")
|
||||
public class LazyNettyServerPropertiesProvider {
|
||||
|
||||
@Resource
|
||||
private LazyNettyServerPropertiesApplication lazyNettyServerPropertiesApplication;
|
||||
|
||||
/**
|
||||
* describe 新增服务端配置信息
|
||||
*
|
||||
* @param lazyNettyServerPropertiesStoryCommand 新增服务端配置信息
|
||||
* @return {@link Result<LazyNettyServerProperties>} 服务端配置信息新增后领域对象
|
||||
|
||||
* @author Jia wei Wu
|
||||
* @date 2024/04/03 03:00 下午
|
||||
**/
|
||||
@Operation(summary = "新增服务端配置信息")
|
||||
@PostMapping("/story")
|
||||
public Result<LazyNettyServerProperties> story(@RequestBody LazyNettyServerPropertiesStoryCommand lazyNettyServerPropertiesStoryCommand){
|
||||
return lazyNettyServerPropertiesApplication.story(lazyNettyServerPropertiesStoryCommand);
|
||||
}
|
||||
/**
|
||||
* describe 批量新增服务端配置信息
|
||||
*
|
||||
* @param lazyNettyServerPropertiesStoryCommandList 批量新增服务端配置信息
|
||||
* @return {@link Result<List<LazyNettyServerProperties>>} 服务端配置信息新增后领域对象集合
|
||||
|
||||
* @author Jia wei Wu
|
||||
* @date 2024/04/03 03:00 下午
|
||||
**/
|
||||
|
||||
@Operation(summary = "批量新增服务端配置信息")
|
||||
@PostMapping("/batchStory")
|
||||
public Result<List<LazyNettyServerProperties>> batchStory(@RequestBody List<LazyNettyServerPropertiesStoryCommand> lazyNettyServerPropertiesStoryCommandList){
|
||||
return lazyNettyServerPropertiesApplication.batchStory(lazyNettyServerPropertiesStoryCommandList);
|
||||
}
|
||||
/**
|
||||
* describe 更新服务端配置信息
|
||||
*
|
||||
* @param lazyNettyServerPropertiesUpdateCommand 更新服务端配置信息
|
||||
* @return {@link Result<LazyNettyServerProperties>} 服务端配置信息领域对象
|
||||
|
||||
* @author Jia wei Wu
|
||||
* @date 2024/04/03 03:00 下午
|
||||
**/
|
||||
|
||||
@Operation(summary = "更新服务端配置信息")
|
||||
@PutMapping("/updateOne")
|
||||
public Result<LazyNettyServerProperties> updateOne(@RequestBody LazyNettyServerPropertiesUpdateCommand lazyNettyServerPropertiesUpdateCommand){
|
||||
return lazyNettyServerPropertiesApplication.updateOne(lazyNettyServerPropertiesUpdateCommand);
|
||||
}
|
||||
/**
|
||||
* describe 查询单个服务端配置信息
|
||||
*
|
||||
* @param lazyNettyServerPropertiesQueryOneCommand 查询单个服务端配置信息
|
||||
* @return {@link Result<LazyNettyServerPropertiesDTO>} 服务端配置信息DTO对象
|
||||
|
||||
* @author Jia wei Wu
|
||||
* @date 2024/04/03 03:00 下午
|
||||
**/
|
||||
|
||||
@Operation(summary = "查询单个服务端配置信息")
|
||||
@GetMapping("/findOne")
|
||||
public Result<LazyNettyServerPropertiesDTO> findOne(@ModelAttribute LazyNettyServerPropertiesQueryOneCommand lazyNettyServerPropertiesQueryOneCommand){
|
||||
return lazyNettyServerPropertiesApplication.findOne(lazyNettyServerPropertiesQueryOneCommand);
|
||||
}
|
||||
/**
|
||||
* describe 查询多个服务端配置信息
|
||||
*
|
||||
* @param lazyNettyServerPropertiesQueryListCommand 查询多个服务端配置信息
|
||||
* @return {@link Result<List<LazyNettyServerPropertiesDTO>>} 服务端配置信息DTO对象
|
||||
|
||||
* @author Jia wei Wu
|
||||
* @date 2024/04/03 03:00 下午
|
||||
**/
|
||||
|
||||
@Operation(summary = "查询多个服务端配置信息")
|
||||
@GetMapping("/findList")
|
||||
public Result<List<LazyNettyServerPropertiesDTO>> findList(@ModelAttribute LazyNettyServerPropertiesQueryListCommand lazyNettyServerPropertiesQueryListCommand){
|
||||
return lazyNettyServerPropertiesApplication.findList(lazyNettyServerPropertiesQueryListCommand);
|
||||
}
|
||||
/**
|
||||
* describe 分页查询多个服务端配置信息
|
||||
*
|
||||
* @param lazyNettyServerPropertiesQueryListCommand 分页查询多个服务端配置信息
|
||||
* @return {@link Result<LazyPage<LazyNettyServerPropertiesDTO>>} 分页服务端配置信息DTO对象
|
||||
|
||||
* @author Jia wei Wu
|
||||
* @date 2024/04/03 03:00 下午
|
||||
**/
|
||||
|
||||
@Operation(summary = "分页查询多个服务端配置信息")
|
||||
@GetMapping("/findPage")
|
||||
public Result<LazyPage<LazyNettyServerPropertiesDTO>> findPage(@Parameter(description ="分页大小") @RequestParam(defaultValue = "10", value = "size") int size,
|
||||
@Parameter(description ="当前页数") @RequestParam(defaultValue = "1", value = "current") int current,@ModelAttribute LazyNettyServerPropertiesQueryListCommand lazyNettyServerPropertiesQueryListCommand){
|
||||
return lazyNettyServerPropertiesApplication.findPage(size,current,lazyNettyServerPropertiesQueryListCommand);
|
||||
}
|
||||
/**
|
||||
* describe 删除服务端配置信息
|
||||
*
|
||||
* @param lazyNettyServerPropertiesRemoveCommand 删除服务端配置信息
|
||||
* @return {@link Result<LazyNettyServerProperties>} 服务端配置信息
|
||||
|
||||
* @author Jia wei Wu
|
||||
* @date 2024/04/03 03:00 下午
|
||||
**/
|
||||
|
||||
@Operation(summary = "删除服务端配置信息")
|
||||
@DeleteMapping("/remove")
|
||||
public Result<LazyNettyServerProperties> remove(@ModelAttribute LazyNettyServerPropertiesRemoveCommand lazyNettyServerPropertiesRemoveCommand){
|
||||
return lazyNettyServerPropertiesApplication.remove(lazyNettyServerPropertiesRemoveCommand);
|
||||
}
|
||||
}
|
@ -0,0 +1,76 @@
|
||||
package org.framework.smart.agent.network.heartbeat.client.domain.model.lazy.netty.server.properties;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import org.framework.smart.agent.network.heartbeat.common.enums.NettyClientStatus;
|
||||
import org.framework.smart.agent.network.heartbeat.client.config.PropertiesType;
|
||||
|
||||
import java.lang.String;
|
||||
import java.time.LocalDateTime;
|
||||
import java.lang.Integer;
|
||||
/**
|
||||
* describe 服务端配置信息
|
||||
*
|
||||
* @author Jia wei Wu
|
||||
* @date 2024/04/03 03:00 下午
|
||||
* @see org.wu.framework.lazy.orm.core.persistence.reverse.lazy.ddd.DefaultDDDLazyDomain
|
||||
**/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@Schema(title = "lazy_netty_server_properties",description = "服务端配置信息")
|
||||
public class LazyNettyServerProperties {
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* 客户身份ID
|
||||
*/
|
||||
@Schema(description ="客户身份ID",name ="clientId",example = "")
|
||||
private String clientId;
|
||||
|
||||
/**
|
||||
*
|
||||
* 状态(on_line、off_line)
|
||||
*/
|
||||
@Schema(description ="状态(on_line、off_line)",name ="connectStatus",example = "")
|
||||
private NettyClientStatus connectStatus;
|
||||
|
||||
/**
|
||||
*
|
||||
* 创建时间
|
||||
*/
|
||||
@Schema(description ="创建时间",name ="createTime",example = "")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* 服务端host
|
||||
*/
|
||||
@Schema(description ="服务端host",name ="inetHost",example = "")
|
||||
private String inetHost;
|
||||
|
||||
/**
|
||||
*
|
||||
* 服务端端口
|
||||
*/
|
||||
@Schema(description ="服务端端口",name ="inetPort",example = "")
|
||||
private Integer inetPort;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* 类型(配置、DB)
|
||||
*/
|
||||
@Schema(description ="类型(配置、DB)",name ="type",example = "")
|
||||
private PropertiesType type;
|
||||
|
||||
/**
|
||||
*
|
||||
* 更新时间
|
||||
*/
|
||||
@Schema(description ="更新时间",name ="updateTime",example = "")
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
}
|
@ -0,0 +1,118 @@
|
||||
package org.framework.smart.agent.network.heartbeat.client.domain.model.lazy.netty.server.properties;
|
||||
|
||||
import org.wu.framework.web.response.Result;
|
||||
import org.wu.framework.web.response.ResultFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.framework.smart.agent.network.heartbeat.client.domain.model.lazy.netty.server.properties.LazyNettyServerProperties;
|
||||
import java.util.List;
|
||||
import org.wu.framework.lazy.orm.database.lambda.domain.LazyPage;
|
||||
/**
|
||||
* describe 服务端配置信息
|
||||
*
|
||||
* @author Jia wei Wu
|
||||
* @date 2024/04/03 03:00 下午
|
||||
* @see org.wu.framework.lazy.orm.core.persistence.reverse.lazy.ddd.DefaultDDDLazyDomainRepository
|
||||
**/
|
||||
|
||||
public interface LazyNettyServerPropertiesRepository {
|
||||
|
||||
|
||||
/**
|
||||
* describe 新增服务端配置信息
|
||||
*
|
||||
* @param lazyNettyServerProperties 新增服务端配置信息
|
||||
* @return {@link Result<LazyNettyServerProperties>} 服务端配置信息新增后领域对象
|
||||
|
||||
* @author Jia wei Wu
|
||||
* @date 2024/04/03 03:00 下午
|
||||
**/
|
||||
|
||||
Result<LazyNettyServerProperties> story(LazyNettyServerProperties lazyNettyServerProperties);
|
||||
|
||||
/**
|
||||
* describe 批量新增服务端配置信息
|
||||
*
|
||||
* @param lazyNettyServerPropertiesList 批量新增服务端配置信息
|
||||
* @return {@link Result<List<LazyNettyServerProperties>>} 服务端配置信息新增后领域对象集合
|
||||
|
||||
* @author Jia wei Wu
|
||||
* @date 2024/04/03 03:00 下午
|
||||
**/
|
||||
|
||||
Result<List<LazyNettyServerProperties>> batchStory(List<LazyNettyServerProperties> lazyNettyServerPropertiesList);
|
||||
|
||||
/**
|
||||
* describe 查询单个服务端配置信息
|
||||
*
|
||||
* @param lazyNettyServerProperties 查询单个服务端配置信息
|
||||
* @return {@link Result<LazyNettyServerProperties>} 服务端配置信息DTO对象
|
||||
|
||||
* @author Jia wei Wu
|
||||
* @date 2024/04/03 03:00 下午
|
||||
**/
|
||||
|
||||
Result<LazyNettyServerProperties> findOne(LazyNettyServerProperties lazyNettyServerProperties);
|
||||
|
||||
/**
|
||||
* describe 查询多个服务端配置信息
|
||||
*
|
||||
* @param lazyNettyServerProperties 查询多个服务端配置信息
|
||||
* @return {@link Result<List<LazyNettyServerProperties>>} 服务端配置信息DTO对象
|
||||
|
||||
* @author Jia wei Wu
|
||||
* @date 2024/04/03 03:00 下午
|
||||
**/
|
||||
|
||||
Result<List<LazyNettyServerProperties>> findList(LazyNettyServerProperties lazyNettyServerProperties);
|
||||
|
||||
/**
|
||||
* describe 分页查询多个服务端配置信息
|
||||
*
|
||||
* @param size 当前页数
|
||||
* @param current 当前页
|
||||
* @param lazyNettyServerProperties 分页查询多个服务端配置信息
|
||||
* @return {@link Result<LazyPage<LazyNettyServerProperties>>} 分页服务端配置信息领域对象
|
||||
|
||||
* @author Jia wei Wu
|
||||
* @date 2024/04/03 03:00 下午
|
||||
**/
|
||||
|
||||
Result<LazyPage<LazyNettyServerProperties>> findPage(int size,int current,LazyNettyServerProperties lazyNettyServerProperties);
|
||||
|
||||
/**
|
||||
* describe 删除服务端配置信息
|
||||
*
|
||||
* @param lazyNettyServerProperties 删除服务端配置信息
|
||||
* @return {@link Result<LazyNettyServerProperties>} 服务端配置信息
|
||||
|
||||
* @author Jia wei Wu
|
||||
* @date 2024/04/03 03:00 下午
|
||||
**/
|
||||
|
||||
Result<LazyNettyServerProperties> remove(LazyNettyServerProperties lazyNettyServerProperties);
|
||||
|
||||
/**
|
||||
* describe 是否存在服务端配置信息
|
||||
*
|
||||
* @param lazyNettyServerProperties 是否存在服务端配置信息
|
||||
* @return {@link Result<Boolean>} 服务端配置信息是否存在
|
||||
|
||||
* @author Jia wei Wu
|
||||
* @date 2024/04/03 03:00 下午
|
||||
**/
|
||||
|
||||
Result<Boolean> exists(LazyNettyServerProperties lazyNettyServerProperties);
|
||||
|
||||
/**
|
||||
* 客户端连接服务端状态在线
|
||||
* @param lazyNettyServerProperties 数据
|
||||
*/
|
||||
void onLine(LazyNettyServerProperties lazyNettyServerProperties);
|
||||
|
||||
/**
|
||||
* 推送客户端离线
|
||||
* @param lazyNettyServerProperties 数据
|
||||
*/
|
||||
void offLine(LazyNettyServerProperties lazyNettyServerProperties);
|
||||
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
package org.framework.smart.agent.network.heartbeat.client.infrastructure.converter;
|
||||
|
||||
import org.framework.smart.agent.network.heartbeat.client.domain.model.lazy.netty.server.properties.LazyNettyServerProperties;
|
||||
import org.framework.smart.agent.network.heartbeat.client.infrastructure.entity.LazyNettyServerPropertiesDO;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
import org.mapstruct.Mapper;
|
||||
/**
|
||||
* describe 服务端配置信息
|
||||
*
|
||||
* @author Jia wei Wu
|
||||
* @date 2024/04/03 03:00 下午
|
||||
* @see org.wu.framework.lazy.orm.core.persistence.reverse.lazy.ddd.DefaultDDDLazyInfrastructureConverter
|
||||
**/
|
||||
@Mapper
|
||||
public interface LazyNettyServerPropertiesConverter {
|
||||
|
||||
|
||||
/**
|
||||
* describe MapStruct 创建的代理对象
|
||||
*
|
||||
|
||||
|
||||
|
||||
* @author Jia wei Wu
|
||||
* @date 2024/04/03 03:00 下午
|
||||
**/
|
||||
LazyNettyServerPropertiesConverter INSTANCE = Mappers.getMapper(LazyNettyServerPropertiesConverter.class);
|
||||
/**
|
||||
* describe 实体对象 转换成领域对象
|
||||
*
|
||||
* @param lazyNettyServerPropertiesDO 服务端配置信息实体对象
|
||||
* @return {@link LazyNettyServerProperties} 服务端配置信息领域对象
|
||||
|
||||
* @author Jia wei Wu
|
||||
* @date 2024/04/03 03:00 下午
|
||||
**/
|
||||
LazyNettyServerProperties toLazyNettyServerProperties(LazyNettyServerPropertiesDO lazyNettyServerPropertiesDO);
|
||||
/**
|
||||
* describe 领域对象 转换成实体对象
|
||||
*
|
||||
* @param lazyNettyServerProperties 服务端配置信息领域对象
|
||||
* @return {@link LazyNettyServerPropertiesDO} 服务端配置信息实体对象
|
||||
|
||||
* @author Jia wei Wu
|
||||
* @date 2024/04/03 03:00 下午
|
||||
**/
|
||||
LazyNettyServerPropertiesDO fromLazyNettyServerProperties(LazyNettyServerProperties lazyNettyServerProperties);
|
||||
}
|
@ -0,0 +1,97 @@
|
||||
package org.framework.smart.agent.network.heartbeat.client.infrastructure.entity;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.framework.smart.agent.network.heartbeat.common.enums.NettyClientStatus;
|
||||
import org.framework.smart.agent.network.heartbeat.client.config.PropertiesType;
|
||||
import org.wu.framework.lazy.orm.core.stereotype.LazyTableIndex;
|
||||
import org.wu.framework.core.stereotype.LayerField;
|
||||
import org.wu.framework.core.stereotype.LayerField.LayerFieldType;
|
||||
import org.wu.framework.lazy.orm.core.stereotype.LazyTable;
|
||||
import org.wu.framework.lazy.orm.core.stereotype.LazyTableField;
|
||||
import org.wu.framework.lazy.orm.core.stereotype.*;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import java.lang.String;
|
||||
import java.time.LocalDateTime;
|
||||
import java.lang.Integer;
|
||||
/**
|
||||
* describe 服务端配置信息
|
||||
*
|
||||
* @author Jia wei Wu
|
||||
* @date 2024/04/03 03:00 下午
|
||||
* @see org.wu.framework.lazy.orm.core.persistence.reverse.lazy.ddd.DefaultDDDLazyInfrastructureEntity
|
||||
**/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@LazyTable(tableName = "lazy_netty_server_properties",comment = "服务端配置信息")
|
||||
@Schema(title = "lazy_netty_server_properties",description = "服务端配置信息")
|
||||
public class LazyNettyServerPropertiesDO {
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* 客户身份ID
|
||||
*/
|
||||
@Schema(description ="客户身份ID",name ="clientId",example = "")
|
||||
@LazyTableFieldUnique(name="client_id",comment="客户身份ID",columnType="varchar(255)")
|
||||
private String clientId;
|
||||
|
||||
/**
|
||||
*
|
||||
* 状态(on_line、off_line)
|
||||
*/
|
||||
@Schema(description ="状态(on_line、off_line)",name ="connectStatus",example = "")
|
||||
@LazyTableField(name="connect_status",comment="状态(on_line、off_line)",columnType="varchar(255)")
|
||||
private NettyClientStatus connectStatus;
|
||||
|
||||
/**
|
||||
*
|
||||
* 创建时间
|
||||
*/
|
||||
@Schema(description ="创建时间",name ="createTime",example = "")
|
||||
@LazyTableField(name="create_time",comment="创建时间")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* 服务端host
|
||||
*/
|
||||
@Schema(description ="服务端host",name ="inetHost",example = "")
|
||||
@LazyTableFieldUnique(name="inet_host",comment="服务端host",columnType="varchar(255)")
|
||||
private String inetHost;
|
||||
|
||||
/**
|
||||
*
|
||||
* 服务端端口
|
||||
*/
|
||||
@Schema(description ="服务端端口",name ="inetPort",example = "")
|
||||
@LazyTableFieldUnique(name="inet_port",comment="服务端端口",columnType="int")
|
||||
private Integer inetPort;
|
||||
|
||||
/**
|
||||
*
|
||||
* 是否删除
|
||||
*/
|
||||
@Schema(description ="是否删除",name ="isDeleted",example = "")
|
||||
@LazyTableField(name="is_deleted",comment="是否删除")
|
||||
private Boolean isDeleted;
|
||||
|
||||
/**
|
||||
*
|
||||
* 类型(配置、DB)
|
||||
*/
|
||||
@Schema(description ="类型(配置、DB)",name ="type",example = "")
|
||||
@LazyTableField(name="type",comment="类型(配置、DB)",columnType="varchar(255)")
|
||||
private PropertiesType type;
|
||||
|
||||
/**
|
||||
*
|
||||
* 更新时间
|
||||
*/
|
||||
@Schema(description ="更新时间",name ="updateTime",example = "")
|
||||
@LazyTableField(name="update_time",comment="更新时间")
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
package org.framework.smart.agent.network.heartbeat.client.infrastructure.mapper;
|
||||
|
||||
/**
|
||||
* describe 服务端配置信息
|
||||
*
|
||||
* @author Jia wei Wu
|
||||
* @date 2024/04/03 03:00 下午
|
||||
* @see org.wu.framework.lazy.orm.core.persistence.reverse.lazy.ddd.DefaultDDDLazyInfrastructureMapper
|
||||
**/
|
||||
|
||||
public interface LazyNettyServerPropertiesMapper {
|
||||
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,213 @@
|
||||
package org.framework.smart.agent.network.heartbeat.client.infrastructure.persistence;
|
||||
|
||||
import org.framework.smart.agent.network.heartbeat.client.config.PropertiesType;
|
||||
import org.framework.smart.agent.network.heartbeat.client.infrastructure.entity.LazyNettyServerPropertiesDO;
|
||||
import org.framework.smart.agent.network.heartbeat.client.infrastructure.converter.LazyNettyServerPropertiesConverter;
|
||||
import org.framework.smart.agent.network.heartbeat.client.infrastructure.mapper.LazyNettyServerPropertiesMapper;
|
||||
import org.framework.smart.agent.network.heartbeat.client.domain.model.lazy.netty.server.properties.LazyNettyServerPropertiesRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.wu.framework.lazy.orm.database.lambda.stream.wrapper.LazyWrappers;
|
||||
import org.wu.framework.web.response.Result;
|
||||
import org.wu.framework.web.response.ResultFactory;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.framework.smart.agent.network.heartbeat.client.domain.model.lazy.netty.server.properties.LazyNettyServerProperties;
|
||||
import org.wu.framework.lazy.orm.database.lambda.stream.lambda.LazyLambdaStream;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.wu.framework.lazy.orm.database.lambda.domain.LazyPage;
|
||||
|
||||
/**
|
||||
* describe 服务端配置信息
|
||||
*
|
||||
* @author Jia wei Wu
|
||||
* @date 2024/04/03 03:00 下午
|
||||
* @see org.wu.framework.lazy.orm.core.persistence.reverse.lazy.ddd.DefaultDDDLazyInfrastructurePersistence
|
||||
**/
|
||||
@Repository
|
||||
public class LazyNettyServerPropertiesRepositoryImpl implements LazyNettyServerPropertiesRepository {
|
||||
|
||||
@Resource
|
||||
LazyLambdaStream lazyLambdaStream;
|
||||
|
||||
/**
|
||||
* describe 新增服务端配置信息
|
||||
*
|
||||
* @param lazyNettyServerProperties 新增服务端配置信息
|
||||
* @return {@link Result<LazyNettyServerProperties>} 服务端配置信息新增后领域对象
|
||||
* @author Jia wei Wu
|
||||
* @date 2024/04/03 03:00 下午
|
||||
**/
|
||||
|
||||
@Override
|
||||
public Result<LazyNettyServerProperties> story(LazyNettyServerProperties lazyNettyServerProperties) {
|
||||
LazyNettyServerPropertiesDO lazyNettyServerPropertiesDO = LazyNettyServerPropertiesConverter.INSTANCE.fromLazyNettyServerProperties(lazyNettyServerProperties);
|
||||
String inetHost = lazyNettyServerPropertiesDO.getInetHost();
|
||||
Integer inetPort = lazyNettyServerPropertiesDO.getInetPort();
|
||||
String clientId = lazyNettyServerPropertiesDO.getClientId();
|
||||
lazyNettyServerPropertiesDO.setIsDeleted(false);
|
||||
|
||||
// 查询 ip、端口、客户端
|
||||
boolean exists = lazyLambdaStream.exists(LazyWrappers.<LazyNettyServerPropertiesDO>lambdaWrapper()
|
||||
.eq(LazyNettyServerPropertiesDO::getInetHost, inetHost)
|
||||
.eq(LazyNettyServerPropertiesDO::getInetPort, inetPort)
|
||||
.eq(LazyNettyServerPropertiesDO::getClientId, clientId)
|
||||
);
|
||||
if (exists) {
|
||||
// 更新
|
||||
lazyLambdaStream.update(lazyNettyServerPropertiesDO, LazyWrappers.<LazyNettyServerPropertiesDO>lambdaWrapper()
|
||||
.eq(LazyNettyServerPropertiesDO::getInetHost, inetHost)
|
||||
.eq(LazyNettyServerPropertiesDO::getInetPort, inetPort)
|
||||
.eq(LazyNettyServerPropertiesDO::getClientId, clientId)
|
||||
);
|
||||
} else {
|
||||
lazyLambdaStream.insert(lazyNettyServerPropertiesDO);
|
||||
}
|
||||
|
||||
return ResultFactory.successOf();
|
||||
}
|
||||
|
||||
/**
|
||||
* describe 批量新增服务端配置信息
|
||||
*
|
||||
* @param lazyNettyServerPropertiesList 批量新增服务端配置信息
|
||||
* @return {@link Result<List<LazyNettyServerProperties>>} 服务端配置信息新增后领域对象集合
|
||||
* @author Jia wei Wu
|
||||
* @date 2024/04/03 03:00 下午
|
||||
**/
|
||||
|
||||
@Override
|
||||
public Result<List<LazyNettyServerProperties>> batchStory(List<LazyNettyServerProperties> lazyNettyServerPropertiesList) {
|
||||
List<LazyNettyServerPropertiesDO> lazyNettyServerPropertiesDOList = lazyNettyServerPropertiesList.stream().map(LazyNettyServerPropertiesConverter.INSTANCE::fromLazyNettyServerProperties).collect(Collectors.toList());
|
||||
lazyLambdaStream.upsert(lazyNettyServerPropertiesDOList);
|
||||
return ResultFactory.successOf();
|
||||
}
|
||||
|
||||
/**
|
||||
* describe 查询单个服务端配置信息
|
||||
*
|
||||
* @param lazyNettyServerProperties 查询单个服务端配置信息
|
||||
* @return {@link Result<LazyNettyServerProperties>} 服务端配置信息领域对象
|
||||
* @author Jia wei Wu
|
||||
* @date 2024/04/03 03:00 下午
|
||||
**/
|
||||
|
||||
@Override
|
||||
public Result<LazyNettyServerProperties> findOne(LazyNettyServerProperties lazyNettyServerProperties) {
|
||||
LazyNettyServerPropertiesDO lazyNettyServerPropertiesDO = LazyNettyServerPropertiesConverter.INSTANCE.fromLazyNettyServerProperties(lazyNettyServerProperties);
|
||||
LazyNettyServerProperties lazyNettyServerPropertiesOne = lazyLambdaStream
|
||||
.selectOne(
|
||||
LazyWrappers.lambdaWrapperBean(lazyNettyServerPropertiesDO)
|
||||
.eq(LazyNettyServerPropertiesDO::getIsDeleted,false)
|
||||
, LazyNettyServerProperties.class);
|
||||
return ResultFactory.successOf(lazyNettyServerPropertiesOne);
|
||||
}
|
||||
|
||||
/**
|
||||
* describe 查询多个服务端配置信息
|
||||
*
|
||||
* @param lazyNettyServerProperties 查询多个服务端配置信息
|
||||
* @return {@link Result<List<LazyNettyServerProperties>>} 服务端配置信息领域对象
|
||||
* @author Jia wei Wu
|
||||
* @date 2024/04/03 03:00 下午
|
||||
**/
|
||||
|
||||
@Override
|
||||
public Result<List<LazyNettyServerProperties>> findList(LazyNettyServerProperties lazyNettyServerProperties) {
|
||||
LazyNettyServerPropertiesDO lazyNettyServerPropertiesDO = LazyNettyServerPropertiesConverter.INSTANCE.fromLazyNettyServerProperties(lazyNettyServerProperties);
|
||||
List<LazyNettyServerProperties> lazyNettyServerPropertiesList = lazyLambdaStream.selectList(
|
||||
LazyWrappers.lambdaWrapperBean(lazyNettyServerPropertiesDO)
|
||||
.eq(LazyNettyServerPropertiesDO::getIsDeleted, false)
|
||||
, LazyNettyServerProperties.class);
|
||||
return ResultFactory.successOf(lazyNettyServerPropertiesList);
|
||||
}
|
||||
|
||||
/**
|
||||
* describe 分页查询多个服务端配置信息
|
||||
*
|
||||
* @param size 当前页数
|
||||
* @param current 当前页
|
||||
* @param lazyNettyServerProperties 分页查询多个服务端配置信息
|
||||
* @return {@link Result<LazyPage<LazyNettyServerProperties>>} 分页服务端配置信息领域对象
|
||||
* @author Jia wei Wu
|
||||
* @date 2024/04/03 03:00 下午
|
||||
**/
|
||||
|
||||
@Override
|
||||
public Result<LazyPage<LazyNettyServerProperties>> findPage(int size, int current, LazyNettyServerProperties lazyNettyServerProperties) {
|
||||
LazyNettyServerPropertiesDO lazyNettyServerPropertiesDO = LazyNettyServerPropertiesConverter.INSTANCE.fromLazyNettyServerProperties(lazyNettyServerProperties);
|
||||
LazyPage<LazyNettyServerProperties> lazyPage = new LazyPage<>(current, size);
|
||||
LazyPage<LazyNettyServerProperties> lazyNettyServerPropertiesLazyPage = lazyLambdaStream.selectPage(
|
||||
LazyWrappers
|
||||
.lambdaWrapperBean(lazyNettyServerPropertiesDO)
|
||||
.eq(LazyNettyServerPropertiesDO::getIsDeleted, false)
|
||||
, lazyPage, LazyNettyServerProperties.class);
|
||||
return ResultFactory.successOf(lazyNettyServerPropertiesLazyPage);
|
||||
}
|
||||
|
||||
/**
|
||||
* describe 删除服务端配置信息
|
||||
*
|
||||
* @param lazyNettyServerProperties 删除服务端配置信息
|
||||
* @return {@link Result<LazyNettyServerProperties>} 服务端配置信息
|
||||
* @author Jia wei Wu
|
||||
* @date 2024/04/03 03:00 下午
|
||||
**/
|
||||
|
||||
@Override
|
||||
public Result<LazyNettyServerProperties> remove(LazyNettyServerProperties lazyNettyServerProperties) {
|
||||
LazyNettyServerPropertiesDO lazyNettyServerPropertiesDO = LazyNettyServerPropertiesConverter.INSTANCE.fromLazyNettyServerProperties(lazyNettyServerProperties);
|
||||
lazyLambdaStream.delete(LazyWrappers.lambdaWrapperBean(lazyNettyServerPropertiesDO));
|
||||
return ResultFactory.successOf();
|
||||
}
|
||||
|
||||
/**
|
||||
* describe 是否存在服务端配置信息
|
||||
*
|
||||
* @param lazyNettyServerProperties 服务端配置信息领域对象
|
||||
* @return {@link Result<Boolean>} 是否存在 true 存在,false 不存在
|
||||
* @author Jia wei Wu
|
||||
* @date 2024/04/03 03:00 下午
|
||||
**/
|
||||
|
||||
@Override
|
||||
public Result<Boolean> exists(LazyNettyServerProperties lazyNettyServerProperties) {
|
||||
LazyNettyServerPropertiesDO lazyNettyServerPropertiesDO = LazyNettyServerPropertiesConverter.INSTANCE.fromLazyNettyServerProperties(lazyNettyServerProperties);
|
||||
Boolean exists = lazyLambdaStream.exists(LazyWrappers.lambdaWrapperBean(lazyNettyServerPropertiesDO));
|
||||
return ResultFactory.successOf(exists);
|
||||
}
|
||||
|
||||
/**
|
||||
* 客户端连接服务端状态在线
|
||||
*
|
||||
* @param lazyNettyServerProperties 数据
|
||||
*/
|
||||
@Override
|
||||
public void onLine(LazyNettyServerProperties lazyNettyServerProperties) {
|
||||
LazyNettyServerPropertiesDO lazyNettyServerPropertiesDO = LazyNettyServerPropertiesConverter.INSTANCE.fromLazyNettyServerProperties(lazyNettyServerProperties);
|
||||
lazyLambdaStream.update(lazyNettyServerPropertiesDO,LazyWrappers.<LazyNettyServerPropertiesDO>lambdaWrapper()
|
||||
.eq(LazyNettyServerPropertiesDO::getInetPort,lazyNettyServerPropertiesDO.getInetPort())
|
||||
.eq(LazyNettyServerPropertiesDO::getInetHost,lazyNettyServerPropertiesDO.getInetHost())
|
||||
.eq(LazyNettyServerPropertiesDO::getClientId,lazyNettyServerPropertiesDO.getClientId())
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 推送客户端离线
|
||||
*
|
||||
* @param lazyNettyServerProperties 数据
|
||||
*/
|
||||
@Override
|
||||
public void offLine(LazyNettyServerProperties lazyNettyServerProperties) {
|
||||
LazyNettyServerPropertiesDO lazyNettyServerPropertiesDO = LazyNettyServerPropertiesConverter.INSTANCE.fromLazyNettyServerProperties(lazyNettyServerProperties);
|
||||
lazyLambdaStream.update(lazyNettyServerPropertiesDO,LazyWrappers.<LazyNettyServerPropertiesDO>lambdaWrapper()
|
||||
.eq(LazyNettyServerPropertiesDO::getInetPort,lazyNettyServerPropertiesDO.getInetPort())
|
||||
.eq(LazyNettyServerPropertiesDO::getInetHost,lazyNettyServerPropertiesDO.getInetHost())
|
||||
.eq(LazyNettyServerPropertiesDO::getClientId,lazyNettyServerPropertiesDO.getClientId())
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="org.framework.smart.agent.network.heartbeat.client.infrastructure.mapper.LazyNettyServerPropertiesMapper">
|
||||
<resultMap id="BaseResultMap" type="org.framework.smart.agent.network.heartbeat.client.infrastructure.entity.LazyNettyServerPropertiesDO">
|
||||
<id column="id" property="id" />
|
||||
<result column="create_time" property="createTime" />
|
||||
<result column="update_time" property="updateTime" />
|
||||
<result column="is_deleted" property="isDeleted" />
|
||||
<result column="inet_host" property="inetHost" />
|
||||
<result column="inet_port" property="inetPort" />
|
||||
<result column="client_id" property="clientId" />
|
||||
<result column="type" property="type" />
|
||||
<result column="connect_status" property="connectStatus" />
|
||||
</resultMap>
|
||||
|
||||
</mapper>
|
@ -0,0 +1,29 @@
|
||||
package org.framework.smart.agent.network.heartbeat.client.netty.advanced;
|
||||
|
||||
|
||||
import io.netty.channel.Channel;
|
||||
import org.framework.smart.agent.network.heartbeat.common.MessageType;
|
||||
import org.framework.smart.agent.network.heartbeat.common.NettyProxyMsg;
|
||||
import org.framework.smart.agent.network.heartbeat.common.advanced.AbstractHandleChannelHeartbeatTypeAdvanced;
|
||||
|
||||
|
||||
/**
|
||||
* 服务端 处理客户端心跳
|
||||
* TYPE_HEARTBEAT
|
||||
*/
|
||||
public class ClientHandleChannelHeartbeatTypeAdvanced extends AbstractHandleChannelHeartbeatTypeAdvanced<NettyProxyMsg> {
|
||||
|
||||
/**
|
||||
* 处理当前数据
|
||||
*
|
||||
* @param channel 当前通道
|
||||
* @param msg 通道数据
|
||||
*/
|
||||
@Override
|
||||
public void doHandler(Channel channel, NettyProxyMsg msg) {
|
||||
NettyProxyMsg hb = new NettyProxyMsg();
|
||||
hb.setType(MessageType.TYPE_HEARTBEAT);
|
||||
// channel.writeAndFlush(hb);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
package org.framework.smart.agent.network.heartbeat.client.netty.advanced;
|
||||
|
||||
import io.netty.channel.Channel;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.framework.smart.agent.network.heartbeat.common.NettyProxyMsg;
|
||||
import org.framework.smart.agent.network.heartbeat.common.advanced.client.AbstractHandleDistributeSingleClientMessageTypeAdvanced;
|
||||
|
||||
/**
|
||||
* 接收服务端发送过来的聊天信息
|
||||
*/
|
||||
@Slf4j
|
||||
public class ClientHandleDistributeSingleClientMessageTypeAdvanced extends AbstractHandleDistributeSingleClientMessageTypeAdvanced<NettyProxyMsg> {
|
||||
/**
|
||||
* 处理当前数据
|
||||
*
|
||||
* @param channel 当前通道
|
||||
* @param nettyProxyMsg 通道数据
|
||||
*/
|
||||
@Override
|
||||
protected void doHandler(Channel channel, NettyProxyMsg nettyProxyMsg) {
|
||||
byte[] clientId = nettyProxyMsg.getClientId();
|
||||
byte[] data = nettyProxyMsg.getData();
|
||||
log.info("接收客户端:{},发送过来的聊天信息:{}", new String(clientId), new String(data));
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
package org.framework.smart.agent.network.heartbeat.client.netty.advanced;
|
||||
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelOption;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.framework.smart.agent.network.heartbeat.common.NettyProxyMsg;
|
||||
import org.framework.smart.agent.network.heartbeat.common.NettyRealIdContext;
|
||||
import org.framework.smart.agent.network.heartbeat.common.advanced.client.AbstractHandleDistributeSingleClientRealAutoReadConnectTypeAdvanced;
|
||||
|
||||
@Slf4j
|
||||
public class ClientHandleDistributeSingleClientRealAutoReadConnectTypeAdvanced extends AbstractHandleDistributeSingleClientRealAutoReadConnectTypeAdvanced<NettyProxyMsg> {
|
||||
/**
|
||||
* 处理当前数据
|
||||
*
|
||||
* @param channel 当前通道
|
||||
* @param nettyProxyMsg 通道数据
|
||||
*/
|
||||
@Override
|
||||
protected void doHandler(Channel channel, NettyProxyMsg nettyProxyMsg) {
|
||||
// 获取访客ID
|
||||
byte[] visitorId = nettyProxyMsg.getVisitorId();
|
||||
// 获取访客对应的真实代理通道
|
||||
Channel realChannel = NettyRealIdContext.getReal(visitorId);
|
||||
if (realChannel != null) {
|
||||
realChannel.config().setOption(ChannelOption.AUTO_READ, true);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
package org.framework.smart.agent.network.heartbeat.client.netty.advanced;
|
||||
|
||||
import io.netty.channel.Channel;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.framework.smart.agent.network.heartbeat.common.NettyCommunicationIdContext;
|
||||
import org.framework.smart.agent.network.heartbeat.common.NettyProxyMsg;
|
||||
import org.framework.smart.agent.network.heartbeat.common.NettyRealIdContext;
|
||||
import org.framework.smart.agent.network.heartbeat.common.advanced.client.AbstractHandleDistributeSingleClientRealCloseVisitorTypeAdvanced;
|
||||
|
||||
@Slf4j
|
||||
public class ClientHandleDistributeSingleClientRealCloseVisitorTypeAdvanced extends AbstractHandleDistributeSingleClientRealCloseVisitorTypeAdvanced<NettyProxyMsg> {
|
||||
/**
|
||||
* 处理当前数据
|
||||
*
|
||||
* @param channel 当前通道
|
||||
* @param nettyProxyMsg 通道数据
|
||||
*/
|
||||
@Override
|
||||
protected void doHandler(Channel channel, NettyProxyMsg nettyProxyMsg) {
|
||||
// 关闭代理的真实通道
|
||||
byte[] visitorId = nettyProxyMsg.getVisitorId();
|
||||
NettyRealIdContext.clear(visitorId);
|
||||
NettyCommunicationIdContext.clear(visitorId);
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
package org.framework.smart.agent.network.heartbeat.client.netty.advanced;
|
||||
|
||||
import io.netty.channel.Channel;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.framework.smart.agent.network.heartbeat.client.config.NettyClientProperties;
|
||||
import org.framework.smart.agent.network.heartbeat.client.netty.socket.NettyClientRealSocket;
|
||||
import org.framework.smart.agent.network.heartbeat.common.InternalNetworkPenetrationRealClient;
|
||||
import org.framework.smart.agent.network.heartbeat.common.NettyProxyMsg;
|
||||
import org.framework.smart.agent.network.heartbeat.common.advanced.HandleChannelTypeAdvanced;
|
||||
import org.framework.smart.agent.network.heartbeat.common.advanced.client.AbstractHandleDistributeSingleClientRealConnectTypeAdvanced;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 客户端创建真实代理同奥
|
||||
*/
|
||||
@Slf4j
|
||||
public class ClientHandleDistributeSingleClientRealConnectTypeAdvanced extends AbstractHandleDistributeSingleClientRealConnectTypeAdvanced<NettyProxyMsg> {
|
||||
|
||||
private final NettyClientProperties nettyClientProperties;// 服务端地址信息
|
||||
private final List<HandleChannelTypeAdvanced> handleChannelTypeAdvancedList;
|
||||
|
||||
public ClientHandleDistributeSingleClientRealConnectTypeAdvanced(NettyClientProperties nettyClientProperties, List<HandleChannelTypeAdvanced> handleChannelTypeAdvancedList) {
|
||||
this.nettyClientProperties = nettyClientProperties;
|
||||
this.handleChannelTypeAdvancedList = handleChannelTypeAdvancedList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理当前数据
|
||||
*
|
||||
* @param channel 当前通道
|
||||
* @param msg 通道数据
|
||||
*/
|
||||
@Override
|
||||
protected void doHandler(Channel channel, NettyProxyMsg msg) {
|
||||
// 创建真实端口监听
|
||||
byte[] clientIdBytes = msg.getClientId();
|
||||
byte[] visitorPort = msg.getVisitorPort();
|
||||
byte[] clientTargetIp = msg.getClientTargetIp();
|
||||
byte[] clientTargetPort = msg.getClientTargetPort();
|
||||
byte[] visitorIdBytes = msg.getVisitorId();
|
||||
InternalNetworkPenetrationRealClient internalNetworkPenetrationRealClient =
|
||||
InternalNetworkPenetrationRealClient
|
||||
.builder()
|
||||
.clientId(new String(clientIdBytes))
|
||||
.visitorPort(Integer.valueOf(new String(visitorPort)))
|
||||
.clientTargetIp(new String(clientTargetIp))
|
||||
.clientTargetPort(Integer.valueOf(new String(clientTargetPort)))
|
||||
.visitorId(new String(visitorIdBytes))
|
||||
.build();
|
||||
|
||||
// 绑定真实服务端口
|
||||
NettyClientRealSocket.buildRealServer(internalNetworkPenetrationRealClient, nettyClientProperties, handleChannelTypeAdvancedList);
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
package org.framework.smart.agent.network.heartbeat.client.netty.advanced;
|
||||
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.Channel;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.framework.smart.agent.network.heartbeat.client.config.NettyClientProperties;
|
||||
import org.framework.smart.agent.network.heartbeat.common.NettyProxyMsg;
|
||||
import org.framework.smart.agent.network.heartbeat.common.NettyRealIdContext;
|
||||
import org.framework.smart.agent.network.heartbeat.common.advanced.client.AbstractHandleDistributeChannelTransferTypeAdvanced;
|
||||
import org.framework.smart.agent.network.heartbeat.common.enums.MessageTypeEnums;
|
||||
|
||||
|
||||
/**
|
||||
* 服务端处理客户端数据传输
|
||||
*
|
||||
* @see MessageTypeEnums#DISTRIBUTE_CLIENT_TRANSFER
|
||||
*/
|
||||
@Slf4j
|
||||
public class ClientReportHandleChannelTransferTypeAdvancedHandleDistribute extends AbstractHandleDistributeChannelTransferTypeAdvanced<NettyProxyMsg> {
|
||||
|
||||
private final NettyClientProperties nettyClientProperties;
|
||||
|
||||
public ClientReportHandleChannelTransferTypeAdvancedHandleDistribute(NettyClientProperties nettyClientProperties) {
|
||||
this.nettyClientProperties = nettyClientProperties;
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理当前数据
|
||||
*
|
||||
* @param channel 当前通道
|
||||
* @param nettyProxyMsg 通道数据
|
||||
*/
|
||||
@Override
|
||||
public void doHandler(Channel channel, NettyProxyMsg nettyProxyMsg) {
|
||||
log.debug("接收到服务端需要内网穿透的数据:{}" , nettyProxyMsg);
|
||||
String clientId = nettyClientProperties.getClientId();
|
||||
byte[] visitorPort = nettyProxyMsg.getVisitorPort();
|
||||
byte[] clientTargetIp = nettyProxyMsg.getClientTargetIp();
|
||||
byte[] clientTargetPort = nettyProxyMsg.getClientTargetPort();
|
||||
byte[] visitorId = nettyProxyMsg.getVisitorId();
|
||||
// 真实服务通道
|
||||
Channel realChannel = NettyRealIdContext.getReal(new String(visitorId));
|
||||
if (realChannel == null) {
|
||||
log.error("无法获取访客:{} 真实服务", new String(visitorId));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// 把数据转到真实服务
|
||||
ByteBuf buf = channel.config().getAllocator().buffer(nettyProxyMsg.getData().length);
|
||||
buf.writeBytes(nettyProxyMsg.getData());
|
||||
|
||||
realChannel.writeAndFlush(buf);
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
package org.framework.smart.agent.network.heartbeat.client.netty.advanced;
|
||||
|
||||
import io.netty.channel.Channel;
|
||||
import org.framework.smart.agent.network.heartbeat.client.config.NettyClientProperties;
|
||||
import org.framework.smart.agent.network.heartbeat.common.ChannelContext;
|
||||
import org.framework.smart.agent.network.heartbeat.common.NettyProxyMsg;
|
||||
import org.framework.smart.agent.network.heartbeat.common.advanced.client.AbstractHandleClientChannelActiveAdvanced;
|
||||
import org.framework.smart.agent.network.heartbeat.common.utils.ChannelAttributeKeyUtils;
|
||||
|
||||
/**
|
||||
* 客户端通道 is active
|
||||
*/
|
||||
public class HandleClientChannelActiveAdvanced extends AbstractHandleClientChannelActiveAdvanced<NettyProxyMsg> {
|
||||
private final NettyClientProperties nettyClientProperties;
|
||||
|
||||
public HandleClientChannelActiveAdvanced(NettyClientProperties nettyClientProperties) {
|
||||
this.nettyClientProperties = nettyClientProperties;
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理当前数据
|
||||
*
|
||||
* @param channel 当前通道
|
||||
* @param nettyProxyMsg 通道数据
|
||||
*/
|
||||
@Override
|
||||
protected void doHandler(Channel channel, NettyProxyMsg nettyProxyMsg) {
|
||||
// 缓存当前通道
|
||||
byte[] clientIdByte = nettyProxyMsg.getClientId();
|
||||
String clientId = new String(clientIdByte);
|
||||
ChannelContext.push(channel, clientId);
|
||||
ChannelAttributeKeyUtils.buildClientId(channel, clientId);
|
||||
}
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
package org.framework.smart.agent.network.heartbeat.client.netty.advanced;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import io.netty.channel.Channel;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.framework.smart.agent.network.heartbeat.client.netty.event.ClientChangeEvent;
|
||||
import org.framework.smart.agent.network.heartbeat.common.NettyProxyMsg;
|
||||
import org.framework.smart.agent.network.heartbeat.common.advanced.client.AbstractHandleDistributeConnectSuccessNotificationTypeAdvancedHandle;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 客户端连接成功通知
|
||||
*/
|
||||
@Slf4j
|
||||
public class HandleDistributeConnectSuccessNotificationTypeAdvancedHandle extends AbstractHandleDistributeConnectSuccessNotificationTypeAdvancedHandle<NettyProxyMsg> {
|
||||
|
||||
private final ClientChangeEvent clientChangeEvent;
|
||||
|
||||
|
||||
public HandleDistributeConnectSuccessNotificationTypeAdvancedHandle(ClientChangeEvent clientChangeEvent) {
|
||||
this.clientChangeEvent = clientChangeEvent;
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理当前数据
|
||||
*
|
||||
* @param channel 当前通道
|
||||
* @param msg 通道数据
|
||||
*/
|
||||
@Override
|
||||
protected void doHandler(Channel channel, NettyProxyMsg msg) {
|
||||
// 客户端ID:{},客户端:{}连接成功
|
||||
log.warn("Client ID: {}, Client Data : {} Connection successful", new String(msg.getClientId()), new String(msg.getData()));
|
||||
|
||||
|
||||
// 存储其他客户端状态
|
||||
List<String> clientIdList = JSONObject.parseArray(new String(msg.getData()), String.class);
|
||||
for (String tenantId : clientIdList) {
|
||||
clientChangeEvent.clientOnLine(tenantId);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
package org.framework.smart.agent.network.heartbeat.client.netty.advanced;
|
||||
|
||||
|
||||
import io.netty.channel.Channel;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.framework.smart.agent.network.heartbeat.client.netty.event.ClientChangeEvent;
|
||||
import org.framework.smart.agent.network.heartbeat.common.NettyProxyMsg;
|
||||
import org.framework.smart.agent.network.heartbeat.common.advanced.client.AbstractHandleDistributeDisconnectTypeAdvancedHandle;
|
||||
|
||||
|
||||
/**
|
||||
* 服务端处理客户端断开连接处理
|
||||
* TYPE_DISCONNECT
|
||||
*/
|
||||
@Slf4j
|
||||
public class HandleDistributeDisconnectTypeAdvancedHandle extends AbstractHandleDistributeDisconnectTypeAdvancedHandle<NettyProxyMsg> {
|
||||
|
||||
|
||||
private final ClientChangeEvent clientChangeEvent;
|
||||
|
||||
public HandleDistributeDisconnectTypeAdvancedHandle(ClientChangeEvent clientChangeEvent) {
|
||||
this.clientChangeEvent = clientChangeEvent;
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理当前数据
|
||||
*
|
||||
* @param channel 当前通道
|
||||
* @param msg 通道数据
|
||||
*/
|
||||
@Override
|
||||
public void doHandler(Channel channel, NettyProxyMsg msg) {
|
||||
// 服务下线
|
||||
byte[] data = msg.getData();
|
||||
byte[] clientId = msg.getClientId();
|
||||
String tenantId = new String(clientId);
|
||||
//客户端:{}下线
|
||||
log.warn("Client: {} Offline", tenantId);
|
||||
clientChangeEvent.clientOffLine(tenantId);
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
package org.framework.smart.agent.network.heartbeat.client.netty.advanced;
|
||||
|
||||
import io.netty.channel.Channel;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.framework.smart.agent.network.heartbeat.common.NettyProxyMsg;
|
||||
import org.framework.smart.agent.network.heartbeat.common.advanced.client.AbstractHandleDistributeStagingClosedTypeAdvanced;
|
||||
|
||||
/**
|
||||
* 服务端下发暂存关闭消息处理
|
||||
*/
|
||||
@Slf4j
|
||||
public class HandleDistributeStagingClosedTypeAdvanced extends AbstractHandleDistributeStagingClosedTypeAdvanced<NettyProxyMsg> {
|
||||
|
||||
|
||||
/**
|
||||
* 处理当前数据
|
||||
*
|
||||
* @param channel 当前通道
|
||||
* @param msg 通道数据
|
||||
*/
|
||||
@Override
|
||||
protected void doHandler(Channel channel, NettyProxyMsg msg) {
|
||||
String clientId = new String(msg.getClientId());
|
||||
log.info("客户端:{}离线暂存关闭", clientId);
|
||||
// 修改redis 客户端暂存状态
|
||||
// String stagingStatusKey = StagingConfigKeyConstant.getStagingStatusKey(clientId);
|
||||
// stringRedisTemplate.opsForValue().set(stagingStatusKey, StagingStatus.CLOSED.name());
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
package org.framework.smart.agent.network.heartbeat.client.netty.advanced;
|
||||
|
||||
import io.netty.channel.Channel;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.framework.smart.agent.network.heartbeat.common.NettyProxyMsg;
|
||||
import org.framework.smart.agent.network.heartbeat.common.advanced.client.AbstractHandleDistributeStagingOpenedTypeAdvanced;
|
||||
|
||||
/**
|
||||
* 服务端下发暂存开启消息处理
|
||||
*/
|
||||
@Slf4j
|
||||
public class HandleDistributeStagingOpenedTypeAdvanced extends AbstractHandleDistributeStagingOpenedTypeAdvanced<NettyProxyMsg> {
|
||||
|
||||
|
||||
public HandleDistributeStagingOpenedTypeAdvanced() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理当前数据
|
||||
*
|
||||
* @param channel 当前通道
|
||||
* @param msg 通道数据
|
||||
*/
|
||||
@Override
|
||||
protected void doHandler(Channel channel, NettyProxyMsg msg) {
|
||||
String clientId = new String(msg.getClientId());
|
||||
//客户端:{}离线暂存开启
|
||||
log.warn("Client: {} Offline temporary storage enabled", new String(msg.getClientId()));
|
||||
// 修改redis 客户端暂存状态
|
||||
// String stagingStatusKey = StagingConfigKeyConstant.getStagingStatusKey(clientId);
|
||||
// stringRedisTemplate.opsForValue().set(stagingStatusKey, StagingStatus.OPENED.name());
|
||||
}
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
package org.framework.smart.agent.network.heartbeat.client.netty.event;
|
||||
|
||||
/**
|
||||
* 客户端状态变更事件
|
||||
*/
|
||||
public interface ClientChangeEvent {
|
||||
|
||||
|
||||
/**
|
||||
* 推送客户端在线
|
||||
*/
|
||||
void clientOnLine(String clientId);
|
||||
|
||||
/**
|
||||
* 推送客户端在线
|
||||
* @param clientId 客户端
|
||||
* @param inetHost 服务端ip
|
||||
* @param inetPort 服务端端口
|
||||
* @param serverId 服务端ID
|
||||
*/
|
||||
void clientOnLine(String inetHost, int inetPort,String serverId ,String clientId);
|
||||
|
||||
/**
|
||||
* 推送客户端离线
|
||||
*/
|
||||
void clientOffLine(String clientId);
|
||||
|
||||
/**
|
||||
* 推送客户端离线
|
||||
*
|
||||
* @param inetHost 服务端ip
|
||||
* @param inetPort 服务端端口
|
||||
* @param serverId 服务端ID
|
||||
* @param clientId 客户端
|
||||
*/
|
||||
void clientOffLine(String inetHost, int inetPort,String serverId,String clientId);
|
||||
|
||||
/**
|
||||
* 暂存开启
|
||||
*
|
||||
* @param clientId 租户ID
|
||||
*/
|
||||
void stagingOpen(String clientId);
|
||||
|
||||
|
||||
/**
|
||||
* 暂存关闭
|
||||
*
|
||||
* @param clientId 客户端ID 对应的租户
|
||||
*/
|
||||
void stagingClose(String clientId);
|
||||
}
|
@ -0,0 +1,131 @@
|
||||
package org.framework.smart.agent.network.heartbeat.client.netty.event;
|
||||
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
import org.framework.smart.agent.network.heartbeat.client.domain.model.lazy.netty.server.properties.LazyNettyServerProperties;
|
||||
import org.framework.smart.agent.network.heartbeat.client.domain.model.lazy.netty.server.properties.LazyNettyServerPropertiesRepository;
|
||||
import org.framework.smart.agent.network.heartbeat.common.enums.NettyClientStatus;
|
||||
import org.springframework.stereotype.Component;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
public class DefaultClientChangeEventImpl implements ClientChangeEvent {
|
||||
|
||||
|
||||
@Resource
|
||||
private LazyNettyServerPropertiesRepository lazyNettyServerPropertiesRepository;
|
||||
|
||||
|
||||
// private final StringRedisTemplate stringRedisTemplate;
|
||||
// private final RedisProviderTemplate redisProviderTemplate;
|
||||
//
|
||||
// public DefaultClientChangeEvent1Impl(StringRedisTemplate stringRedisTemplate, RedisProviderTemplate redisProviderTemplate) {
|
||||
// this.stringRedisTemplate = stringRedisTemplate;
|
||||
// this.redisProviderTemplate = redisProviderTemplate;
|
||||
// }
|
||||
|
||||
|
||||
/**
|
||||
* 推送客户端在线
|
||||
*/
|
||||
@Override
|
||||
public void clientOnLine(String clientId) {
|
||||
// // 获取当前客户端ID
|
||||
// if (ObjectUtils.isEmpty(clientId)) {
|
||||
// clientId = stringRedisTemplate.opsForValue().get(ClientConfigKeyUtils.CLIENT_ID_KEY);
|
||||
// }
|
||||
// String clientStatusKey = ClientConfigKeyUtils.getClientStatusKey(clientId);
|
||||
// // 如果可以已经在线状态不推送
|
||||
// stringRedisTemplate.opsForValue().set(clientStatusKey, NettyClientStatus.ON_LINE.name());
|
||||
// ClientOnLineState clientOnLineState = new ClientOnLineState();
|
||||
// clientOnLineState.setClientId(clientId);
|
||||
// clientOnLineState.setOnLineState(NettyClientStatus.ON_LINE.name());
|
||||
// // 暂存扫描触发
|
||||
// redisProviderTemplate.send(RedisChannelConstant.REDIS_CLIENT_ONLINE_OR_OFFLINE_CHANNEL,clientOnLineState);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 推送客户端在线
|
||||
*
|
||||
* @param inetHost 服务端ip
|
||||
* @param inetPort 服务端端口
|
||||
* @param serverId 服务端ID
|
||||
* @param clientId 客户端
|
||||
*/
|
||||
@Override
|
||||
public void clientOnLine(String inetHost, int inetPort, String serverId, String clientId) {
|
||||
LazyNettyServerProperties lazyNettyServerProperties = new LazyNettyServerProperties();
|
||||
lazyNettyServerProperties.setClientId(clientId);
|
||||
lazyNettyServerProperties.setInetHost(inetHost);
|
||||
lazyNettyServerProperties.setInetPort(inetPort);
|
||||
lazyNettyServerProperties.setConnectStatus(NettyClientStatus.ON_LINE);
|
||||
lazyNettyServerPropertiesRepository.onLine(lazyNettyServerProperties);
|
||||
// 更改状态未在线
|
||||
clientOnLine(clientId);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 推送客户端离线
|
||||
*/
|
||||
@Override
|
||||
public void clientOffLine(String clientId) {
|
||||
// if (ObjectUtils.isEmpty(clientId)) {
|
||||
// clientId = stringRedisTemplate.opsForValue().get(ClientConfigKeyUtils.CLIENT_ID_KEY);
|
||||
// }
|
||||
// String clientStatusKey = ClientConfigKeyUtils.getClientStatusKey(clientId);
|
||||
// // 离线状态
|
||||
// stringRedisTemplate.opsForValue().set(clientStatusKey, NettyClientStatus.OFF_LINE.name());
|
||||
// // 暂存状态
|
||||
// stagingOpen(clientId);
|
||||
// // 暂存扫描触发
|
||||
// ClientOnLineState clientOnLineState = new ClientOnLineState();
|
||||
// clientOnLineState.setClientId(clientId);
|
||||
// clientOnLineState.setOnLineState(NettyClientStatus.OFF_LINE.name());
|
||||
// redisProviderTemplate.send(RedisChannelConstant.REDIS_CLIENT_ONLINE_OR_OFFLINE_CHANNEL,clientOnLineState);
|
||||
}
|
||||
|
||||
/**
|
||||
* 推送客户端离线
|
||||
*
|
||||
* @param inetHost 服务端ip
|
||||
* @param inetPort 服务端端口
|
||||
* @param serverId
|
||||
* @param clientId 客户端
|
||||
*/
|
||||
@Override
|
||||
public void clientOffLine(String inetHost, int inetPort, String serverId, String clientId) {
|
||||
LazyNettyServerProperties lazyNettyServerProperties = new LazyNettyServerProperties();
|
||||
lazyNettyServerProperties.setClientId(clientId);
|
||||
lazyNettyServerProperties.setInetHost(inetHost);
|
||||
lazyNettyServerProperties.setInetPort(inetPort);
|
||||
lazyNettyServerProperties.setConnectStatus(NettyClientStatus.OFF_LINE);
|
||||
lazyNettyServerPropertiesRepository.offLine(lazyNettyServerProperties);
|
||||
clientOffLine(clientId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stagingOpen(String clientId) {
|
||||
// String stagingStatusKey = StagingConfigKeyConstant.getStagingStatusKey(clientId);
|
||||
// stringRedisTemplate.opsForValue().set(stagingStatusKey, StagingStatus.OPENED.name());
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 暂存关闭
|
||||
*
|
||||
* @param clientId 租户ID
|
||||
*/
|
||||
@Override
|
||||
public void stagingClose(String clientId) {
|
||||
// if (clientId == null) {
|
||||
// clientId = stringRedisTemplate.opsForValue().get(ClientConfigKeyUtils.CLIENT_ID_KEY);
|
||||
// }
|
||||
// String stagingStatusKey = StagingConfigKeyConstant.getStagingStatusKey(clientId);
|
||||
// stringRedisTemplate.opsForValue().set(stagingStatusKey, StagingStatus.CLOSED.name());
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
package org.framework.smart.agent.network.heartbeat.client.netty.filter;
|
||||
|
||||
import io.netty.channel.ChannelInitializer;
|
||||
import io.netty.channel.ChannelPipeline;
|
||||
import io.netty.channel.socket.SocketChannel;
|
||||
import io.netty.handler.codec.string.StringDecoder;
|
||||
import io.netty.handler.codec.string.StringEncoder;
|
||||
import io.netty.handler.timeout.IdleStateHandler;
|
||||
import org.framework.smart.agent.network.heartbeat.client.netty.handler.NettyClientHandler;
|
||||
import org.framework.smart.agent.network.heartbeat.client.netty.socket.NettyClientSocket;
|
||||
import org.framework.smart.agent.network.heartbeat.common.adapter.ChannelTypeAdapter;
|
||||
import org.framework.smart.agent.network.heartbeat.common.decoder.NettyProxyMsgDecoder;
|
||||
import org.framework.smart.agent.network.heartbeat.common.encoder.NettyProxyMsgEncoder;
|
||||
|
||||
public class NettyClientFilter extends ChannelInitializer<SocketChannel> {
|
||||
|
||||
|
||||
private final ChannelTypeAdapter channelTypeAdapter;
|
||||
private final NettyClientSocket nettyClientSocket;
|
||||
|
||||
public NettyClientFilter(ChannelTypeAdapter channelTypeAdapter, NettyClientSocket nettyClientSocket) {
|
||||
this.channelTypeAdapter = channelTypeAdapter;
|
||||
this.nettyClientSocket = nettyClientSocket;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initChannel(SocketChannel ch) throws Exception {
|
||||
ChannelPipeline pipeline = ch.pipeline();
|
||||
|
||||
/* * 解码和编码,应和服务端一致 * */
|
||||
// pipeline.addLast(new NettyMsgDecoder(Integer.MAX_VALUE, 0, 4, -4, 0));
|
||||
// pipeline.addLast(new NettMsgEncoder());
|
||||
// 解码、编码
|
||||
pipeline.addLast(new NettyProxyMsgDecoder(Integer.MAX_VALUE, 0, 4, -4, 0));
|
||||
pipeline.addLast(new NettyProxyMsgEncoder());
|
||||
// pipeline.addLast("framer", new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter()));
|
||||
//入参说明: 读超时时间、写超时时间、所有类型的超时时间、时间格式
|
||||
//因为服务端设置的超时时间是5秒,所以设置4秒
|
||||
|
||||
pipeline.addLast(new IdleStateHandler(0, 4, 0));
|
||||
pipeline.addLast("decoder", new StringDecoder());
|
||||
pipeline.addLast("encoder", new StringEncoder());
|
||||
pipeline.addLast("doHandler", new NettyClientHandler(channelTypeAdapter, nettyClientSocket)); //客户端的逻辑
|
||||
}
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
package org.framework.smart.agent.network.heartbeat.client.netty.filter;
|
||||
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelInitializer;
|
||||
import io.netty.channel.ChannelPipeline;
|
||||
import io.netty.channel.socket.SocketChannel;
|
||||
import org.framework.smart.agent.network.heartbeat.client.netty.handler.NettyClientRealHandler;
|
||||
|
||||
public class NettyClientRealFilter extends ChannelInitializer<SocketChannel> {
|
||||
/**
|
||||
* This method will be called once the {@link Channel} was registered. After the method returns this instance
|
||||
* will be removed from the {@link ChannelPipeline} of the {@link Channel}.
|
||||
*
|
||||
* @param ch the {@link Channel} which was registered.
|
||||
* @throws Exception is thrown if an error occurs. In that case it will be handled by
|
||||
* {@link #exceptionCaught(ChannelHandlerContext, Throwable)} which will by default connectionClose
|
||||
* the {@link Channel}.
|
||||
*/
|
||||
@Override
|
||||
protected void initChannel(SocketChannel ch) throws Exception {
|
||||
ChannelPipeline pipeline = ch.pipeline();
|
||||
pipeline.addLast(new NettyClientRealHandler());
|
||||
// // 解码、编码
|
||||
// pipeline.addLast(new NettyProxyMsgDecoder(Integer.MAX_VALUE, 0, 4, -4, 0));
|
||||
// pipeline.addLast(new NettMsgEncoder());
|
||||
// pipeline.addLast(new NettyProxyMsgDecoder(Integer.MAX_VALUE, 0, 4, -4, 0));
|
||||
// pipeline.addLast(new NettyProxyMsgEncoder());
|
||||
}
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
package org.framework.smart.agent.network.heartbeat.client.netty.filter;
|
||||
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelInitializer;
|
||||
import io.netty.channel.ChannelPipeline;
|
||||
import io.netty.channel.socket.SocketChannel;
|
||||
import org.framework.smart.agent.network.heartbeat.client.netty.handler.NettyClientVisitorRealHandler;
|
||||
import org.framework.smart.agent.network.heartbeat.common.adapter.ChannelTypeAdapter;
|
||||
import org.framework.smart.agent.network.heartbeat.common.decoder.NettyProxyMsgDecoder;
|
||||
import org.framework.smart.agent.network.heartbeat.common.encoder.NettyProxyMsgEncoder;
|
||||
|
||||
/**
|
||||
* netty 客户端连接真实服服务端访客拦截器
|
||||
*/
|
||||
public class NettyClientVisitorRealFilter extends ChannelInitializer<SocketChannel> {
|
||||
private final ChannelTypeAdapter channelTypeAdapter;
|
||||
|
||||
public NettyClientVisitorRealFilter(ChannelTypeAdapter channelTypeAdapter) {
|
||||
this.channelTypeAdapter = channelTypeAdapter;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will be called once the {@link Channel} was registered. After the method returns this instance
|
||||
* will be removed from the {@link ChannelPipeline} of the {@link Channel}.
|
||||
*
|
||||
* @param ch the {@link Channel} which was registered.
|
||||
* @throws Exception is thrown if an error occurs. In that case it will be handled by
|
||||
* {@link #exceptionCaught(ChannelHandlerContext, Throwable)} which will by default connectionClose
|
||||
* the {@link Channel}.
|
||||
*/
|
||||
@Override
|
||||
protected void initChannel(SocketChannel ch) throws Exception {
|
||||
ChannelPipeline pipeline = ch.pipeline();
|
||||
// // 解码、编码
|
||||
// pipeline.addLast(new NettyProxyMsgDecoder(Integer.MAX_VALUE, 0, 4, -4, 0));
|
||||
// pipeline.addLast(new NettMsgEncoder());
|
||||
pipeline.addLast(new NettyProxyMsgDecoder(Integer.MAX_VALUE, 0, 4, -4, 0));
|
||||
pipeline.addLast(new NettyProxyMsgEncoder());
|
||||
pipeline.addLast(new NettyClientVisitorRealHandler(channelTypeAdapter));
|
||||
}
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
package org.framework.smart.agent.network.heartbeat.client.netty.handler;
|
||||
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelInboundHandlerAdapter;
|
||||
import io.netty.handler.timeout.IdleState;
|
||||
import io.netty.handler.timeout.IdleStateEvent;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
public class HeartBeatClientHandler extends ChannelInboundHandlerAdapter {
|
||||
private final int lossConnectCount = 0;
|
||||
|
||||
@Override
|
||||
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
|
||||
System.out.println("客户端循环心跳监测发送: " + new Date());
|
||||
if (evt instanceof IdleStateEvent event) {
|
||||
if (event.state() == IdleState.WRITER_IDLE) {
|
||||
ctx.writeAndFlush("biubiu");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,121 @@
|
||||
package org.framework.smart.agent.network.heartbeat.client.netty.handler;
|
||||
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.EventLoop;
|
||||
import io.netty.channel.SimpleChannelInboundHandler;
|
||||
import io.netty.handler.timeout.IdleState;
|
||||
import io.netty.handler.timeout.IdleStateEvent;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.framework.smart.agent.network.heartbeat.client.netty.socket.NettyClientSocket;
|
||||
import org.framework.smart.agent.network.heartbeat.common.MessageType;
|
||||
import org.framework.smart.agent.network.heartbeat.common.NettyProxyMsg;
|
||||
import org.framework.smart.agent.network.heartbeat.common.adapter.ChannelTypeAdapter;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Date;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* description
|
||||
*
|
||||
* @author 吴佳伟
|
||||
* @date 2023/09/13 10:29
|
||||
*/
|
||||
@Slf4j
|
||||
public class NettyClientHandler extends SimpleChannelInboundHandler<NettyProxyMsg> {
|
||||
|
||||
private final ChannelTypeAdapter channelTypeAdapter;
|
||||
private final NettyClientSocket nettyClientSocket;
|
||||
|
||||
|
||||
public NettyClientHandler(ChannelTypeAdapter channelTypeAdapter, NettyClientSocket nettyClientSocket) {
|
||||
this.channelTypeAdapter = channelTypeAdapter;
|
||||
this.nettyClientSocket = nettyClientSocket;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ctx the {@link ChannelHandlerContext} which this {@link SimpleChannelInboundHandler}
|
||||
* belongs to
|
||||
* @param msg the message to handle
|
||||
*/
|
||||
@Override
|
||||
protected void channelRead0(ChannelHandlerContext ctx, NettyProxyMsg msg) {
|
||||
// log.info("第" + count + "次" + ",客户端接受的消息:" + msg);
|
||||
// log.info("第" + count + "次" + ",客户端接受的消息内容:" + new String(msg.getData()));
|
||||
// count++;
|
||||
// 接收服务端、或者是代理端的信息
|
||||
Channel channel = ctx.channel();
|
||||
// log.info("type:{},clientId:{},data:{}",msg.getMysqlType(),new String(msg.getClientId()),new String(msg.getData()));
|
||||
channelTypeAdapter.handler(channel, msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* 建立连接时
|
||||
*/
|
||||
@Override
|
||||
public void channelActive(ChannelHandlerContext ctx) throws Exception {
|
||||
// 建立连接时
|
||||
log.info("When establishing a connection:{}" , new Date());
|
||||
ctx.fireChannelActive();
|
||||
String clientId = nettyClientSocket.getClientId();
|
||||
// 处理客户端连接成功
|
||||
Channel channel = ctx.channel();
|
||||
NettyProxyMsg nettyMsg = new NettyProxyMsg();
|
||||
nettyMsg.setType(MessageType.CLIENT_CHANNEL_ACTIVE);
|
||||
nettyMsg.setClientId(clientId);
|
||||
channelTypeAdapter.handler(channel, nettyMsg);
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭连接时
|
||||
*/
|
||||
@Override
|
||||
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
|
||||
//服务端主动关闭当前客户端连接时
|
||||
log.info("When the server actively closes the current client connection:{}" , new Date());
|
||||
final EventLoop eventLoop = ctx.channel().eventLoop();
|
||||
eventLoop.schedule(() -> {
|
||||
try {
|
||||
nettyClientSocket.newConnect2Server();
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}, 1L, TimeUnit.SECONDS);
|
||||
|
||||
super.channelInactive(ctx);
|
||||
}
|
||||
|
||||
/**
|
||||
* 心跳请求处理 * 每4秒发送一次心跳请求; *
|
||||
*/
|
||||
@Override
|
||||
public void userEventTriggered(ChannelHandlerContext ctx, Object obj) throws Exception {
|
||||
if (obj instanceof IdleStateEvent event) {
|
||||
if (IdleState.WRITER_IDLE.equals(event.state())) { //如果写通道处于空闲状态,就发送心跳命令
|
||||
String clientId = nettyClientSocket.getClientId();
|
||||
NettyProxyMsg nettyMsg = new NettyProxyMsg();
|
||||
nettyMsg.setType(MessageType.TYPE_HEARTBEAT);
|
||||
nettyMsg.setData(clientId.getBytes(StandardCharsets.UTF_8));
|
||||
nettyMsg.setClientId(clientId.getBytes(StandardCharsets.UTF_8));
|
||||
ctx.writeAndFlush(nettyMsg);// 发送心跳数据
|
||||
} else if (event.state() == IdleState.WRITER_IDLE) { // 如果检测到写空闲状态,关闭连接
|
||||
// 离线、暂存通知
|
||||
String clientId = nettyClientSocket.getClientId();
|
||||
Channel channel = ctx.channel();
|
||||
NettyProxyMsg nettyMsg = new NettyProxyMsg();
|
||||
nettyMsg.setType(MessageType.DISTRIBUTE_CLIENT_DISCONNECTION_NOTIFICATION);
|
||||
nettyMsg.setClientId(clientId.getBytes(StandardCharsets.UTF_8));
|
||||
channelTypeAdapter.handler(channel, nettyMsg);
|
||||
ctx.close();
|
||||
}
|
||||
|
||||
} else {
|
||||
super.userEventTriggered(ctx, obj);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,85 @@
|
||||
package org.framework.smart.agent.network.heartbeat.client.netty.handler;
|
||||
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.SimpleChannelInboundHandler;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.framework.smart.agent.network.heartbeat.common.MessageType;
|
||||
import org.framework.smart.agent.network.heartbeat.common.NettyCommunicationIdContext;
|
||||
import org.framework.smart.agent.network.heartbeat.common.NettyProxyMsg;
|
||||
import org.framework.smart.agent.network.heartbeat.common.utils.ChannelAttributeKeyUtils;
|
||||
|
||||
/**
|
||||
* 来自客户端 真实服务器返回的数据请求
|
||||
*/
|
||||
@Slf4j
|
||||
public class NettyClientRealHandler extends SimpleChannelInboundHandler<ByteBuf> {
|
||||
|
||||
@Override
|
||||
public void channelRead0(ChannelHandlerContext ctx, ByteBuf buf) throws Exception {
|
||||
|
||||
// 客户端发送真实数据到代理了
|
||||
byte[] bytes = new byte[buf.readableBytes()];
|
||||
buf.readBytes(bytes);
|
||||
log.debug("接收客户端真实服务数据:{}", new String(bytes));
|
||||
String visitorId = ChannelAttributeKeyUtils.getVisitorId(ctx.channel());
|
||||
Integer visitorPort = ChannelAttributeKeyUtils.getVisitorPort(ctx.channel());
|
||||
String clientId = ChannelAttributeKeyUtils.getClientId(ctx.channel());
|
||||
// 访客通信通道 上报服务端代理完成
|
||||
Channel visitorChannel = NettyCommunicationIdContext.getVisitor(visitorId);
|
||||
NettyProxyMsg returnMessage = new NettyProxyMsg();
|
||||
returnMessage.setType(MessageType.REPORT_CLIENT_TRANSFER);
|
||||
returnMessage.setVisitorId(visitorId);
|
||||
returnMessage.setClientId(clientId);
|
||||
returnMessage.setVisitorPort(visitorPort);
|
||||
returnMessage.setData(bytes);
|
||||
|
||||
visitorChannel.writeAndFlush(returnMessage);
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelActive(ChannelHandlerContext ctx) throws Exception {
|
||||
super.channelActive(ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
|
||||
String clientId = ChannelAttributeKeyUtils.getClientId(ctx.channel());
|
||||
String visitorId = ChannelAttributeKeyUtils.getVisitorId(ctx.channel());
|
||||
// 客户端真实通信通道
|
||||
Channel visitor = NettyCommunicationIdContext.getVisitor(visitorId);
|
||||
if (visitor != null) {
|
||||
// 上报关闭这个客户端的访客通道
|
||||
NettyProxyMsg closeVisitorMsg = new NettyProxyMsg();
|
||||
closeVisitorMsg.setType(MessageType.REPORT_SINGLE_CLIENT_CLOSE_VISITOR);
|
||||
closeVisitorMsg.setVisitorId(visitorId);
|
||||
visitor.writeAndFlush(closeVisitorMsg);
|
||||
}
|
||||
|
||||
super.channelInactive(ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelWritabilityChanged(ChannelHandlerContext ctx) throws Exception {
|
||||
// String vid = ctx.channel().attr(Constant.VID).get();
|
||||
// if (StringUtil.isNullOrEmpty(vid)) {
|
||||
// super.channelWritabilityChanged(ctx);
|
||||
// return;
|
||||
// }
|
||||
// Channel proxyChannel = Constant.vpc.get(vid);
|
||||
// if (proxyChannel != null) {
|
||||
// proxyChannel.config().setOption(ChannelOption.AUTO_READ, ctx.channel().isWritable());
|
||||
// }
|
||||
|
||||
super.channelWritabilityChanged(ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
|
||||
super.exceptionCaught(ctx, cause);
|
||||
}
|
||||
}
|
@ -0,0 +1,66 @@
|
||||
package org.framework.smart.agent.network.heartbeat.client.netty.handler;
|
||||
|
||||
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.SimpleChannelInboundHandler;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.framework.smart.agent.network.heartbeat.common.ChannelContext;
|
||||
import org.framework.smart.agent.network.heartbeat.common.MessageType;
|
||||
import org.framework.smart.agent.network.heartbeat.common.NettyProxyMsg;
|
||||
import org.framework.smart.agent.network.heartbeat.common.adapter.ChannelTypeAdapter;
|
||||
import org.framework.smart.agent.network.heartbeat.common.utils.ChannelAttributeKeyUtils;
|
||||
|
||||
/**
|
||||
* 客户端访客通信通道 处理器
|
||||
*/
|
||||
@Slf4j
|
||||
public class NettyClientVisitorRealHandler extends SimpleChannelInboundHandler<NettyProxyMsg> {
|
||||
private final ChannelTypeAdapter channelTypeAdapter;
|
||||
|
||||
public NettyClientVisitorRealHandler(ChannelTypeAdapter channelTypeAdapter) {
|
||||
this.channelTypeAdapter = channelTypeAdapter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelRead0(ChannelHandlerContext ctx, NettyProxyMsg nettyProxyMsg) throws Exception {
|
||||
Channel channel = ctx.channel();
|
||||
channelTypeAdapter.handler(channel, nettyProxyMsg);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelActive(ChannelHandlerContext ctx) throws Exception {
|
||||
super.channelActive(ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
|
||||
|
||||
String clientId = ChannelAttributeKeyUtils.getClientId(ctx.channel());
|
||||
String visitorId = ChannelAttributeKeyUtils.getVisitorId(ctx.channel());
|
||||
// 关闭访客
|
||||
ChannelContext.ClientChannel clientChannel = ChannelContext.get(clientId);
|
||||
if (clientChannel != null) {
|
||||
Channel channel = clientChannel.getChannel();
|
||||
// 上报关闭这个客户端的访客通道
|
||||
NettyProxyMsg closeVisitorMsg = new NettyProxyMsg();
|
||||
closeVisitorMsg.setType(MessageType.REPORT_SINGLE_CLIENT_CLOSE_VISITOR);
|
||||
closeVisitorMsg.setVisitorId(visitorId);
|
||||
channel.writeAndFlush(closeVisitorMsg);
|
||||
}
|
||||
|
||||
super.channelInactive(ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelWritabilityChanged(ChannelHandlerContext ctx) throws Exception {
|
||||
|
||||
super.channelWritabilityChanged(ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
|
||||
super.exceptionCaught(ctx, cause);
|
||||
}
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
//package org.framework.smart.agent.network.heartbeat.client.netty.listener;
|
||||
//
|
||||
//
|
||||
//import lombok.extern.slf4j.Slf4j;
|
||||
//import org.springframework.stereotype.Component;
|
||||
//import org.framework.smart.agent.network.heartbeat.client.netty.config.NettyClientProperties;
|
||||
//import org.framework.smart.agent.network.heartbeat.client.rpc.StagingNoticeApiRpc;
|
||||
//import org.framework.smart.agent.network.heartbeat.common.constant.RedisChannelConstant;
|
||||
//
|
||||
///**
|
||||
// * 客户端暂存开启、关闭通知
|
||||
// *
|
||||
// * @see RedisChannelConstant#REDIS_CLIENT_STAGING_OPENED_OR_CLOSED_CHANNEL
|
||||
// */
|
||||
//@Slf4j
|
||||
//@Component
|
||||
//public class ClientStagingOpenedOrClosedListener {
|
||||
//
|
||||
// private final StagingNoticeApiRpc stagingNoticeApiRpc;
|
||||
// private final NettyClientProperties nettyServerProperties;
|
||||
//
|
||||
//
|
||||
// public ClientStagingOpenedOrClosedListener(StagingNoticeApiRpc stagingNoticeApiRpc, NettyClientProperties nettyServerProperties) {
|
||||
// this.stagingNoticeApiRpc = stagingNoticeApiRpc;
|
||||
// this.nettyServerProperties = nettyServerProperties;
|
||||
//
|
||||
// }
|
||||
//
|
||||
//// /**
|
||||
//// * 使用redis监听注解监听数据
|
||||
//// *
|
||||
//// * @param consumerRecord 客户端暂存开启、关闭通知
|
||||
//// */
|
||||
//// @EasyRedisListener(topics = RedisChannelConstant.REDIS_CLIENT_STAGING_OPENED_OR_CLOSED_CHANNEL)
|
||||
//// public void subscription(ConsumerRecord<String, ClientStagingRedisChannelBo> consumerRecord, Acknowledgment acknowledgment) {
|
||||
//// ClientStagingRedisChannelBo payload = consumerRecord.payload();
|
||||
//// String clientId = payload.getClientId();
|
||||
//// // 如果客户端ID为空默认当前客户端
|
||||
//// if (ObjectUtils.isEmpty(clientId)) {
|
||||
//// clientId = nettyServerProperties.getClientId();
|
||||
//// }
|
||||
//// StagingStatus stagingStatus = payload.getStagingStatus();
|
||||
//// log.info("客户端:【{}】暂存:【{}】通知", clientId, stagingStatus);
|
||||
////
|
||||
////
|
||||
//// if (StagingStatus.OPENED.equals(stagingStatus)) {
|
||||
//// stagingNoticeApiRpc.stagingOpened(clientId);
|
||||
//// } else if (StagingStatus.CLOSED.equals(stagingStatus)) {
|
||||
//// stagingNoticeApiRpc.stagingClosed(clientId);
|
||||
//// }
|
||||
//// acknowledgment.acknowledge();
|
||||
//// }
|
||||
//}
|
@ -0,0 +1,183 @@
|
||||
package org.framework.smart.agent.network.heartbeat.client.netty.socket;
|
||||
|
||||
|
||||
import io.netty.bootstrap.Bootstrap;
|
||||
import io.netty.channel.*;
|
||||
import io.netty.channel.nio.NioEventLoopGroup;
|
||||
import io.netty.channel.socket.nio.NioSocketChannel;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.framework.smart.agent.network.heartbeat.client.config.NettyClientProperties;
|
||||
import org.framework.smart.agent.network.heartbeat.client.netty.filter.NettyClientRealFilter;
|
||||
import org.framework.smart.agent.network.heartbeat.client.netty.filter.NettyClientVisitorRealFilter;
|
||||
import org.framework.smart.agent.network.heartbeat.common.*;
|
||||
import org.framework.smart.agent.network.heartbeat.common.adapter.ChannelTypeAdapter;
|
||||
import org.framework.smart.agent.network.heartbeat.common.advanced.HandleChannelTypeAdvanced;
|
||||
import org.framework.smart.agent.network.heartbeat.common.utils.ChannelAttributeKeyUtils;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* 客户端连接真实服务
|
||||
*/
|
||||
@Slf4j
|
||||
public class NettyClientRealSocket {
|
||||
static EventLoopGroup eventLoopGroup = new NioEventLoopGroup();
|
||||
|
||||
/**
|
||||
* 连接真实服务
|
||||
*
|
||||
* @param internalNetworkPenetrationRealClient 访客信息
|
||||
* @param nettyClientProperties 服务端地址信息
|
||||
*/
|
||||
public static void buildRealServer(InternalNetworkPenetrationRealClient internalNetworkPenetrationRealClient,
|
||||
NettyClientProperties nettyClientProperties,
|
||||
List<HandleChannelTypeAdvanced> handleChannelTypeAdvancedList) {
|
||||
|
||||
buildNewRealServer(internalNetworkPenetrationRealClient, nettyClientProperties, handleChannelTypeAdvancedList);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param internalNetworkPenetrationRealClient 访客信息
|
||||
* @param nettyClientProperties 服务端地址信息
|
||||
*/
|
||||
private static void buildNewRealServer(InternalNetworkPenetrationRealClient internalNetworkPenetrationRealClient,
|
||||
NettyClientProperties nettyClientProperties,
|
||||
List<HandleChannelTypeAdvanced> handleChannelTypeAdvancedList) {
|
||||
try {
|
||||
String clientId = internalNetworkPenetrationRealClient.getClientId();
|
||||
String clientTargetIp = internalNetworkPenetrationRealClient.getClientTargetIp();
|
||||
Integer clientTargetPort = internalNetworkPenetrationRealClient.getClientTargetPort();
|
||||
Integer visitorPort = internalNetworkPenetrationRealClient.getVisitorPort();
|
||||
String visitorId = internalNetworkPenetrationRealClient.getVisitorId();
|
||||
Bootstrap bootstrap = new Bootstrap();
|
||||
bootstrap.group(eventLoopGroup).channel(NioSocketChannel.class)
|
||||
.handler(new NettyClientRealFilter());
|
||||
bootstrap.connect(clientTargetIp, clientTargetPort).addListener((ChannelFutureListener) future -> {
|
||||
if (future.isSuccess()) {
|
||||
// 客户端链接真实服务成功 设置自动读写false 等待访客连接成功后设置成true
|
||||
Channel realChannel = future.channel();
|
||||
realChannel.config().setOption(ChannelOption.AUTO_READ, false);
|
||||
|
||||
log.info("访客通过 客户端:【{}】,绑定本地服务,IP:{},端口:{} 新建通道成功", clientId, clientTargetIp, clientTargetPort);
|
||||
// 客户端真实通道
|
||||
NettyRealIdContext.pushReal(realChannel, visitorId);
|
||||
// 绑定访客ID到当前真实通道属性
|
||||
ChannelAttributeKeyUtils.buildVisitorId(realChannel, visitorId);
|
||||
ChannelAttributeKeyUtils.buildClientId(realChannel, clientId);
|
||||
ChannelAttributeKeyUtils.buildVisitorPort(realChannel, visitorPort);
|
||||
// 通知服务端访客连接成功
|
||||
|
||||
|
||||
// 新建一个通道处理
|
||||
newVisitorConnect2Server(internalNetworkPenetrationRealClient, nettyClientProperties, handleChannelTypeAdvancedList);
|
||||
|
||||
// 是否等 服务端相应访客通道已经可以自动读写
|
||||
// realChannel.config().setOption(ChannelOption.AUTO_READ, true);
|
||||
// 模拟发送
|
||||
String byteData = "GET /swagger-ui/index.html HTTP/1.1\n" +
|
||||
"Host: 127.0.0.1:19080\n" +
|
||||
"Connection: keep-alive\n" +
|
||||
"Cache-Control: max-age=0\n" +
|
||||
"sec-ch-ua: \"Not_A Brand\";v=\"8\", \"Chromium\";v=\"120\", \"Google Chrome\";v=\"120\"\n" +
|
||||
"sec-ch-ua-mobile: ?0\n" +
|
||||
"sec-ch-ua-platform: \"macOS\"\n" +
|
||||
"Upgrade-Insecure-Requests: 1\n" +
|
||||
"User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36\n" +
|
||||
"Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7\n" +
|
||||
"Sec-Fetch-Site: none\n" +
|
||||
"Sec-Fetch-Mode: navigate\n" +
|
||||
"Sec-Fetch-User: ?1\n" +
|
||||
"Sec-Fetch-Dest: document\n" +
|
||||
"Accept-Encoding: gzip, deflate, br\n" +
|
||||
"Accept-Language: zh-CN,zh;q=0.9\n" +
|
||||
"Cookie: XXL_JOB_LOGIN_IDENTITY=7b226964223a312c22757365726e616d65223a2261646d696e222c2270617373776f7264223a226531306164633339343962613539616262653536653035376632306638383365222c22726f6c65223a312c227065726d697373696f6e223a6e756c6c7d; Hm_lvt_173e771eef816c412396d2cb4fe2d632=1703040917\n";
|
||||
// ChannelContext.ClientChannel clientChannel = ChannelContext.get(String.valueOf(visitorPort).getBytes(StandardCharsets.UTF_8));
|
||||
// Channel channel = clientChannel.getChannel();
|
||||
// channel.writeAndFlush(byteData.getBytes(StandardCharsets.UTF_8));
|
||||
// future.channel().attr(Constant.VID).set(internalNetworkPenetrationRealClient);
|
||||
// Constant.vrc.put(internalNetworkPenetrationRealClient, future.channel());
|
||||
// ProxySocket.connectProxyServer(internalNetworkPenetrationRealClient);
|
||||
} else {
|
||||
log.error("客户:【{}】,无法连接当前网络内的目标IP:【{}】,目标端口:【{}】", clientId, clientTargetIp, clientTargetPort);
|
||||
}
|
||||
});
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 创建访客连接服务端
|
||||
*
|
||||
* @param internalNetworkPenetrationRealClient 内网穿透信息
|
||||
* @param nettyClientProperties 服务端配置信息
|
||||
* @param handleChannelTypeAdvancedList 处理器适配器
|
||||
* @throws InterruptedException 异常
|
||||
*/
|
||||
protected static void newVisitorConnect2Server(InternalNetworkPenetrationRealClient internalNetworkPenetrationRealClient,
|
||||
NettyClientProperties nettyClientProperties,
|
||||
List<HandleChannelTypeAdvanced> handleChannelTypeAdvancedList) throws InterruptedException {
|
||||
Bootstrap bootstrap = new Bootstrap();
|
||||
bootstrap.group(eventLoopGroup)
|
||||
.channel(NioSocketChannel.class)
|
||||
.handler(new NettyClientVisitorRealFilter(new ChannelTypeAdapter(handleChannelTypeAdvancedList)))
|
||||
;
|
||||
|
||||
String inetHost = nettyClientProperties.getInetHost();
|
||||
int inetPort = nettyClientProperties.getInetPort();
|
||||
// local client id
|
||||
|
||||
String clientId = nettyClientProperties.getClientId();
|
||||
|
||||
|
||||
String visitorId = internalNetworkPenetrationRealClient.getVisitorId();
|
||||
Integer visitorPort = internalNetworkPenetrationRealClient.getVisitorPort();
|
||||
String clientTargetIp = internalNetworkPenetrationRealClient.getClientTargetIp();
|
||||
Integer clientTargetPort = internalNetworkPenetrationRealClient.getClientTargetPort();
|
||||
String visitorClientId = internalNetworkPenetrationRealClient.getClientId();
|
||||
|
||||
// 客户端新建访客通道 连接服务端IP:{},连接服务端端口:{}
|
||||
log.info("Client creates a new visitor channel to connect to server IP: {}, connecting to server port: {}", inetHost, inetPort);
|
||||
ChannelFuture future = bootstrap.connect(inetHost, inetPort);
|
||||
|
||||
// 使用的客户端ID:{}
|
||||
log.info("Client ID used: {}" , visitorClientId);
|
||||
future.addListener((ChannelFutureListener) futureListener -> {
|
||||
Channel channel = futureListener.channel();
|
||||
if (futureListener.isSuccess()) {
|
||||
|
||||
NettyProxyMsg myMsg = new NettyProxyMsg();
|
||||
myMsg.setType(MessageType.REPORT_SINGLE_CLIENT_REAL_CONNECT);
|
||||
myMsg.setClientId(visitorClientId);
|
||||
myMsg.setVisitorPort(visitorPort);
|
||||
myMsg.setClientTargetIp(clientTargetIp);
|
||||
myMsg.setClientTargetPort(clientTargetPort);
|
||||
|
||||
myMsg.setVisitorId(visitorId);
|
||||
channel.writeAndFlush(myMsg);
|
||||
// 绑定客户端真实通信通道
|
||||
NettyCommunicationIdContext.pushVisitor(channel, visitorId);
|
||||
ChannelAttributeKeyUtils.buildVisitorId(channel, visitorId);
|
||||
ChannelAttributeKeyUtils.buildClientId(channel, visitorClientId);
|
||||
// 客户端真实通道自动读写打开
|
||||
Channel visitor = NettyRealIdContext.getReal(visitorId);
|
||||
visitor.config().setOption(ChannelOption.AUTO_READ, true);
|
||||
|
||||
|
||||
} else {
|
||||
log.info("每隔2s重连....");
|
||||
// 离线
|
||||
channel.eventLoop().schedule(() -> {
|
||||
try {
|
||||
newVisitorConnect2Server(internalNetworkPenetrationRealClient, nettyClientProperties, handleChannelTypeAdvancedList);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}, 2, TimeUnit.SECONDS);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@ -0,0 +1,122 @@
|
||||
package org.framework.smart.agent.network.heartbeat.client.netty.socket;
|
||||
|
||||
|
||||
import io.netty.bootstrap.Bootstrap;
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelFuture;
|
||||
import io.netty.channel.ChannelFutureListener;
|
||||
import io.netty.channel.EventLoopGroup;
|
||||
import io.netty.channel.nio.NioEventLoopGroup;
|
||||
import io.netty.channel.socket.nio.NioSocketChannel;
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.framework.smart.agent.network.heartbeat.client.netty.event.ClientChangeEvent;
|
||||
import org.framework.smart.agent.network.heartbeat.client.netty.filter.NettyClientFilter;
|
||||
import org.framework.smart.agent.network.heartbeat.common.MessageType;
|
||||
import org.framework.smart.agent.network.heartbeat.common.NettyProxyMsg;
|
||||
import org.framework.smart.agent.network.heartbeat.common.NettyServerContext;
|
||||
import org.framework.smart.agent.network.heartbeat.common.adapter.ChannelTypeAdapter;
|
||||
import org.framework.smart.agent.network.heartbeat.common.advanced.HandleChannelTypeAdvanced;
|
||||
import org.framework.smart.agent.network.heartbeat.common.utils.ChannelAttributeKeyUtils;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* 客户端连接服务端
|
||||
*/
|
||||
@Slf4j
|
||||
public class NettyClientSocket {
|
||||
private final EventLoopGroup eventLoopGroup = new NioEventLoopGroup();
|
||||
/**
|
||||
* 服务端host
|
||||
*/
|
||||
private final String inetHost;
|
||||
/**
|
||||
* 服务端端口
|
||||
*/
|
||||
private final int inetPort;
|
||||
/**
|
||||
* 当前客户端id
|
||||
*/
|
||||
@Getter
|
||||
private final String clientId;
|
||||
|
||||
/**
|
||||
* 当前连接的服务端ID
|
||||
*/
|
||||
private final String serverId;
|
||||
/**
|
||||
* 客户端状态变更事件
|
||||
*/
|
||||
@Getter
|
||||
private final ClientChangeEvent clientChangeEvent;
|
||||
private final List<HandleChannelTypeAdvanced> handleChannelTypeAdvancedList; // 处理服务端发送过来的数据类型
|
||||
|
||||
public NettyClientSocket(String inetHost, int inetPort, String clientId, String serverId, ClientChangeEvent clientChangeEvent, List<HandleChannelTypeAdvanced> handleChannelTypeAdvancedList) {
|
||||
this.inetHost = inetHost;
|
||||
this.inetPort = inetPort;
|
||||
this.clientId = clientId;
|
||||
this.serverId = serverId;
|
||||
this.clientChangeEvent = clientChangeEvent;
|
||||
this.handleChannelTypeAdvancedList = handleChannelTypeAdvancedList;
|
||||
}
|
||||
|
||||
public void newConnect2Server() throws InterruptedException {
|
||||
newConnect2Server(inetHost, inetPort, clientId, serverId, clientChangeEvent);
|
||||
}
|
||||
|
||||
protected void newConnect2Server(String inetHost, int inetPort, String clientId, String serverId, ClientChangeEvent clientChangeEvent) throws InterruptedException {
|
||||
Bootstrap bootstrap = new Bootstrap();
|
||||
bootstrap.group(eventLoopGroup)
|
||||
.channel(NioSocketChannel.class)
|
||||
.handler(new NettyClientFilter(new ChannelTypeAdapter(handleChannelTypeAdvancedList), this))
|
||||
;
|
||||
|
||||
log.info("use clientId:{} connect to server IP:{},server port :{}", clientId, inetHost, inetPort);
|
||||
ChannelFuture future = bootstrap.connect(inetHost, inetPort);
|
||||
// 客户端连接服务端的channel
|
||||
Channel serviceChannel = future.channel();
|
||||
|
||||
future.addListener((ChannelFutureListener) futureListener -> {
|
||||
if (futureListener.isSuccess()) {
|
||||
|
||||
log.info("clientId:{},connect to server IP:{},server port :{} isSuccess ", clientId, inetHost, inetPort);
|
||||
// 告诉服务端这条连接是client的连接
|
||||
NettyProxyMsg nettyMsg = new NettyProxyMsg();
|
||||
nettyMsg.setType(MessageType.REPORT_CLIENT_CONNECT_SUCCESS);
|
||||
nettyMsg.setClientId(clientId);
|
||||
nettyMsg.setData((clientId).getBytes());
|
||||
ChannelAttributeKeyUtils.buildClientId(serviceChannel, clientId);
|
||||
serviceChannel.writeAndFlush(nettyMsg);
|
||||
|
||||
NettyServerContext.pushServerEndpointChannel(serverId, clientId, serviceChannel);
|
||||
// 在线 客户端注册服务端成功
|
||||
clientChangeEvent.clientOnLine(inetHost, inetPort,serverId, clientId);
|
||||
} else {
|
||||
log.warn("Reconnect every 2 seconds....");
|
||||
// 离线
|
||||
NettyServerContext.removeServerEndpointChannels(serverId, clientId);
|
||||
clientChangeEvent.clientOffLine(inetHost, inetPort,serverId, clientId);
|
||||
futureListener.channel().eventLoop().schedule(() -> {
|
||||
try {
|
||||
newConnect2Server(inetHost, inetPort, clientId, serverId, clientChangeEvent);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}, 2, TimeUnit.SECONDS);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭连接
|
||||
*/
|
||||
|
||||
public void shutdown() {
|
||||
if ((eventLoopGroup != null) && (!eventLoopGroup.isShutdown())) {
|
||||
eventLoopGroup.shutdownGracefully();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,65 @@
|
||||
//package org.framework.smart.agent.network.heartbeat.client.rpc;
|
||||
//
|
||||
//import org.wu.framework.database.lazy.web.plus.stereotype.LazyRpc;
|
||||
//import org.wu.framework.web.response.Result;
|
||||
//import org.wu.framework.web.response.ResultFactory;
|
||||
//import io.netty.channel.Channel;
|
||||
//import org.framework.smart.agent.network.heartbeat.common.ChannelContext;
|
||||
//import org.framework.smart.agent.network.heartbeat.common.MessageType;
|
||||
//import org.framework.smart.agent.network.heartbeat.common.NettyProxyMsg;
|
||||
//
|
||||
//import java.nio.charset.StandardCharsets;
|
||||
//import java.util.List;
|
||||
//
|
||||
//@LazyRpc
|
||||
//public class StagingNoticeApiRpc {
|
||||
//
|
||||
//
|
||||
// /**
|
||||
// * 前提当前客户端曾经有过离线、而后上线了,但是呢现在有暂存的数据,因此暂存是打开的,所以这个时候可以通知服务端让其告知其他客户户我暂存了
|
||||
// * 通知自己暂存了
|
||||
// *
|
||||
// * @param clientId 租户ID
|
||||
// * @return
|
||||
// */
|
||||
// public Result<Void> stagingOpened(String clientId) {
|
||||
// List<ChannelContext.ClientChannel> clientChannels = ChannelContext.get();
|
||||
// for (ChannelContext.ClientChannel clientChannel : clientChannels) {
|
||||
// // 上报 当前通道暂存开启了
|
||||
// Channel channel = clientChannel.getChannel();
|
||||
//
|
||||
// NettyProxyMsg nettyMsg = new NettyProxyMsg();
|
||||
// nettyMsg.setType(MessageType.REPORT_CLIENT_STAGING_OPENED);
|
||||
// nettyMsg.setData((clientId
|
||||
// .getBytes(StandardCharsets.UTF_8)));
|
||||
// nettyMsg.setClientId((clientId
|
||||
// .getBytes(StandardCharsets.UTF_8)));
|
||||
// channel.writeAndFlush(nettyMsg);
|
||||
// }
|
||||
//
|
||||
// return ResultFactory.successOf();
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 暂存恢复
|
||||
// *
|
||||
// * @param clientId 租户ID
|
||||
// * @return
|
||||
// */
|
||||
// public Result<Void> stagingClosed(String clientId) {
|
||||
// List<ChannelContext.ClientChannel> clientChannels = ChannelContext.get();
|
||||
// for (ChannelContext.ClientChannel clientChannel : clientChannels) {
|
||||
// // 上报 当前通道暂存关闭了
|
||||
// Channel channel = clientChannel.getChannel();
|
||||
// NettyProxyMsg nettyMsg = new NettyProxyMsg();
|
||||
// nettyMsg.setType(MessageType.REPORT_CLIENT_STAGING_CLOSED);
|
||||
// nettyMsg.setData((clientId
|
||||
// .getBytes(StandardCharsets.UTF_8)));
|
||||
// nettyMsg.setClientId((clientId
|
||||
// .getBytes(StandardCharsets.UTF_8)));
|
||||
// channel.writeAndFlush(nettyMsg);
|
||||
// }
|
||||
//
|
||||
// return ResultFactory.successOf();
|
||||
// }
|
||||
//}
|
@ -0,0 +1,65 @@
|
||||
package org.framework.smart.agent.network.heartbeat.client.ui;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.wu.framework.web.ui.LazyUI;
|
||||
|
||||
/**
|
||||
* netty 客户端本地UI
|
||||
*/
|
||||
@Configuration
|
||||
public class NettyClientLocalLazyUI implements LazyUI {
|
||||
public static final String UI_URL = "/netty-client-local-ui/**";
|
||||
public static final String UI_URL_INDEX = "/netty-client-local-ui/index.html";
|
||||
public static final String CLASSPATH = "classpath:/netty-client-local-ui/v1/";
|
||||
|
||||
/**
|
||||
* 是否支持 default false
|
||||
* <p>
|
||||
* pathPatterns 格式 /acw-client-ui/**
|
||||
* locations 格式 classpath:/acw-local-client/v1/
|
||||
* </p>
|
||||
*
|
||||
* @return true、false
|
||||
*/
|
||||
@Override
|
||||
public boolean support() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return UI 描述
|
||||
*/
|
||||
@Override
|
||||
public String desc() {
|
||||
return "Netty 本地客户端 UI";
|
||||
}
|
||||
|
||||
/**
|
||||
* @return UI 访问的path
|
||||
* 例如:/acw-client-ui/**
|
||||
*/
|
||||
@Override
|
||||
public String pathPatterns() {
|
||||
return UI_URL;
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回页面首页地址
|
||||
*
|
||||
* @return String
|
||||
* 例如 /acw-client-ui/index.html
|
||||
*/
|
||||
@Override
|
||||
public String index() {
|
||||
return UI_URL_INDEX;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return 文件资源
|
||||
* 例如:classpath:/acw-local-client/v1/
|
||||
*/
|
||||
@Override
|
||||
public String locations() {
|
||||
return CLASSPATH;
|
||||
}
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
# Auto Configure
|
||||
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
|
||||
org.framework.smart.agent.network.heartbeat.client.EnableHeartbeatClientAutoConfiguration,\
|
||||
org.framework.smart.agent.network.heartbeat.client.config.NettyClientProperties,\
|
||||
org.framework.smart.agent.network.heartbeat.client.config.InitConfig,\
|
||||
org.framework.smart.agent.network.heartbeat.client.config.HeartbeatClientConfiguration
|
@ -0,0 +1,4 @@
|
||||
org.framework.smart.agent.network.heartbeat.client.EnableHeartbeatClientAutoConfiguration
|
||||
org.framework.smart.agent.network.heartbeat.client.config.NettyClientProperties
|
||||
org.framework.smart.agent.network.heartbeat.client.config.InitConfig
|
||||
org.framework.smart.agent.network.heartbeat.client.config.HeartbeatClientConfiguration
|
After Width: | Height: | Size: 4.2 KiB |
@ -0,0 +1,14 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<link rel="icon" href="./favicon.ico">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Java 使用 Lazy ORM 网络穿透客户端!</title>
|
||||
<script type="module" crossorigin src="assets/index-BTaJShFE.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="./assets/index-C9GutiFy.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
</body>
|
||||
</html>
|
30
wu-smart-agent-network-heartbeat-common/pom.xml
Normal file
@ -0,0 +1,30 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>top.wu2020</groupId>
|
||||
<artifactId>wu-smart-agent-network</artifactId>
|
||||
<version>1.2.6-JDK17-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>wu-smart-agent-network-heartbeat-common</artifactId>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>netty-all</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>top.wu2020</groupId>
|
||||
<artifactId>wu-framework-web</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
@ -0,0 +1,199 @@
|
||||
package org.framework.smart.agent.network.heartbeat.common;
|
||||
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelId;
|
||||
import lombok.Data;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* 通道上下文
|
||||
*/
|
||||
@Slf4j
|
||||
public class ChannelContext {
|
||||
|
||||
private final static ConcurrentHashMap<String/*clientId*/, ClientChannelImpl/*通道*/>
|
||||
channelIdClientChannelDTOConcurrentHashMap = new ConcurrentHashMap<>();
|
||||
|
||||
/**
|
||||
* 新增通道
|
||||
*
|
||||
* @param channel 通道
|
||||
* @param clientId 客户端ID
|
||||
*/
|
||||
public static void push(Channel channel, String clientId) {
|
||||
|
||||
ChannelId channelId = channel.id();
|
||||
ClientChannelImpl clientChannelImpl = new ClientChannelImpl();
|
||||
clientChannelImpl.setChannelId(channelId);
|
||||
clientChannelImpl.setChannel(channel);
|
||||
clientChannelImpl.setClientId(clientId.getBytes(StandardCharsets.UTF_8));
|
||||
// 如果客户端已经存在 移除
|
||||
if (channelIdClientChannelDTOConcurrentHashMap.containsKey(clientId)) {
|
||||
// clear(clientId);
|
||||
}
|
||||
channelIdClientChannelDTOConcurrentHashMap.put(clientId, clientChannelImpl);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增通道
|
||||
*
|
||||
* @param channel 通道
|
||||
* @param clientId 客户端ID
|
||||
*/
|
||||
public static void push(Channel channel, byte[] clientId) {
|
||||
|
||||
ChannelId channelId = channel.id();
|
||||
ClientChannelImpl clientChannelImpl = new ClientChannelImpl();
|
||||
clientChannelImpl.setChannelId(channelId);
|
||||
clientChannelImpl.setChannel(channel);
|
||||
clientChannelImpl.setClientId(clientId);
|
||||
channelIdClientChannelDTOConcurrentHashMap.put(new String(clientId), clientChannelImpl);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有通道
|
||||
*
|
||||
* @return 返回所有通道信息
|
||||
*/
|
||||
public static List<ClientChannel> get() {
|
||||
return new ArrayList<>(channelIdClientChannelDTOConcurrentHashMap.values());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 根据通道ID获取通道信息
|
||||
*
|
||||
* @param clientId 客户端ID
|
||||
* @return 通道信息
|
||||
*/
|
||||
public static ClientChannel get(byte[] clientId) {
|
||||
if (channelIdClientChannelDTOConcurrentHashMap
|
||||
.containsKey(new String(clientId))) {
|
||||
return channelIdClientChannelDTOConcurrentHashMap
|
||||
.get(new String(clientId));
|
||||
} else {
|
||||
// 无法通过客户端ID[{}]获取通道信息
|
||||
log.error("Unable to obtain channel information through client ID [{}]",new String(clientId));
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据通道ID获取通道信息
|
||||
*
|
||||
* @param clientId 客户端ID
|
||||
* @return 通道信息
|
||||
*/
|
||||
public static ChannelContext.ClientChannel get(String clientId) {
|
||||
return get(clientId.getBytes(StandardCharsets.UTF_8));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 关闭通道
|
||||
*
|
||||
* @param clientId 客户端ID
|
||||
*/
|
||||
public static void clear(String clientId) {
|
||||
ClientChannel clientChannel = get(clientId);
|
||||
if (clientChannel != null) {
|
||||
remove(clientId);
|
||||
Channel channel = clientChannel.getChannel();
|
||||
if (channel != null && channel.isActive()) {
|
||||
channel.close();
|
||||
}
|
||||
} else {
|
||||
// log warm
|
||||
// 无法通过客户ID:[{}]移除客户端
|
||||
log.warn("Unable to remove client through customer ID: [{}]", clientId);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过客户端ID移除客户端通道
|
||||
*
|
||||
* @param clientId 客户端ID
|
||||
*/
|
||||
public static void remove(byte[] clientId) {
|
||||
ClientChannel clientChannel = get(clientId);
|
||||
if (clientChannel != null) {
|
||||
channelIdClientChannelDTOConcurrentHashMap.remove(new String(clientId));
|
||||
} else {
|
||||
// log warm 无法通过客户ID:[{}]移除客户端
|
||||
log.warn("Unable to remove client through customer ID: [{}]", new String(clientId));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过客户端ID移除客户端通道
|
||||
*
|
||||
* @param clientId 客户端ID
|
||||
*/
|
||||
public static void remove(String clientId) {
|
||||
ClientChannel clientChannel = get(clientId);
|
||||
if (clientChannel != null) {
|
||||
channelIdClientChannelDTOConcurrentHashMap.remove(clientId);
|
||||
} else {
|
||||
// log warm 无法通过客户ID:[{}]移除客户端
|
||||
log.warn("Unable to remove client through customer ID: [{}]", clientId);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 客户端通道信息
|
||||
*/
|
||||
public interface ClientChannel {
|
||||
|
||||
/**
|
||||
* 客户端ID
|
||||
*/
|
||||
byte[] getClientId();
|
||||
|
||||
/**
|
||||
* 通道ID
|
||||
*/
|
||||
ChannelId getChannelId();
|
||||
|
||||
/**
|
||||
* 通道
|
||||
*/
|
||||
Channel getChannel();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 客户端通道信息
|
||||
*/
|
||||
@Data
|
||||
class ClientChannelImpl implements ChannelContext.ClientChannel {
|
||||
/**
|
||||
* 客户端ID
|
||||
*/
|
||||
private byte[] clientId;
|
||||
/**
|
||||
* 通道ID
|
||||
*/
|
||||
private ChannelId channelId;
|
||||
/**
|
||||
* 通道
|
||||
*/
|
||||
private Channel channel;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ClientChannelImpl{" +
|
||||
"clientId=" + new String(clientId) +
|
||||
", channelId=" + channelId.asLongText() +
|
||||
'}';
|
||||
}
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
package org.framework.smart.agent.network.heartbeat.common;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* describe 内网穿透映射 真实客户端
|
||||
*
|
||||
* @author Jia wei Wu
|
||||
* @date 2023/12/29 05:21 下午
|
||||
**/
|
||||
@Builder
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class InternalNetworkPenetrationRealClient {
|
||||
|
||||
|
||||
/**
|
||||
* 客户端ID
|
||||
*/
|
||||
private String clientId;
|
||||
|
||||
/**
|
||||
* 客户端目标地址
|
||||
*/
|
||||
private String clientTargetIp;
|
||||
|
||||
/**
|
||||
* 客户端目标端口
|
||||
*/
|
||||
private Integer clientTargetPort;
|
||||
|
||||
|
||||
/**
|
||||
* 访问端口
|
||||
*/
|
||||
private Integer visitorPort;
|
||||
/**
|
||||
* 访客ID
|
||||
*/
|
||||
private String visitorId;
|
||||
}
|
@ -0,0 +1,182 @@
|
||||
package org.framework.smart.agent.network.heartbeat.common;
|
||||
|
||||
import org.framework.smart.agent.network.heartbeat.common.advanced.AbstractHandleChannelHeartbeatTypeAdvanced;
|
||||
import org.framework.smart.agent.network.heartbeat.common.advanced.client.*;
|
||||
import org.framework.smart.agent.network.heartbeat.common.advanced.server.*;
|
||||
import org.framework.smart.agent.network.heartbeat.common.enums.MessageTypeEnums;
|
||||
|
||||
/**
|
||||
* @see MessageTypeEnums
|
||||
* 数据取值范围 -128~ 127
|
||||
* 当前约束范围 -100~100
|
||||
*/
|
||||
public class MessageType {
|
||||
/**
|
||||
* 心跳
|
||||
*
|
||||
* @see MessageTypeEnums#TYPE_HEARTBEAT
|
||||
* @see AbstractHandleChannelHeartbeatTypeAdvanced
|
||||
*/
|
||||
public static final byte TYPE_HEARTBEAT = 0X00;
|
||||
|
||||
/**
|
||||
* 客户端上报连接成功
|
||||
*
|
||||
* @see MessageTypeEnums#REPORT_CLIENT_CONNECT_SUCCESS
|
||||
* @see AbstractHandleClientConnectSuccessTypeAdvanced
|
||||
*/
|
||||
public static final byte REPORT_CLIENT_CONNECT_SUCCESS = 0X01;
|
||||
/**
|
||||
* 上报 客户端断开连接
|
||||
*
|
||||
* @see MessageTypeEnums#REPORT_CLIENT_DISCONNECTION
|
||||
* @see AbstractHandleReportDisconnectTypeAdvanced
|
||||
*/
|
||||
public static final byte REPORT_CLIENT_DISCONNECTION = 0X02;
|
||||
/**
|
||||
* 客户端上报暂存开启
|
||||
*
|
||||
* @see MessageTypeEnums#REPORT_CLIENT_STAGING_OPENED
|
||||
* @see AbstractHandleReportStagingOpenedTypeAdvanced
|
||||
*/
|
||||
public static final byte REPORT_CLIENT_STAGING_OPENED = 0X03;
|
||||
/**
|
||||
* 客户端上报暂存关闭
|
||||
*
|
||||
* @see MessageTypeEnums#REPORT_CLIENT_STAGING_CLOSED
|
||||
* @see AbstractHandleReportStagingClosedTypeAdvanced
|
||||
*/
|
||||
public static final byte REPORT_CLIENT_STAGING_CLOSED = 0X04;
|
||||
|
||||
/**
|
||||
* 上报 客户端数据传输(内网穿透数据回传)
|
||||
*
|
||||
* @see MessageTypeEnums#REPORT_CLIENT_TRANSFER
|
||||
* @see AbstractHandleReportHandleChannelTransferTypeAdvanced
|
||||
*/
|
||||
public static final byte REPORT_CLIENT_TRANSFER = 0X05;
|
||||
|
||||
|
||||
/**
|
||||
* 上报 客户端创建需要代理的真实端口成功
|
||||
*
|
||||
* @see MessageTypeEnums#REPORT_SINGLE_CLIENT_REAL_CONNECT
|
||||
* @see AbstractHandleReportSingleClientRealConnectTypeAdvanced
|
||||
*/
|
||||
public static final byte REPORT_SINGLE_CLIENT_REAL_CONNECT = 0X06;
|
||||
/**
|
||||
* 上报 客户端关闭一个访客通道
|
||||
*
|
||||
* @see MessageTypeEnums#REPORT_SINGLE_CLIENT_CLOSE_VISITOR
|
||||
* @see AbstractHandleReportSingleClientCloseVisitorTypeAdvanced
|
||||
*/
|
||||
public static final byte REPORT_SINGLE_CLIENT_CLOSE_VISITOR = 0X08;
|
||||
|
||||
/**
|
||||
* 上报 客户端消息到另一个客户端
|
||||
*
|
||||
* @see MessageTypeEnums#REPORT_SINGLE_CLIENT_MESSAGE
|
||||
* @see AbstractHandleReportSingleClientMessage2OtherClientTypeAdvanced
|
||||
*/
|
||||
public static final byte REPORT_SINGLE_CLIENT_MESSAGE = 0X09;
|
||||
/**
|
||||
* 服务端通道 is active
|
||||
*
|
||||
* @see MessageTypeEnums#SERVER_CHANNEL_ACTIVE
|
||||
* @see AbstractHandleServerChannelActiveTypeAdvanced
|
||||
*/
|
||||
public static final byte SERVER_CHANNEL_ACTIVE = 0X10;
|
||||
|
||||
/**
|
||||
* 上报 集群注册
|
||||
*
|
||||
* @see MessageTypeEnums#REPORT_CLUSTER_NODE_REGISTER_MESSAGE
|
||||
* @see AbstractHandleReportClusterNodeRegisterTypeAdvanced
|
||||
*/
|
||||
public static final byte REPORT_CLUSTER_NODE_REGISTER_MESSAGE = 0X11;
|
||||
|
||||
/**
|
||||
* 下发 客户端接收连接成功通知
|
||||
*
|
||||
* @see MessageTypeEnums#DISTRIBUTE_CLIENT_CONNECTION_SUCCESS_NOTIFICATION
|
||||
* @see AbstractHandleDistributeConnectSuccessNotificationTypeAdvancedHandle
|
||||
*/
|
||||
public static final byte DISTRIBUTE_CLIENT_CONNECTION_SUCCESS_NOTIFICATION = -0X01;
|
||||
/**
|
||||
* 下发 客户端断开连接通知
|
||||
*
|
||||
* @see MessageTypeEnums#DISTRIBUTE_CLIENT_DISCONNECTION_NOTIFICATION
|
||||
* @see AbstractHandleDistributeDisconnectTypeAdvancedHandle
|
||||
*/
|
||||
public static final byte DISTRIBUTE_CLIENT_DISCONNECTION_NOTIFICATION = -0X02;
|
||||
/**
|
||||
* 下发 客户端暂存开启通知
|
||||
*
|
||||
* @see MessageTypeEnums#DISTRIBUTE_CLIENT_STAGING_OPENED_NOTIFICATION
|
||||
* @see AbstractHandleDistributeStagingOpenedTypeAdvanced
|
||||
*/
|
||||
public static final byte DISTRIBUTE_CLIENT_STAGING_OPENED_NOTIFICATION = -0X03;
|
||||
|
||||
/**
|
||||
* 下发 客户端暂存关闭通知
|
||||
*
|
||||
* @see MessageTypeEnums#DISTRIBUTE_CLIENT_STAGING_CLOSED_NOTIFICATION
|
||||
* @see AbstractHandleDistributeStagingClosedTypeAdvanced
|
||||
*/
|
||||
public static final byte DISTRIBUTE_CLIENT_STAGING_CLOSED_NOTIFICATION = -0X04;
|
||||
/**
|
||||
* 下发 客户端数据传输(内网穿透数据发送)
|
||||
*
|
||||
* @see MessageTypeEnums#DISTRIBUTE_CLIENT_TRANSFER
|
||||
* @see AbstractHandleDistributeChannelTransferTypeAdvanced
|
||||
*/
|
||||
public static final byte DISTRIBUTE_CLIENT_TRANSFER = -0X05;
|
||||
/**
|
||||
* 下发 客户端创建需要代理的真实端口
|
||||
*
|
||||
* @see MessageTypeEnums#DISTRIBUTE_SINGLE_CLIENT_REAL_CONNECT
|
||||
* @see AbstractHandleDistributeSingleClientRealConnectTypeAdvanced
|
||||
*/
|
||||
public static final byte DISTRIBUTE_SINGLE_CLIENT_REAL_CONNECT = -0X06;
|
||||
|
||||
/**
|
||||
* 下发 客户端代理的真实端口自动读写
|
||||
*
|
||||
* @see MessageTypeEnums#DISTRIBUTE_SINGLE_CLIENT_REAL_CONNECT_AUTO_READ
|
||||
* @see AbstractHandleDistributeSingleClientRealAutoReadConnectTypeAdvanced
|
||||
*/
|
||||
public static final byte DISTRIBUTE_SINGLE_CLIENT_REAL_CONNECT_AUTO_READ = -0X07;
|
||||
|
||||
/**
|
||||
* 下发 客户端关闭代理服务通道
|
||||
*
|
||||
* @see MessageTypeEnums#DISTRIBUTE_SINGLE_CLIENT_REAL_CLOSE_VISITOR
|
||||
* @see AbstractHandleDistributeSingleClientRealCloseVisitorTypeAdvanced
|
||||
*/
|
||||
public static final byte DISTRIBUTE_SINGLE_CLIENT_REAL_CLOSE_VISITOR = -0X08;
|
||||
|
||||
/**
|
||||
* 下发 客户端消息
|
||||
*
|
||||
* @see MessageTypeEnums#DISTRIBUTE_SINGLE_CLIENT_MESSAGE
|
||||
* @see AbstractHandleDistributeSingleClientMessageTypeAdvanced
|
||||
*/
|
||||
public static final byte DISTRIBUTE_SINGLE_CLIENT_MESSAGE = -0X09;
|
||||
|
||||
|
||||
/**
|
||||
* 客户端通道 is active
|
||||
*
|
||||
* @see MessageTypeEnums#CLIENT_CHANNEL_ACTIVE
|
||||
* @see AbstractHandleClientChannelActiveAdvanced
|
||||
*/
|
||||
public static final byte CLIENT_CHANNEL_ACTIVE = -0X10;
|
||||
|
||||
/**
|
||||
* 下发 集群注册
|
||||
*
|
||||
* @see MessageTypeEnums#DISTRIBUTE_CLUSTER_NODE_REGISTER_MESSAGE
|
||||
* @see AbstractHandleDistributeClusterNodeRegisterTypeAdvanced
|
||||
*/
|
||||
public static final byte DISTRIBUTE_CLUSTER_NODE_REGISTER_MESSAGE = -0X11;
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
package org.framework.smart.agent.network.heartbeat.common;
|
||||
|
||||
import io.netty.channel.Channel;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 客户端连接服务端 通道
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
@Data
|
||||
public class NettyClientChannel {
|
||||
|
||||
/**
|
||||
* 客户端ID
|
||||
*/
|
||||
private String clientId;
|
||||
/**
|
||||
* 客户端通道
|
||||
*/
|
||||
private Channel channel;
|
||||
/**
|
||||
* 服务端ID
|
||||
*/
|
||||
private String serverId;
|
||||
|
||||
}
|
@ -0,0 +1,73 @@
|
||||
package org.framework.smart.agent.network.heartbeat.common;
|
||||
|
||||
import org.wu.framework.core.utils.ObjectUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* 访客端口对应访客上下文
|
||||
*/
|
||||
public class NettyClientVisitorContext {
|
||||
|
||||
protected static final ConcurrentHashMap<String/*clientId*/, List<Object>/*NettyVisitorSocket*/> VISITOR_SOCKET = new ConcurrentHashMap<>();
|
||||
|
||||
|
||||
/**
|
||||
* 添加访客
|
||||
*
|
||||
* @param clientId 客户端ID
|
||||
* @param visitorSocket 客户端访客socket
|
||||
*/
|
||||
public static <T> void pushVisitorSocket(String clientId, T visitorSocket) {
|
||||
List<Object> visitors = getVisitorSockets(clientId);
|
||||
visitors.add(visitorSocket);
|
||||
VISITOR_SOCKET.put(clientId, visitors);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过客户端ID获取客户端使用的访客socket
|
||||
*
|
||||
* @param <T> 访客范型
|
||||
* @param clientId 客户端ID
|
||||
* @return 访客
|
||||
*/
|
||||
public static <T> List<T> getVisitorSockets(String clientId) {
|
||||
return (List<T>) VISITOR_SOCKET.getOrDefault(clientId, new ArrayList<>());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 移除 客户端 访客信息
|
||||
*
|
||||
* @param clientId 客户端ID
|
||||
*/
|
||||
public static void removeVisitorSockets(String clientId) {
|
||||
VISITOR_SOCKET.remove(clientId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除 客户端 访客信息
|
||||
*
|
||||
* @param clientId 客户端ID
|
||||
* @param visitorSocket 访客socket
|
||||
*/
|
||||
public static <T> void removeVisitorSocket(String clientId, T visitorSocket) {
|
||||
List<Object> visitorSocketList = VISITOR_SOCKET.get(clientId);
|
||||
if(!ObjectUtils.isEmpty(visitorSocketList)){
|
||||
visitorSocketList.remove(visitorSocket);
|
||||
VISITOR_SOCKET.put(clientId,visitorSocketList);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭客户端访客socket
|
||||
*
|
||||
* @param clientId 客户端ID
|
||||
*/
|
||||
public static void close(String clientId) {
|
||||
// getVisitorSockets(clientId)
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,71 @@
|
||||
package org.framework.smart.agent.network.heartbeat.common;
|
||||
|
||||
import io.netty.channel.Channel;
|
||||
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* 通信通道对应上下文
|
||||
*/
|
||||
public class NettyCommunicationIdContext {
|
||||
|
||||
protected static final ConcurrentHashMap<String, Object> COMMUNICATION = new ConcurrentHashMap<>();
|
||||
|
||||
|
||||
/**
|
||||
* 添加访客
|
||||
*
|
||||
* @param visitorId 访客id
|
||||
* @param visitor 访客
|
||||
*/
|
||||
public static <T> void pushVisitor(T visitor, String visitorId) {
|
||||
COMMUNICATION.put(visitorId, visitor);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过访客端口获取访客
|
||||
*
|
||||
* @param visitorId 访客id
|
||||
* @param <T> 访客范型
|
||||
* @return 访客
|
||||
*/
|
||||
public static <T> T getVisitor(String visitorId) {
|
||||
return (T) COMMUNICATION.get(visitorId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过访客端口获取访客
|
||||
*
|
||||
* @param visitorId 访客id
|
||||
* @param <T> 访客范型
|
||||
* @return 访客
|
||||
*/
|
||||
public static <T> T getVisitor(byte[] visitorId) {
|
||||
return getVisitor(new String(visitorId));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除访客
|
||||
*
|
||||
* @param visitorId 访客ID
|
||||
*/
|
||||
public static void clear(String visitorId) {
|
||||
Channel visitor = getVisitor(visitorId);
|
||||
if (visitor != null) {
|
||||
COMMUNICATION.remove(visitorId);
|
||||
visitor.close();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除访客
|
||||
*
|
||||
* @param visitorId 访客ID
|
||||
*/
|
||||
public static void clear(byte[] visitorId) {
|
||||
clear(new String(visitorId));
|
||||
}
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
package org.framework.smart.agent.network.heartbeat.common;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
@Setter
|
||||
@Getter
|
||||
public class NettyMsg {
|
||||
// body 长度 type 1 clientId 4 data 4
|
||||
public static final int bodyLength = 9;
|
||||
|
||||
/**
|
||||
* 数据类型
|
||||
*
|
||||
* @see MessageType
|
||||
* byte长度 1
|
||||
*/
|
||||
private byte type;
|
||||
/**
|
||||
* 客户端ID
|
||||
* byte[] 长度 4
|
||||
*/
|
||||
private byte[] clientId;
|
||||
|
||||
/**
|
||||
* 消息传输数据
|
||||
* byte[] 长度 4
|
||||
*/
|
||||
private byte[] data;
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "NettyProxyMsg [type=" + type + ", data=" + Arrays.toString(data) + ",clientId=" + Arrays.toString(clientId) + "]";
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,113 @@
|
||||
package org.framework.smart.agent.network.heartbeat.common;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
/**
|
||||
* netty 代理请求数据
|
||||
*/
|
||||
@NoArgsConstructor
|
||||
@Setter
|
||||
@Getter
|
||||
public class NettyProxyMsg {
|
||||
// body 长度 type 1 clientId 4 clientTargetIp 4 clientTargetPort 4 visitorPort 4 visitorId 4 data 4
|
||||
public static final int bodyLength = 1 + 4 + 4 + 4 + 4 + 4 + 4;
|
||||
|
||||
|
||||
/**
|
||||
* 数据类型
|
||||
*
|
||||
* @see MessageType
|
||||
* byte长度 1
|
||||
*/
|
||||
private byte type;
|
||||
|
||||
/**
|
||||
* 客户端ID
|
||||
* byte[] 长度 4
|
||||
*/
|
||||
private byte[] clientId;
|
||||
/**
|
||||
* 客户端目标地址
|
||||
* byte[] 长度 4
|
||||
*/
|
||||
private byte[] clientTargetIp;
|
||||
|
||||
/**
|
||||
* 客户端目标端口
|
||||
* byte[] 长度 4
|
||||
*/
|
||||
private byte[] clientTargetPort;
|
||||
/**
|
||||
* 客户端目使用的代理端口
|
||||
* byte[] 长度 4
|
||||
*/
|
||||
private byte[] visitorPort;
|
||||
/**
|
||||
* 访客ID
|
||||
* byte[] 长度 4
|
||||
*/
|
||||
private byte[] visitorId;
|
||||
/**
|
||||
* 消息传输数据
|
||||
* byte[] 长度 4
|
||||
*/
|
||||
private byte[] data;
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "NettyProxyMsg [type=" + type +
|
||||
",clientId=" + (clientId == null ? null : new String(clientId)) +
|
||||
",clientTargetIp=" + (clientTargetIp == null ? null : new String(clientTargetIp)) +
|
||||
",clientTargetPort=" + (clientTargetPort == null ? null : new String(clientTargetPort)) +
|
||||
",visitorPort=" + (visitorPort == null ? null : new String(visitorPort)) +
|
||||
"]";
|
||||
}
|
||||
|
||||
public void setClientId(byte[] clientId) {
|
||||
this.clientId = clientId;
|
||||
}
|
||||
|
||||
public void setClientId(String clientId) {
|
||||
this.clientId = clientId.getBytes(StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
|
||||
public void setClientTargetIp(byte[] clientTargetIp) {
|
||||
this.clientTargetIp = clientTargetIp;
|
||||
}
|
||||
|
||||
public void setClientTargetIp(String clientTargetIp) {
|
||||
this.clientTargetIp = clientTargetIp.getBytes(StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
public void setClientTargetPort(Integer clientTargetPort) {
|
||||
this.clientTargetPort = String.valueOf(clientTargetPort).getBytes(StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
public void setClientTargetPort(byte[] clientTargetPort) {
|
||||
this.clientTargetPort = clientTargetPort;
|
||||
}
|
||||
|
||||
public void setVisitorPort(byte[] visitorPort) {
|
||||
this.visitorPort = visitorPort;
|
||||
}
|
||||
|
||||
public void setVisitorPort(Integer visitorPort) {
|
||||
this.visitorPort = String.valueOf(visitorPort).getBytes(StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
public void setVisitorId(String visitorId) {
|
||||
this.visitorId = visitorId.getBytes(StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
public void setVisitorId(byte[] visitorId) {
|
||||
this.visitorId = visitorId;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,71 @@
|
||||
package org.framework.smart.agent.network.heartbeat.common;
|
||||
|
||||
import io.netty.channel.Channel;
|
||||
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* 真实通道对应上下文 客户端、服务端真实代理通道
|
||||
*/
|
||||
public class NettyRealIdContext {
|
||||
|
||||
protected static final ConcurrentHashMap<String, Object> REAL = new ConcurrentHashMap<>();
|
||||
|
||||
|
||||
/**
|
||||
* 添加真实通道
|
||||
*
|
||||
* @param visitorId 访客id
|
||||
* @param visitor 访客真实通道
|
||||
*/
|
||||
public static <T> void pushReal(T visitor, String visitorId) {
|
||||
REAL.put(visitorId, visitor);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过访客端口获取访客
|
||||
*
|
||||
* @param visitorId 访客id
|
||||
* @param <T> 访客范型
|
||||
* @return 访客
|
||||
*/
|
||||
public static <T> T getReal(String visitorId) {
|
||||
return (T) REAL.get(visitorId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过访客端口获取访客
|
||||
*
|
||||
* @param visitorId 访客id
|
||||
* @param <T> 访客范型
|
||||
* @return 访客
|
||||
*/
|
||||
public static <T> T getReal(byte[] visitorId) {
|
||||
return getReal(new String(visitorId));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除访客
|
||||
*
|
||||
* @param visitorId 访客ID
|
||||
*/
|
||||
public static void clear(String visitorId) {
|
||||
Channel visitor = getReal(visitorId);
|
||||
if (visitor != null) {
|
||||
REAL.remove(visitorId);
|
||||
visitor.close();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除访客
|
||||
*
|
||||
* @param visitorId 访客ID
|
||||
*/
|
||||
public static void clear(byte[] visitorId) {
|
||||
clear(new String(visitorId));
|
||||
}
|
||||
}
|
@ -0,0 +1,109 @@
|
||||
package org.framework.smart.agent.network.heartbeat.common;
|
||||
|
||||
import io.netty.channel.Channel;
|
||||
import org.wu.framework.core.utils.ObjectUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 服务端存储 channel 上下文
|
||||
*/
|
||||
public class NettyServerContext {
|
||||
|
||||
|
||||
protected static final ConcurrentHashMap<String/*serverId*/, List<NettyClientChannel>/*NettyClientChannel*/>
|
||||
NETTY_CLIENT_CHANNEL_SOCKET = new ConcurrentHashMap<>();
|
||||
|
||||
|
||||
/**
|
||||
* 添加访客
|
||||
*
|
||||
* @param serverId 服务端ID
|
||||
* @param clientId 客户端ID
|
||||
* @param channel channel
|
||||
*/
|
||||
public static <T> void pushServerEndpointChannel(String serverId, String clientId, Channel channel) {
|
||||
List<NettyClientChannel> nettyClientChannelList = getServerEndpointChannels(serverId);
|
||||
// 关闭旧的通道
|
||||
nettyClientChannelList.stream().filter(nettyClientChannel -> nettyClientChannel.getClientId().equals(clientId) && nettyClientChannel.getServerId().equals(serverId)).forEach(nettyClientChannel -> {
|
||||
Channel oldChannel = nettyClientChannel.getChannel();
|
||||
if (oldChannel != null && oldChannel.isActive()) {
|
||||
oldChannel.close();
|
||||
}
|
||||
});
|
||||
|
||||
List<NettyClientChannel> activeNettyClientChannelList = nettyClientChannelList
|
||||
.stream()
|
||||
.filter(nettyClientChannel ->
|
||||
!nettyClientChannel.getClientId().equals(clientId) && !nettyClientChannel.getServerId().equals(serverId))
|
||||
.collect(Collectors.toList());
|
||||
NettyClientChannel nettyClientChannel = new NettyClientChannel(clientId, channel, serverId);
|
||||
activeNettyClientChannelList.add(nettyClientChannel);
|
||||
NETTY_CLIENT_CHANNEL_SOCKET.put(serverId, activeNettyClientChannelList);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过客户端ID获取客户端使用的访客socket
|
||||
*
|
||||
* @param serverId 服务端ID
|
||||
* @return 客户端通道
|
||||
*/
|
||||
public static List<NettyClientChannel> getServerEndpointChannels(String serverId) {
|
||||
return NETTY_CLIENT_CHANNEL_SOCKET.getOrDefault(serverId, new ArrayList<>());
|
||||
}
|
||||
/**
|
||||
* 通过客户端ID获取客户端使用的访客socket
|
||||
* @return 客户端通道
|
||||
*/
|
||||
public static List<NettyClientChannel> getServerEndpointChannels() {
|
||||
return NETTY_CLIENT_CHANNEL_SOCKET
|
||||
.values()
|
||||
.stream()
|
||||
.collect(Collectors.flatMapping(Collection::stream,Collectors.toList()));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 移除 客户端通道
|
||||
*
|
||||
* @param serverId 服务端ID
|
||||
*/
|
||||
public static void removeServerEndpointChannels(String serverId) {
|
||||
for (NettyClientChannel nettyClientChannel : getServerEndpointChannels(serverId)) {
|
||||
if (nettyClientChannel.getChannel() != null && nettyClientChannel.getChannel().isActive()) {
|
||||
nettyClientChannel.getChannel().close();
|
||||
}
|
||||
}
|
||||
NETTY_CLIENT_CHANNEL_SOCKET.remove(serverId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除 客户端通道
|
||||
*
|
||||
* @param serverId 服务端ID
|
||||
* @param clientId 客户端ID
|
||||
*/
|
||||
public static <T> void removeServerEndpointChannels(String serverId, String clientId) {
|
||||
List<NettyClientChannel> nettyClientChannelList = NETTY_CLIENT_CHANNEL_SOCKET.get(serverId);
|
||||
if (!ObjectUtils.isEmpty(nettyClientChannelList)) {
|
||||
// 关闭指定服务端对应客户端通道
|
||||
nettyClientChannelList.stream().filter(nettyClientChannel -> nettyClientChannel.getClientId().equals(clientId))
|
||||
.forEach(nettyClientChannel -> {
|
||||
if (nettyClientChannel.getChannel() != null && nettyClientChannel.getChannel().isActive()) {
|
||||
nettyClientChannel.getChannel().close();
|
||||
}
|
||||
});
|
||||
// 过滤后数据
|
||||
List<NettyClientChannel> clientChannelList = nettyClientChannelList.stream().filter(nettyClientChannel -> !nettyClientChannel.getClientId().equals(clientId))
|
||||
.collect(Collectors.toList());
|
||||
NETTY_CLIENT_CHANNEL_SOCKET.put(serverId, clientChannelList);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,72 @@
|
||||
package org.framework.smart.agent.network.heartbeat.common;
|
||||
|
||||
import io.netty.channel.Channel;
|
||||
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* 访客通信通道上下文(服务端、客户端 通信)
|
||||
*/
|
||||
@Deprecated
|
||||
public class NettyVisitorIdContext {
|
||||
|
||||
protected static final ConcurrentHashMap<String, Object> VISITOR_ID = new ConcurrentHashMap<>();
|
||||
|
||||
|
||||
/**
|
||||
* 添加访客
|
||||
*
|
||||
* @param visitorId 访客id
|
||||
* @param visitor 访客
|
||||
*/
|
||||
public static <T> void pushVisitor(T visitor, String visitorId) {
|
||||
VISITOR_ID.put(visitorId, visitor);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过访客端口获取访客
|
||||
*
|
||||
* @param visitorId 访客id
|
||||
* @param <T> 访客范型
|
||||
* @return 访客
|
||||
*/
|
||||
public static <T> T getVisitor(String visitorId) {
|
||||
return (T) VISITOR_ID.get(visitorId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过访客端口获取访客
|
||||
*
|
||||
* @param visitorId 访客id
|
||||
* @param <T> 访客范型
|
||||
* @return 访客
|
||||
*/
|
||||
public static <T> T getVisitor(byte[] visitorId) {
|
||||
return getVisitor(new String(visitorId));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除访客
|
||||
*
|
||||
* @param visitorId 访客ID
|
||||
*/
|
||||
public static void clear(String visitorId) {
|
||||
Channel visitor = getVisitor(visitorId);
|
||||
if (visitor != null) {
|
||||
VISITOR_ID.remove(visitorId);
|
||||
visitor.close();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除访客
|
||||
*
|
||||
* @param visitorId 访客ID
|
||||
*/
|
||||
public static void clear(byte[] visitorId) {
|
||||
clear(new String(visitorId));
|
||||
}
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
package org.framework.smart.agent.network.heartbeat.common;
|
||||
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* 访客端口对应上下文
|
||||
*/
|
||||
public class NettyVisitorPortContext {
|
||||
|
||||
protected static final ConcurrentHashMap<Integer, Object> VISITOR_PORT = new ConcurrentHashMap<>();
|
||||
|
||||
|
||||
/**
|
||||
* 添加访客
|
||||
*
|
||||
* @param visitorPort 访客端口
|
||||
* @param visitor 访客
|
||||
*/
|
||||
public static <T> void pushVisitor(Integer visitorPort, T visitor) {
|
||||
VISITOR_PORT.put(visitorPort, visitor);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过访客端口获取访客
|
||||
*
|
||||
* @param visitorPort 访客端口
|
||||
* @param <T> 访客范型
|
||||
* @return 访客
|
||||
*/
|
||||
public static <T> T getVisitor(Integer visitorPort) {
|
||||
return (T) VISITOR_PORT.get(visitorPort);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除访客
|
||||
* @param visitorPort 访客通道
|
||||
* @return 删除的访客通道
|
||||
* @param <T> 访客通道范型
|
||||
*/
|
||||
public static <T> T removeVisitor(Integer visitorPort){
|
||||
T visitor = getVisitor(visitorPort);
|
||||
if(visitor!=null){
|
||||
VISITOR_PORT.remove(visitorPort);
|
||||
}
|
||||
return visitor;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
package org.framework.smart.agent.network.heartbeat.common.adapter;
|
||||
|
||||
import io.netty.channel.Channel;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.framework.smart.agent.network.heartbeat.common.advanced.flow.ChannelFlow;
|
||||
import org.framework.smart.agent.network.heartbeat.common.advanced.flow.HandleChannelFlowAdvanced;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 通道流量适配器
|
||||
*
|
||||
* @see HandleChannelFlowAdvanced
|
||||
*/
|
||||
@Slf4j
|
||||
public class ChannelFlowAdapter {
|
||||
|
||||
protected final List<HandleChannelFlowAdvanced> handleChannelFlowAdvancedList;
|
||||
|
||||
public ChannelFlowAdapter(List<HandleChannelFlowAdvanced> handleChannelFlowAdvancedList) {
|
||||
this.handleChannelFlowAdvancedList = handleChannelFlowAdvancedList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理当前数据
|
||||
*
|
||||
* @param channelFlow 通道数据
|
||||
*/
|
||||
public void handler(Channel channel, ChannelFlow channelFlow) {
|
||||
for (HandleChannelFlowAdvanced handleChannelTypeAdvanced : handleChannelFlowAdvancedList) {
|
||||
if (handleChannelTypeAdvanced.support(channelFlow)) {
|
||||
try {
|
||||
handleChannelTypeAdvanced.handler(channel, channelFlow);
|
||||
} catch (Exception e) {
|
||||
log.error("流量统计失败:{}", e.getMessage());
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
package org.framework.smart.agent.network.heartbeat.common.adapter;
|
||||
|
||||
import io.netty.channel.Channel;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.framework.smart.agent.network.heartbeat.common.advanced.HandleChannelTypeAdvanced;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 通道类型适配器
|
||||
*/
|
||||
@Slf4j
|
||||
public class ChannelTypeAdapter {
|
||||
protected final List<HandleChannelTypeAdvanced> handleChannelTypeAdvancedList;
|
||||
|
||||
public ChannelTypeAdapter(List<HandleChannelTypeAdvanced> handleChannelTypeAdvancedList) {
|
||||
this.handleChannelTypeAdvancedList = handleChannelTypeAdvancedList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理当前数据
|
||||
*
|
||||
* @param msg 通道数据
|
||||
*/
|
||||
public void handler(Channel channel, Object msg) {
|
||||
// 升序 处理器
|
||||
List<HandleChannelTypeAdvanced> handleChannelTypeAdvancedSortedList =
|
||||
handleChannelTypeAdvancedList.
|
||||
stream().
|
||||
sorted(Comparator.comparing(Ordered::getOrder)).
|
||||
toList();
|
||||
|
||||
|
||||
for (HandleChannelTypeAdvanced handleChannelTypeAdvanced : handleChannelTypeAdvancedSortedList) {
|
||||
if (handleChannelTypeAdvanced.support(msg)) {
|
||||
// log.info("处理器:{},客户端:{}, 处理类型:{}",handleChannelTypeAdvanced.getClass(),new String(msg.getClientId()),msg.getMysqlType());
|
||||
handleChannelTypeAdvanced.handler(channel, msg);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
package org.framework.smart.agent.network.heartbeat.common.advanced;
|
||||
|
||||
|
||||
import org.framework.smart.agent.network.heartbeat.common.NettyProxyMsg;
|
||||
import org.framework.smart.agent.network.heartbeat.common.enums.MessageTypeEnums;
|
||||
|
||||
|
||||
/**
|
||||
* 服务端 处理客户端心跳
|
||||
* TYPE_HEARTBEAT
|
||||
*/
|
||||
|
||||
public abstract class AbstractHandleChannelHeartbeatTypeAdvanced<MSG> extends AbstractHandleChannelTypeAdvanced<NettyProxyMsg> implements HandleChannelTypeAdvanced {
|
||||
|
||||
/**
|
||||
* 是否支持当前类型
|
||||
*
|
||||
* @param msg 通道数据
|
||||
* @return 布尔类型 是、否
|
||||
*/
|
||||
@Override
|
||||
public boolean doSupport(NettyProxyMsg msg) {
|
||||
return MessageTypeEnums.TYPE_HEARTBEAT.getTypeByte() == msg.getType();
|
||||
}
|
||||
}
|
@ -0,0 +1,93 @@
|
||||
package org.framework.smart.agent.network.heartbeat.common.advanced;
|
||||
|
||||
|
||||
import io.netty.channel.Channel;
|
||||
import org.springframework.core.Ordered;
|
||||
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.Objects;
|
||||
|
||||
public abstract class AbstractHandleChannelTypeAdvanced<MSG> implements HandleChannelTypeAdvanced {
|
||||
|
||||
/**
|
||||
* 处理当前数据
|
||||
*
|
||||
* @param channel 当前通道
|
||||
* @param msg 通道数据
|
||||
*/
|
||||
protected abstract void doHandler(Channel channel, MSG msg);
|
||||
|
||||
/**
|
||||
* 处理当前数据
|
||||
*
|
||||
* @param channel 当前通道
|
||||
* @param msg 通道数据
|
||||
*/
|
||||
@Override
|
||||
public void handler(Channel channel, Object msg) {
|
||||
doHandler(channel, (MSG) msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否支持当前类型
|
||||
*
|
||||
* @param msg 通道数据
|
||||
* @return 布尔类型 是、否
|
||||
*/
|
||||
protected abstract boolean doSupport(MSG msg);
|
||||
|
||||
/**
|
||||
* 是否支持当前类型
|
||||
*
|
||||
* @param msg 通道数据
|
||||
* @return 布尔类型 是、否
|
||||
*/
|
||||
@Override
|
||||
public boolean support(Object msg) {
|
||||
if (msg == null) return false;
|
||||
if (!msg.getClass().isAssignableFrom(Objects.requireNonNull(getMsgTypes()))) {
|
||||
return false;
|
||||
}
|
||||
return doSupport((MSG) msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前处理范型
|
||||
*
|
||||
* @return 范型
|
||||
*/
|
||||
private Class<?> getMsgTypes() {
|
||||
|
||||
Type superClassType = this.getClass().getGenericSuperclass();
|
||||
if (superClassType instanceof ParameterizedType parameterizedType) {
|
||||
|
||||
Type[] actualTypes = parameterizedType.getActualTypeArguments();
|
||||
// for (Type type : actualTypes) {
|
||||
// System.out.println("范型类型:" + ((Class<?>) type).getName());
|
||||
// }
|
||||
return (Class<?>) actualTypes[0];
|
||||
} else {
|
||||
// System.out.println("未能获取到范型类型");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the order value of this object.
|
||||
* <p>Higher values are interpreted as lower priority. As a consequence,
|
||||
* the object with the lowest value has the highest priority (somewhat
|
||||
* analogous to Servlet {@code load-on-startup} values).
|
||||
* <p>Same order values will result in arbitrary sort positions for the
|
||||
* affected objects.
|
||||
*
|
||||
* @return the order value
|
||||
* @see #HIGHEST_PRECEDENCE
|
||||
* @see #LOWEST_PRECEDENCE
|
||||
* 越小越靠前
|
||||
*/
|
||||
@Override
|
||||
public int getOrder() {
|
||||
return Ordered.LOWEST_PRECEDENCE;
|
||||
}
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
package org.framework.smart.agent.network.heartbeat.common.advanced;
|
||||
|
||||
|
||||
import io.netty.channel.Channel;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.framework.smart.agent.network.heartbeat.common.MessageType;
|
||||
import org.framework.smart.agent.network.heartbeat.common.enums.MessageTypeEnums;
|
||||
|
||||
/**
|
||||
* 通道不同数据类型处理器
|
||||
*
|
||||
* @see MessageType
|
||||
* @see MessageTypeEnums
|
||||
*/
|
||||
public interface HandleChannelTypeAdvanced extends Ordered {
|
||||
|
||||
|
||||
/**
|
||||
* 处理当前数据
|
||||
*
|
||||
* @param channel 当前通道
|
||||
* @param msg 通道数据
|
||||
*/
|
||||
void handler(Channel channel, Object msg);
|
||||
|
||||
/**
|
||||
* 是否支持当前类型
|
||||
*
|
||||
* @param msg 通道数据
|
||||
* @return 布尔类型 是、否
|
||||
*/
|
||||
boolean support(Object msg);
|
||||
|
||||
|
||||
}
|