Java使用snmp协议采集服务器信息
 
 一.snmp简介
 
  SNMP是专门设计用于在 IP 网络管理网络节点(服务器、工作站、路由器、交换机及Hubs等)的一种标准协议,它是一种应用层协议。 SNMP 使网络管理员能够管理网络效能,发现并解决网络问题以及规划网络增长。通过SNMP接收随机消息(及事件报告)网络管理系统获知网络出现问题。

  SNMP的前身是简单网关监控协议(SGMP),用来对通信线路进行管理。随后,人们对SGMP进行了很大的修改,特别是加入了符合Internet定义的SMI和MIB,改进后的协议就是著名的SNMP。基于TCP/IP的SNMP网络管理框架是工业上的现行标准,由3个主要部分组成,分别是管理信息结构SMI(Structure ofManagement Information)、管理信息库MIB和管理协议SNMP。

  • SMI定义了SNMP框架所用信息的组织和标识,为MIB定义管理对象及使用管理对象提供模板。
  • MIB定义了可以通过SNMP进行访问的管理对象的集合。
  • SNMP协议是应用层协议,定义了网络管理者如何对代理进程的MIB对象进行读写操作。

  SNMP中的MIB是一种树状数据库,MIB管理的对象,就是树的端节点,每个节点都有唯一位置和唯一名字。IETF规定管理信息库对象识别符(OID,Object Identifier)唯一指定,其命名规则就是父节点的名字作为子节点名字的前缀。

二、开发集成

<!-- https://mvnrepository.com/artifact/org.snmp4j/snmp4j -->
<dependency>
<groupId>org.snmp4j</groupId>
<artifactId>snmp4j</artifactId>
<version>2.7.0</version>
</dependency>
  https://mvnrepository.com/artifact/org.snmp4j/snmp4j
  目前最新版本3.7.7,目前以2.7.0版本为例。

 三、基础OID

import java.math.BigDecimal;

/**
* snmp协议工具类配置文件
*/
public class SnmpConfig
{
private SnmpConfig(){} /**
* get cpu描述信息
*/
public static final String SNMPGET_CPUDESC=".1.3.6.1.2.1.1.1.0.255.1"; /**
* walk 网络接口描述
*/
public static final String SNMPWALK_IFDESCR=".1.3.6.1.2.1.2.2.1.2"; /**
* walk 接口物理地址
*/
public static final String SNMPWALK_IFPHYSADDRESS=".1.3.6.1.2.1.2.2.1.6"; /**
* get IO负载
*/
public static final String SNMPGET_IOLOAD=".1.3.6.1.2.1.1.1.0.255.0"; /**
* 硬盘大小
*/
public static final String SNMPGET_DSKTOTAL=".1.3.6.1.4.1.2021.9.1.6"; /**
* walk cpu 负载
*/
public static final String SNMPWALK_HRPROCESSLOAD=".1.3.6.1.2.1.25.3.3.1.2"; /**
* walk cpu 空闲率
*/
public static final String SNMPWALK_SSCPUIDLE=".1.3.6.1.4.1.2021.11.11.0"; /**
* walk 存储设备描述
*/
public static final String SNMPWALK_HRSTORAGEDESCR=".1.3.6.1.2.1.25.2.3.1.3";
/**
* walk 存储设备描述
*/
public static final String SNMPWALK_AHU=".1.3.6.1.2.1.25.2.3.1.4";
/**
* walk 存储设备描述
*/
public static final String SNMPWALK_AUR=".1.3.6.1.2.1.25.2.3.1.5"; /**
*walk 存储设备使用大小
* 内存使用多少,跟总容量相除就是占用率
*/
public static final String SNMPWALK_HRSTORAGEUSED=".1.3.6.1.2.1.25.2.3.1.6";
/**
*walk 内存占用
* 各个进程占用的内存
*/
public static final String SNMPWALK_MEMORY_WIN=".1.3.6.1.2.1.25.5.1.1.2"; /**
*walk 存储设备使用率
*
*/
public static final String SNMPWALK_DSKPERCENT=".1.3.6.1.4.1.2021.9.1.9"; /**
* get 获取内存大小
*/
public static final String SNMPGET_HRMEMORYSIZE=".1.3.6.1.2.1.25.2.2.0"; /**
* 获取机器名
*/
public static final String SNMPWALK_SYSNAME=".1.3.6.1.2.1.1.5"; /**
* 性能参数ID-cpu使用率
*/
public static final Integer PERFORMANCE_PARAM_CPUUSAGE=1; /**
* 性能参数ID-内存使用率
*/
public static final Integer PERFORMANCE_PARAM_MEMORYUSAGE=2; /**
* 性能参数ID-io带宽占用率
*/
public static final Integer PERFORMANCE_PARAM_IOUSAGE=3; /**
* decimal 类型1024,用于除法计算
*/
public static final BigDecimal DEVIDE_NUM=new BigDecimal("1024"); /**
* get方式获取内存大小
*/
public static final String GET_MEMORY="1.3.6.1.2.1.25.2.2.0"; /**
* 获取系统描述
*/
public static final String SYS_DSC="1.3.6.1.2.1.1.1.0"; /**
* 获取网络接口数量
*/
public static final String IF_NUM="1.3.6.1.2.1.2.1.0"; /**
* 获取cpu核数
*/
public static final String CPU_NUM="1.3.6.1.2.1.25.3.3.1.2"; }

 四、snmp信息采集工具类

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.snmp4j.CommunityTarget;
import org.snmp4j.PDU;
import org.snmp4j.Snmp;
import org.snmp4j.event.ResponseEvent;
import org.snmp4j.mp.SnmpConstants;
import org.snmp4j.smi.OID;
import org.snmp4j.smi.OctetString;
import org.snmp4j.smi.UdpAddress;
import org.snmp4j.smi.VariableBinding;
import org.snmp4j.transport.DefaultUdpTransportMapping;
import org.snmp4j.util.DefaultPDUFactory;
import org.snmp4j.util.TableEvent;
import org.snmp4j.util.TableUtils; import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.util.List; /**
* snmp协议工具类
* 获取服务器cpu,内存,及硬盘占用
*/
public class SnmpUtil
{
private static Logger logger = LogManager.getLogger(SnmpUtil.class);
private static Snmp snmp = null;
private CommunityTarget target;
@SuppressWarnings("squid:S3010")
public SnmpUtil(String intranetDeviceIp, Integer snmpPort) throws IOException
{
if (snmp == null)
{
snmp = new Snmp(new DefaultUdpTransportMapping());
snmp.listen();
}
//初始化CommunityTarget
target = new CommunityTarget();
target.setCommunity(new OctetString("public"));
target.setVersion(SnmpConstants.version2c);
target.setAddress(new UdpAddress(intranetDeviceIp + "/" + snmpPort));
target.setTimeout(1000);
target.setRetries(1);
} private ResponseEvent snmpGet(String oid)
{
PDU pdu = new PDU();
pdu.addOID(new VariableBinding(new OID(oid)));
ResponseEvent re=null;
try
{
re = snmp.get(pdu, target);
}catch (Exception e){
logger.info("snmpGet 异常"+e.getMessage());
}
return re;
} private List<TableEvent> snmpWalk(String oid)
{
TableUtils utils = new TableUtils(snmp, new DefaultPDUFactory(PDU.GETBULK));
OID[] columnOid = new OID[]{new OID(oid)};
return utils.getTable(target, columnOid, null, null);
} /**
* 获取cpu负载
* @return
*/
public BigDecimal getCpuUsage()
{
List<TableEvent> list = snmpWalk(SnmpConfig.SNMPWALK_HRPROCESSLOAD);
BigDecimal usage = new BigDecimal("0");
for (TableEvent tableEvent : list)
{
try
{
String s=tableEvent.toString().split("=")[3].split("]")[0].trim();
if (!"-4,exception".equals(s)){
usage=usage.add(new BigDecimal(tableEvent.toString().split("=")[3].split("]")[0].trim()));
}else {
return new BigDecimal("-1");
}
}
catch (Exception e)
{
logger.info("获取cpu负载失败"+e.getMessage());
return new BigDecimal("-1");
}
}
usage = usage.divide(new BigDecimal(list.size()),2,BigDecimal.ROUND_HALF_UP);
return usage;
} /**
* 获取cpu使用率
* @return
*/
public BigDecimal getCpu()
{
BigDecimal totalSize;
ResponseEvent responseEvent = snmpGet(SnmpConfig.SNMPWALK_SSCPUIDLE);
if(responseEvent!=null&&responseEvent.getResponse()!=null){
totalSize=new BigDecimal(responseEvent.getResponse().toString().split("=")[4].split("]")[0].trim());
}else {
return new BigDecimal("-1");
}
return new BigDecimal("100").subtract(totalSize);
} /**
* 获取磁盘占用率
* @return
*/
public BigDecimal getDiskUsageForWindows()
{
BigDecimal multiply=new BigDecimal("-1");
try
{
BigDecimal diskSize = getDiskSize();
BigDecimal diskUsed = getDiskUsed();
if (BigDecimal.ZERO.compareTo(diskSize)<0&&BigDecimal.ZERO.compareTo(diskUsed)<0){
multiply = getDiskUsed().divide(getDiskSize(), 3, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100));
}
}catch (Exception e){
logger.info("获取windows磁盘占用异常"+e.getMessage());
} return multiply;
}
/**
* 获取磁盘占用率
* @return
*/
public BigDecimal getDiskUsage()
{
BigDecimal totalSize=null;
//org.snmp4j.util.TableEvent[index=null,vbs=null,status=-1,exception=null,report=null]
List<TableEvent> tableEvents = snmpWalk(SnmpConfig.SNMPWALK_DSKPERCENT);
if(tableEvents.isEmpty()){
totalSize = getDiskUsageForWindows();
return totalSize;
}
for(int i=0;i<tableEvents.size();i++){
if ("-1,exception".equals(tableEvents.get(i).toString().split("=")[3].split("]")[0].trim())){
return new BigDecimal("-1");
}
String s=tableEvents.get(i).toString().split("=")[3].split("]")[0].trim();
if (!"-4,exception".equals(s)){
totalSize= new BigDecimal(tableEvents.get(i).toString().split("=")[3].split("]")[0].trim());
}else {
return new BigDecimal("-1");
}
} return totalSize;
} /**
* 获取内存使用率
* @return
*/
public BigDecimal getMemoryUsage(){
BigDecimal usage;
BigDecimal totalSize;
try
{
ResponseEvent event = snmpGet(SnmpConfig.SNMPGET_HRMEMORYSIZE);
if (event != null && event.getResponse() != null)
{
totalSize = new BigDecimal(event.getResponse().toString().split("=")[4].split("]")[0].trim());
usage = getMemoryUsed();
return usage.multiply(new BigDecimal("100")).divide(totalSize, 0, BigDecimal.ROUND_HALF_UP);
}
else
{
return new BigDecimal("-1");
}
}catch (Exception e){
logger.info("获取内存使用率失败"+e.getMessage());
return new BigDecimal("-1");
}
} /**
* 获取内存已使用
* @return
*/
public BigDecimal getMemoryUsed(){
List<TableEvent> list=snmpWalk(SnmpConfig.SNMPWALK_HRSTORAGEDESCR);
int index=0;
BigDecimal usedMemory=new BigDecimal("0");
for(int i=0;i<list.size();i++){
String trim = list.get(i).toString().split("=")[3].split("]")[0].trim();
if(trim.contains("Physical memory")){
//linux系统
index=i;
List<TableEvent> usedList=snmpWalk(SnmpConfig.SNMPWALK_HRSTORAGEUSED);
usedMemory= new BigDecimal(usedList.get(index).toString().split("=")[3].split("]")[0].trim());
}else if (trim.contains("Physical Memory")){
//windows系统
List<TableEvent> list1=snmpWalk(SnmpConfig.SNMPWALK_MEMORY_WIN);
BigDecimal re=new BigDecimal("0");
for (int j=0;j<list1.size();j++){
String trim1 = list1.get(j).toString().split("=")[3].split("]")[0].trim();
BigDecimal b = new BigDecimal(trim1);
re=re.add(b);
}
return re;
}else if(trim.contains("Memory buffers")){
//linux系统
index=i;
List<TableEvent> usedList=snmpWalk(SnmpConfig.SNMPWALK_HRSTORAGEUSED);
usedMemory= usedMemory.subtract(new BigDecimal(usedList.get(index).toString().split("=")[3].split("]")[0].trim()));
}else if(trim.contains("Cached memory")){
//linux系统
index=i;
List<TableEvent> usedList=snmpWalk(SnmpConfig.SNMPWALK_HRSTORAGEUSED);
usedMemory= usedMemory.subtract(new BigDecimal(usedList.get(index).toString().split("=")[3].split("]")[0].trim()));
}
}
return usedMemory; } /**
* 获取磁盘
* @return
*/
public BigDecimal getDiskSize(){
List<TableEvent> list=snmpWalk(SnmpConfig.SNMPWALK_HRSTORAGEDESCR);
BigDecimal diskSize=new BigDecimal(-1);
if (!list.isEmpty()){
diskSize=new BigDecimal("0");
List<TableEvent> usedList1=snmpWalk(SnmpConfig.SNMPWALK_AHU);
List<TableEvent> usedList2=snmpWalk(SnmpConfig.SNMPWALK_AUR);
for(int i=0;i<list.size();i++){
boolean re=list.get(i).toString().split("=")[3].split("]")[0].trim().contains(":")||list.get(i).toString().split("=")[3].split("]")[0].trim().contains("/");
if(re){
diskSize=diskSize.add(new BigDecimal(usedList1.get(i).toString().split("=")[3].split("]")[0].trim()).multiply(new BigDecimal(usedList2.get(i).toString().split("=")[3].split("]")[0].trim())).divide(new BigDecimal("1073741824"),2,BigDecimal.ROUND_HALF_UP));
}
}
}
return diskSize;
} /**
* 获取磁盘已使用
* @return
*/
public BigDecimal getDiskUsed(){
List<TableEvent> list=snmpWalk(SnmpConfig.SNMPWALK_HRSTORAGEDESCR);
BigDecimal diskSize=new BigDecimal(-1);
if (!list.isEmpty()){
diskSize=new BigDecimal("0");
List<TableEvent> usedList1=snmpWalk(SnmpConfig.SNMPWALK_AHU);
List<TableEvent> usedList2=snmpWalk(SnmpConfig.SNMPWALK_HRSTORAGEUSED);
for(int i=0;i<list.size();i++){
boolean re=list.get(i).toString().split("=")[3].split("]")[0].trim().contains(":")||list.get(i).toString().split("=")[3].split("]")[0].trim().contains("/");
if(re){
diskSize=diskSize.add(new BigDecimal(usedList1.get(i).toString().split("=")[3].split("]")[0].trim()).multiply(new BigDecimal(usedList2.get(i).toString().split("=")[3].split("]")[0].trim())).divide(new BigDecimal("1073741824"),2,BigDecimal.ROUND_HALF_UP));
}
}
}
return diskSize;
} /**
* 获取IO负载
* @return
*/
public Float getIOUsage(){
ResponseEvent event=snmpGet(SnmpConfig.SNMPGET_IOLOAD);
if(event!=null&&event.getResponse()!=null){
float usage=Float.parseFloat(event.getResponse().toString().split("=")[4].split("]")[0].trim());
if(usage>1){
return usage;
}else{
return usage*100;
}
}
return null;
} /**
* 获取性某性能参数数据
* @param parameterId
* @return
*/
public Object getData(Integer parameterId) {
Object data=null;
try{
if(parameterId.equals(SnmpConfig.PERFORMANCE_PARAM_CPUUSAGE)){
data=getCpuUsage();
}else if(parameterId.equals(SnmpConfig.PERFORMANCE_PARAM_MEMORYUSAGE)){
data=getMemoryUsage();
}else if(parameterId.equals(SnmpConfig.PERFORMANCE_PARAM_IOUSAGE)){
data=getIOUsage();
}
}catch(Exception e){
logger.info("获取性能参数异常"+e.getMessage());
}
return data;
} /**
* 获取设备物理地址
* @return
*/
public String getMacAddress(){
try
{
List<TableEvent> list = snmpWalk(SnmpConfig.SNMPWALK_IFDESCR);
int index = 0;
for (int i = 0; i < list.size(); i++)
{
if (list.get(i).toString().split("=")[3].split("]")[0].trim().contains("eth"))
{
index = i;
}
}
List<TableEvent> ifAddressList = snmpWalk(SnmpConfig.SNMPWALK_IFPHYSADDRESS);
return ifAddressList.get(index).toString().split("=")[3].split("]")[0].trim();
}catch (Exception e){
logger.info("获取物理地址失败"+e.getMessage());
return "failure";
}
} /**
* 获取设备内存大小 单位为GB
* @return
*/
public String getMemoryDesc() {
ResponseEvent event =snmpGet(SnmpConfig.SNMPGET_HRMEMORYSIZE);
Long bytes =Long.parseLong(event==null?"0":event.getResponse().toString().split("=")[4].split("]")[0].trim());
float gb =bytes/1024.0f/1024.0f;
DecimalFormat decimalFormat =new DecimalFormat(".00");
return decimalFormat.format(gb)+"GB";
} /**
* @throws IOException
* 获取cpu描述信息
* @return
*/
public String getCpuDesc() throws IOException {
ResponseEvent event=snmpGet(SnmpConfig.SNMPGET_CPUDESC);
return event==null? "":event.getResponse().toString().split("=")[4].split("]")[0].trim().split(":")[1].trim();
} /**
* 获取存储设备大小 (空盘空间不足百分百)
* @param deviceCode
* @return
*/
public BigDecimal getDiskSize(String deviceCode){ List<TableEvent> list = snmpWalk(SnmpConfig.SNMPGET_DSKTOTAL);
BigDecimal diskSize=new BigDecimal(-1);
if (list!=null){
try
{
for (TableEvent tableEvent:list){
diskSize=new BigDecimal(tableEvent.toString().split("=")[3].split("]")[0].trim()).divide(SnmpConfig.DEVIDE_NUM).divide(SnmpConfig.DEVIDE_NUM,2,RoundingMode.HALF_UP);
}
}catch (Exception e){
logger.info("获取磁盘大小失败"+e.getMessage());
}
}
if (BigDecimal.ZERO.compareTo(diskSize)>0){
diskSize = getDiskSize();
}
return diskSize;
} /**
* 获取磁盘描述
* @param deviceCode
* @return
* @throws IOException
*/
public BigDecimal getDiskDesc(String deviceCode) {
return getDiskSize(deviceCode).divide(SnmpConfig.DEVIDE_NUM,2,RoundingMode.HALF_UP).divide(SnmpConfig.DEVIDE_NUM,2,RoundingMode.HALF_UP);
} /**
* snmp协议检测
*/
public boolean snmpCheck() {
ResponseEvent re=snmpGet(".1.3.6.1.4.1.2021.255.1");
return re == null || re.getResponse() != null;
} /**
* 获取机器名
* @return
*/
public String getSysName(){
String name=null;
try{
List<TableEvent> list = snmpWalk(SnmpConfig.SNMPWALK_SYSNAME);
if (list!=null){
for (TableEvent tableEvent:list){
name=(tableEvent.toString().split("=")[3].split("]")[0].trim());
}
}
}catch (Exception e){
logger.info("获取机器名失败"+e.getMessage());
}
return name;
} /**
* 获取内存总大小(实际值)
* @return
*/
public BigDecimal getMemoryTotalSize(){
try
{
ResponseEvent event = snmpGet(SnmpConfig.GET_MEMORY);
if (event!=null&&event.getResponse()!=null){
String trim = event.getResponse().toString().split("=")[4].split("]")[0].trim();
return new BigDecimal(trim).divide(SnmpConfig.DEVIDE_NUM,2, RoundingMode.HALF_UP).divide(SnmpConfig.DEVIDE_NUM,2, RoundingMode.HALF_UP);
}else {
throw new RuntimeException("获取内存信息失败");
}
}
catch (Exception e)
{
logger.info("获取内存总大小失败"+e.getMessage());
}
return new BigDecimal("-1");
} /**
* 获取系统描述
* @return
*/
public String getSysDsc(){
try
{
ResponseEvent event = snmpGet(SnmpConfig.SYS_DSC);
if (event!=null&&event.getResponse()!=null){
return event.getResponse().toString().split("=")[4].split("]")[0].trim();
}else {
throw new RuntimeException("获取系统描述信息失败");
}
}
catch (Exception e)
{
logger.info("获取系统描述信息失败"+e.getMessage());
}
return "failure";
}
/**
* 获取接口数
* @return
*/
public Integer getIfNumber(){
try
{
ResponseEvent event = snmpGet(SnmpConfig.IF_NUM);
if (event!=null&&event.getResponse()!=null){
String trim = event.getResponse().toString().split("=")[4].split("]")[0].trim();
return Integer.parseInt(trim);
}else {
throw new RuntimeException("获取接口信息失败");
}
}
catch (Exception e)
{
logger.info("获取接口数量失败"+e.getMessage());
}
return -1;
} /**
* 获取cpu核数(n个cpu有n条数据)
* @return
*/
public Integer getCpuNum(){
List<TableEvent> list = snmpWalk(SnmpConfig.CPU_NUM);
Integer num=-1;
if (list!=null){
num=list.size();
}
return num;
} public static void main(String[] args) throws IOException
{
String snmpIp = "127.0.0.1";
Integer snmpPort = 161;
SnmpUtil snmpUtil = new SnmpUtil(snmpIp, snmpPort); System.out.println("机器名称"+snmpUtil.getSysName());
System.out.println("磁盘大小 "+ snmpUtil.getDiskSize("devide"));
System.out.println("物理地址"+snmpUtil.getMacAddress());
System.out.println("cpu "+snmpUtil.getCpuUsage());
}
}

五、结果展示

机器名称localhost
磁盘大小 49.98
cpu 12.67

Java使用snmp协议采集服务器信息的更多相关文章

  1. java EE : http 协议响应头部信息验证

    一  location :*****   302   重定向  private void doWork(HttpServletRequest req, HttpServletResponse resp ...

  2. 【转载】 java利用snmp4j包来读取snmp协议数据(Manager端)

    https://www.cnblogs.com/xdp-gacl/p/4187089.html http://doc.okbase.net/yuanfy008/archive/265663.html ...

  3. linux 安装开启SNMP协议,最下面是yum安装

    Linux SNMP 以下的示例采用SUSE10 Linux环境,但它同样适用于其它Linux发行版. 编译和安装 首先我们需要下载Net-SNMP的源代码,选择一个版本,比如5.7.1,地址如下: ...

  4. Java Web ——http协议请求报文

    package com.demo.util; import java.io.IOException; import java.io.InputStream; import java.net.*; /* ...

  5. SNMP协议入门

    SNMP协议入门 1.引言 基于TCP/IP的网络管理包含3个组成部分: 1) 一个管理信息库MIB(Management Information Base).管理信息库包含所有代理进程的所有可被查询 ...

  6. HTTP协议的头信息详解

    转载地址:http://blog.csdn.net/guoguo1980/article/details/2649658 HTTP(HyperTextTransferProtocol)是超文本传输协议 ...

  7. 浅议SNMP安全、SNMP协议、网络管理学习

    相关学习资料 tcp-ip详解卷1:协议.pdf(重点看25章SNMP部分) http://www.rfc-editor.org/rfc/rfc1213.txt http://www.rfc-edit ...

  8. 网络编辑基础:对HTTP协议的头信息详解

    HTTP(HyperTextTransferProtocol) 是超文本传输协议的缩写,它用于传送WWW方式的数据,关于HTTP 协议的详细内容请参 考RFC2616.HTTP协议采用了请求/响应模型 ...

  9. 用SNMP协议实现系统信息监控--Windows Server 2008

    简单了解: SNMP简单网络管理协议,是一种属于应有层的协议,主要有三个部分组成,被管理部分.代理部分和网络管理系统. 被管理部分是一个网络节点,也称为网络单元.SNMP代理是被管理设备上的一个网络管 ...

  10. PHP. 01. C/S架构、B/S架构、服务器类型、服务器软件、HTTP协议/服务器、数据库、服务器web开发、PHP简介/常见语法、PHPheader()、 PHP_POST/GET数据获取和错误处理

    C/S架构 Client/Server 指客户端,服务器 架构的意思 优点:性能性高:可将一部分的计算工作放在客户端上,服务器只需处理出局即可   洁面炫酷,可使用更多系统提供的效果 缺点:更新软件需 ...

随机推荐

  1. 单细胞测序最好的教程(十):细胞类型注释迁移|万能的Transformer

    作者按 本章节主要讲解了基于transformer的迁移注释方法TOSICA,该算法在迁移注释上达到了SOTA的水平,在注释这么卷的赛道愣是杀出了一条血路.本教程首发于单细胞最好的中文教程,未经授权许 ...

  2. AI知识库这事儿FastGPT是专业的

    在搭建AI知识库这事儿上,有不少成熟的框架,我推荐使用FastGPT.这篇文章笔者就使用过的两款平台做个比较,FastGPT和百度千帆平台. 1. 为什么要搭建知识库 随着企业的运营,企业的私有数据越 ...

  3. Aic 应用开发基础一(概念与场景)

    Agi通用人工智能应用概念与场景 大家看到,自美国OpenAI主导的GPT发布以来,全球科技领域掀起了革命性的浪潮.比如最近看到的aigc 人工绘图,智能机器人等行业,很多新概念掘起, 随着人工智能技 ...

  4. linux环境弱网测试

    linux环境弱网测试 使用以下命令可以对linux系统进行弱网设置 sudo tc qdisc add dev eth0 root netem delay 500ms       #设置500ms的 ...

  5. SpringBoot全局异常处理及自定义异常

    首先定义自定义返回类,如果自己项目中已经有了自定义返回类只需要将后面的代码做相应的修改即可: import io.swagger.annotations.ApiModelProperty; impor ...

  6. 【Java】MuliThread 多线程

    程序Program 是完成特定人,用某种语言编写的一组指令集合,即一段静态代码,静态对象 进程Process 是程序的一次执行过程,可以是一个正在执行的程序 - 程序是静态的,进程是动态的 - 进程是 ...

  7. 【Layui】15 日期时间选择器 Laydate

    文档地址: https://www.layui.com/demo/laydate.html [基本案例] 基本日期与国际日期 <fieldset class="layui-elem-f ...

  8. 使用 abortNavigation 阻止导航

    title: 使用 abortNavigation 阻止导航 date: 2024/8/3 updated: 2024/8/3 author: cmdragon excerpt: 摘要:在Nuxt3中 ...

  9. [SDOI2010] 城市规划 题解

    前言 题目链接:洛谷. 题意简述 树套环上求至少间隔两个位置的最大独立集. (树套环,即树上每个结点都是一个结点或环) 题目分析 将题目拆解成树上 DP 和环上 DP 即可.用 tarjan 缩点就行 ...

  10. [学习笔记] 单调队列优化DP - DP

    单调队列优化DP 简单好想的DP优化 真正的教育是把学过的知识忘掉后剩下的东西 -- *** 对于一个转移方程类似于 \(dp[i]=max(min)\{dp[j]+b[j]+a[i]\}\ \ x_ ...