网站首页 包含标签 服务器 的所有文章

  • Linux实时信息与状态监控脚本

    最近遇到一台无法连接互联网并且没有集成状态监控的Linux服务器,没办法整体观测服务器状态去排查问题。 所以写了下面这个这个脚本来监控,声明这个脚本没办法适配所有Linux服务器。 思路如下,针对自己的服务器情况有需要自己改下再用。 也能在拿到一台新机器时,一键观测下服务器状态。 先看代码 请注意将脚本中的eth0替换为你实际使用的网络接口(如enp0s3,wlan0,ens33等)。 #!/bin/bash # 获取服务器基本信息 hostname=$(hostname) ip_address=$(hostname -I | awk '{print $1}') os=$(lsb_release -ds) kernel=$(uname -r) uptime=$(uptime -p) # 监控循环 while true; do # 获取CPU信息 cpu_model=$(cat /proc/cpuinfo | grep "model name" | head -n1 | awk -F': ' '{print $2}') cpu_cores=$(cat /proc/cpuinfo | grep "model name" | wc -l) # 获取内存信息(加入单位) memory_total=$(free -h | awk 'NR==2{print $2}') memory_used=$(free -h | awk 'NR==2{print $3}') memory_free=$(free -h | awk 'NR==2{print $4}') memory_available=$(free -h | awk 'NR==2{print $7}') # 获取磁盘使用情况 disk_total=$(df -h --output=size / | awk 'NR==2{print $1}') disk_used=$(df -h --output=used / | awk 'NR==2{print $1}') disk_free=$(df -h --output=avail / | awk 'NR==2{print $1}') # 使用 top 命令获取 CPU 使用率 cpu_usage=$(top -b -n 1 | grep "%Cpu(s):" | awk '{printf "%.2f%%", 100-$8}') # 输出监控信息 clear echo "服务器信息:" echo "主机名:$hostname" echo "IP地址:$ip_address" echo "操作系统:$os" echo "内核版本:$kernel" echo "运行时间:$uptime" echo "--------------------------------------" echo "CPU信息:" echo "型号:$cpu_model" echo "核心数:$cpu_cores" echo "CPU使用率:$cpu_usage" echo "--------------------------------------" echo "内存信息:" echo "总量:$memory_total" echo "已使用:$memory_used" echo "可用:$memory_available" echo "--------------------------------------" echo "磁盘信息:" echo "总量:$disk_total" echo "已使用:$disk_used" echo "可用:$disk_free" # 每 3 秒刷新一次 sleep 3 done   运行结果 ...

    2023-12-14 实用工具 183
  • NTP时间同步过程

    NTP通过时间戳和网络延迟计算来调整本地时钟,以确保系统时钟与NTP服务器的时钟尽可能一致,实现高精度的时间同步。 第一步、NTP客户端发起时间请求 NTP客户端向NTP服务器发起时间请求,请求服务器的准确时间。这个请求通常包括客户端的当前时间戳。 通常,这是通过UDP协议的端口123完成的。NTP客户端可以是计算机、路由器、交换机或其他网络设备。 第二步、NTP服务器响应 NTP服务器收到客户端的请求,并在响应中包括自己的时间戳。服务器的时间通常比客户端的时间更准确。服务器的响应包括四个时间戳:T1、T2、T3、T4。 T1:客户端发送请求的时间。 T2:服务器接收到请求的时间。 T3:服务器发送响应的时间。 T4:客户端接收响应的时间。 NTP服务器可以是Stratum 1服务器(通常是高精度时间源,如原子钟或GPS时钟)或Stratum 2服务器,依次类推。 第三步、计算网络延迟 客户端使用T1、T2、T3、T4时间戳来计算网络延迟和时钟偏移。根据这些时间戳,客户端可以计算出网络延迟,即信号从客户端发送到服务器再返回所需的时间。你在示例中计算了延迟,这在NTP中非常重要,因为网络延迟会对时钟同步产生影响。 第四步、调整本地时钟 客户端使用计算得到的网络延迟和服务器的时间戳来调整自己的本地时钟。这个调整会将客户端的时钟与服务器的时钟对齐,以减小时钟偏移。 ?请记住:时间同步不是一次性事件,而是定期进行的。 客户端设备通常每隔一段时间(通常是每10分钟或每小时)与NTP服务器进行一次时间同步,以确保时钟的准确性。 此后的时间同步交换通常只需要一次消息交换,因为客户端已经与NTP服务器建立了时间校准。 ...

    2023-11-07 148
  • 如何在Ubuntu服务器22.04上设置静态IP地址

    在这篇文章中,我们将介绍如何在 Ubuntu 服务器 22.04 上设置静态 IP 地址。 强烈建议在 Linux 服务器上使用静态 IP,因为它会在重启后保持不变。静态 IP 对邮件服务器、Web 服务器和文件服务器等服务器起着重要作用。 准备条件 最小安装的 Ubuntu 服务器 22.04 具有 sudo 管理员权限的普通用户 在 Ubuntu 服务器 22.04 中,网络由 netplan 程序控制,因此我们将使用 netplan 在 Ubuntu 服务器上配置静态 IP 地址。 注意:我们不能使用 nmcli 程序,因为它不是 Ubuntu 服务器上默认安装的一部分。 在Ubuntu服务器22.04上设置静态IP地址 登录到你的 Ubuntu 服务器 22.04,查找 netplan 配置文件。它位于 /etc/netplan 目录下。 $ cd /etc/netplan/ $ ls -l total 4 -rw-r--r-- 1 root root 116 Oct 12 04:03 00-installer-config.yaml $ 运行以下 cat 命令以查看 00-installer-config.yaml 的内容。 注意:配置文件的名称可能因你的设置而异。由于它是一个 yaml 文件,因此请确保在编辑时保持缩进和语法。 $ cat 00-installer-config.yaml 输出: 根据上面的输出,它说我们有 ens33 接口,它正在从 DHCP 服务器获取 IP。查看接口名称的另一种方法是通过 ip 命令。 现在,要配置静态 IP 代替 DHCP,使用 vi 或 nano 编辑器编辑 netplan 配置文件并添加以下内容。 $ sudo vi 00-installer-config.yaml # This is the network config written by 'subiquity' network: renderer: networkd ethernets: ens33: addresses: - 192.168.1.247/24 nameservers: addresses: [4.2.2.2, 8.8.8.8] routes: - to: default via: 192.168.1.1 version: 2 保存并关闭文件。 在上面的文件中,我们使用了以下内容, ens33 为接口名称 用于设置静态 IP 的地址 nameservers 用于指定 DNS 服务器的 IP 用于指定默认网关的路由 注意:根据你的环境更改 IP 详细信息和接口名称。 要是上述修改生效,请使用以下 netplan 命令应用这些更改: $ sudo netplan apply 运行以下 IP 命令查看接口上的 IP 地址: $ ip addr show ens33 要查看默认路由,请运行: $ ip route show 上述命令的输出。 ip-addr-route-command-output-u buntu-server 完美,以上命令的输出确认静态 IP 和路由配置成功。 这就是这篇文章的全部内容。请在下面的评论部分发表你的问题和反馈。 ...

    2023-10-28 232
  • 为什么Java中字符串是不可变的

    文章目录 1. 什么是不可变类? 2.字符串的运作方式 3.不可变字符串的优点 3.1. 应用程序和数据安全性 3.2. 提高性能 3.3. 线程安全性 3.4. 缓存 结论 默认情况下,Java 字符串是不可变的。字符串的不变性有助于提供缓存、安全性、快速性能和更好的内存利用率等功能。本教程讨论字符串的不可变性如何帮助实现这些功能。 1. 什么是不可变类? 什么是不可变类? 让我们从不可变性本身开始。一个不可变对象是一个其状态在其整个生命周期内都保证不会发生改变的对象。这意味着一旦初始化了对象的状态,它就无法在任何情况下被改变。 Java也有不可变类,主要包括String和包装类。 2.字符串的运作方式 在Java中,内存被分为三个部分,即堆(Heap)、栈(Stack)和字符串常量池(String Pool)。字符串常量池是专门用于存储字符串字面值的特殊区域。 当我们创建一个字符串时,会在字符串常量池中搜索具有完全相同内容的String对象。如果找到一个现有的String对象,那么它的引用就会指向新变量,因此,实际上,现有对象也会被重用于新的字符串声明。这有助于减小因为存在多个具有相同内容的字符串而导致的内存使用量。 String str1 = "value"; String str2 = "value"; String str3 = "value"; 上述程序创建了三个String类型的变量,它们都指向字符串常量池区域中的同一个对象。将来所有具有内容“value”的字符串都会指向堆中的同一对象,从而节省内存。 当我们修改一个字符串时,会在字符串常量池中创建一个新的带有修改内容的字符串。现有的对象永远不会被改变。 str3 = "test"; 当没有引用变量指向字符串常量池中的字符串对象时,该对象将被垃圾回收。通过这种方式,一旦创建了一个字符串,它就永远不会被更改。 3.不可变字符串的优点 现在让我们了解一下上面讨论的不可变性如何在运行时有所帮助。 3.1. 应用程序和数据安全性 首先,毫无疑问最重要的原因是安全性。这不仅适用于我们的应用程序,甚至适用于JDK本身。Java类加载机制是根据传递的类名参数来工作的,然后在类路径中搜索这些类。 在以下程序中,我们通过类名加载SQL服务器驱动程序。想象一下,如果字符串是可变的,那么恶意操作者可以更改驱动程序名称,在运行时加载恶意驱动程序类,并几乎不费力地入侵应用程序。 public static final String DRIVER_CLASS = "com.microsoft.sqlserver.jdbc.SQLServerDriver"; Class.forName(DRIVER_CLASS); 类似地,恶意操作者可以更改SQL语句并在运行时执行SQL注入攻击。不可变性确保不会发生此类修改。 3.2. 提高性能 String类的不可变性是字符串常量池的基础。如果没有不可变性,普通堆内存和字符串常量池之间就没有区别。 正如在前面的部分中讨论的那样,字符串常量池有助于实现更好的内存利用率,从而提高性能。 3.3. 线程安全性 不可变对象在多线程应用程序中自动具备线程安全性。如果某物无法更改,那么即使线程也无法更改它。非常简单! 由于String类在Java编程语言中是主要的构建块,因为它用于类加载机制,因此在多线程情况下,必须防止String类被污染。不可变性在这里起到了魔法作用。 3.4. 缓存 缓存通常是作为键-值对实现的,类似于Java中的Map实现。缓存键通常存储为字符串,以便快速查找。 考虑一下,如果我们可以在与其关联的值存储在缓存中之后更改键,那么在我们意外构建相同键之前,将不可能再检索该值。 字符串的不可变性保证了缓存键永远不会被更改。这就是为什么在Java中字符串是缓存和映射中最常用的键的原因。 结论 从以上讨论可以得出结论,字符串的不可变性有助于实现Java应用程序所需的安全性和性能。 ...

    2023-09-16 217
  • Java OOP面向对象编程简介及4大特性

    文章目录 1. 什么是OOP或面向对象编程? 1.1. 类和对象 1.2. 构造函数 2. OOP 的 4 个特性 2.1. 抽象 2.1.1. 数据抽象 2.1.2. 控制抽象 2.2. 封装 2.2.1. 信息隐藏 2.2.2. 实施隐藏 2.3. 继承 2.3.1. 继承示例 2.3.2. 继承的类型 2.4. 多态性 2.4.1. 编译时多态性 2.4.2. 运行时多态性 3.更多面向对象编程概念 3.1. 耦合度 3.2. 内聚度 3.3. 关联 3.4. 聚合 3.5. 组合 4.最佳实践 4.1. 优先考虑组合而不是继承 4.2. 面向接口编程,而不是具体实现 4.3. DRY(不要重复自己) 4.4. 封装变化 4.5. 单一职责原则 4.6. 开闭原则 5. 总结 面向对象编程(OOP)是指基于对象的编程方法,而不是像函数式编程那样仅基于函数和过程。这些对象可以包含数据(属性)和方法(行为),就像我们在应用程序中建模的现实生活实体一样。 本教程将教我们四个主要特性——抽象、封装、继承和多态性。这些也被称为面向对象编程范式的四大特性。 1. 什么是OOP或面向对象编程? 早期,人们用二进制代码编写程序,并使用机械开关来加载程序。后来,随着硬件功能的发展,专家尝试使用高级语言来简化编程,我们使用编译器从程序生成机器指令。 随着更多的发展,专家们创建了基于小函数的结构化编程。这些函数在很多方面都有帮助,例如代码重用、局部变量、代码调试和代码可维护性。 随着计算的进步和对更复杂应用程序的需求,结构化编程的局限性开始显现出来。复杂的应用程序需要与现实世界和用例更紧密地建模。 后来,专家们开发了面向对象编程。在 OOP 的中心,我们有对象和类。就像现实生活中的实体一样,对象具有两个重要特征: 数据– 讲述属性和对象的状态 行为– 赋予其改变自身并与其他对象进行通信的能力 1.1. 类和对象 对象是类的实例。每个对象都有自己的状态、行为和身份。类是其对象的蓝图或模板。 对象可以通过调用函数与其他对象进行通信。它有时被称为消息传递。 例如,如果我们正在开发人力资源应用程序,那么它由实体/参与者组成,例如员工、经理、部门、工资单、假期、目标、时间跟踪等。为了在计算机程序中对这些实体进行建模,我们可以创建具有类似属性的类现实生活中的数据属性和行为。 例如,员工实体可以表示为Employee类: public class Employee { private long id; private String title; private String firstName; private String middleName; private String lastName; private Date dateOfBirth; private Address mailingAddress; private Address permanentAddress; // 根据应用程序的要求,可以添加更多类似的属性、getter和setter方法。 }   以上Employee作为模板。我们可以使用此类在应用程序中创建所需数量的不同员工对象。 Employee e = new Employee(111); e.setFirstName("Alex"); .. .. int age = e.getAge();   该id字段有助于存储和检索任何单个员工的详细信息。 对象标识通常由应用程序运行时环境维护,例如,用于Java应用程序的Java虚拟机(JVM)。每次我们创建一个 Java 对象时,JVM 都会为该对象创建一个哈希码并分配它。这样,即使程序员忘记添加id字段,JVM 也能确保所有对象都是唯一标识的。 1.2. 构造函数 构造函数是没有任何返回值的特殊方法。它们的名称始终与类的名称相同,但它们可以接受参数,这些参数有助于在应用程序开始使用对象之前设置对象的初始状态。 如果我们不提供任何构造函数,JVM 会为该类分配一个默认构造函数。此默认构造函数不接受任何参数,即无参构造。 请记住,如果我们为任何类分配构造函数,那么 JVM 不会为其分配默认构造函数。如果需要,我们需要向类显式指定默认构造函数。 public class Employee { // 默认构造 public Employee() { } // 自定义构造 public Employee(int id) { this.id = id; } }   2. OOP 的 4 个特性 面向对象编程的四大特点是: 抽象 封装 继承 多态 2.1. 抽象 当我们将抽象与实时示例联系起来时,它就很容易理解。例如,当我们驾驶汽车时,我们不必关心汽车的确切内部工作原理。我们关心的是通过方向盘、制动踏板、油门踏板等接口与汽车进行交互。在这里,我们对汽车的了解是抽象的。 在计算机科学中,抽象是用形式与其含义(语义)相似的表示来定义数据和程序,同时隐藏实现细节的过程。 简而言之,抽象隐藏了与上下文无关的信息,或者只显示相关信息,并通过将其与现实世界中的类似信息进行比较来简化它。 通常抽象可以通过两种方式来看待: 2.1.1. 数据抽象 数据抽象是从多个较小的数据类型创建复杂数据类型的方法,这更接近现实生活中的实体。例如, Employee 类可以是具有各种小关联的复杂对象。 public class Employee { private Department department; private Address address; private Education education; //So on... } 因此,如果您想获取有关员工的信息,您可以从 Employee 对象中询问 – 就像在现实生活中一样,询问该人本人。 2.1.2. 控制抽象 控制抽象是通过隐藏复杂任务的操作序列(在简单的方法调用内)来实现的,因此执行任务的逻辑可以对客户端隐藏,并且可以在不影响客户端代码的情况下进行更改。 public class EmployeeManager { public Address getPrefferedAddress(Employee e) { //从数据库获取所有地址 //在这里实现获取所有地址的逻辑 //返回一个包含所有地址的列表 } } 在上面的例子中,明天如果你想改变逻辑,让每次国内地址始终是首选地址,你就改变getPrefferedAddress()方法内部的逻辑,  客户端将不受影响。 2.2. 封装 将数据和方法包装在类中并与实现隐藏(通过访问控制)相结合通常称为封装。结果是具有特征和行为的数据类型。 “无论发生何种变化,都要将其封装起来” – 一条著名的设计原则。 封装本质上既有信息隐藏,也有实现隐藏。 信息隐藏是通过使用访问控制修饰符(public、private、protected)来完成的,实现隐藏是通过为类创建接口来实现的。 实现隐藏允许设计者修改对象履行职责的方式。当设计(甚至需求)可能发生变化时,这一点尤其有价值。 让我们举一个例子来更清楚地说明这一点。 2.2.1. 信息隐藏 class InformationHiding { //限制直接访问内部数据 private ArrayList items = new ArrayList(); //提供一种访问数据的方式 - 内部逻辑可以在将来安全地进行更改 public ArrayList getItems(){ return items; } }   2.2.2. 实施隐藏 interface ImplemenatationHiding { Integer sumAllItems(ArrayList items); } class InformationHiding implements ImplemenatationHiding{//限制直接访问内部数据private ArrayList items = new ArrayList(); //提供一种访问数据的方式 - 内部逻辑可以在将来安全地进行更改 public ArrayList getItems(){ return items; } public Integer sumAllItems(ArrayList items) { // 在这里,您可以按任何顺序执行N项操作 // 这些操作您不希望客户端知道 // 您可以更改顺序甚至整个逻辑 // 而不会影响客户端。 } }   2.3. 继承 继承是面向对象编程中的另一个重要概念。继承是一个类获取父类的属性和行为的一种机制。它本质上是在类之间创建父子关系。在Java中,我们使用继承主要是为了代码的可重用性和可维护性。 Java 中的关键字“ extends ”用于继承类。“ extends”关键字表示我们正在创建一个派生自现有类的新类。 在Java术语中,被继承的类称为超类。新类称为子类。 子类从其超类继承所有非私有成员(字段、方法和嵌套类)。构造函数不是成员,因此不能被子类继承,但可以从子类调用超类的构造函数。 2.3.1. 继承示例 public class Employee { private Department department; private Address address; private Education education; //So on... } public class Manager extends Employee { private List<Employee> reportees;}   在上面的代码中,Manager 是 Employee 的特殊版本,重用Employee类中的部门、地址和教育,并定义了自己的reportees列表。 2.3.2. 继承的类型 单继承——子类派生自一个父类。 class Parent { //code } class Child extends Parent { //code}   多重继承——一个孩子可以从多个父母那里继承。在 JDK 1.7 之前,通过使用类在 java 中无法实现多重继承。但从 JDK 1.8 开始,通过使用带有默认方法的接口可以实现多重继承。 interface MyInterface1 { } interface MyInterface2 { } class MyClass implements MyInterface1, MyInterface2 { }   多级继承——指三个以上的类之间的继承,其中一个子类将充当另一个子类的父类。 class A { } class B extends A { } class C extends B { }   层次继承是指有一个超类和多个扩展超类的子类时的继承。 class A { } class B extends A { } class C extends A { } class D extends A { }   混合继承——是两种或多种继承类型的组合。因此,当类之间的关系包含两种或多种类型的继承时,我们就说类实现了混合继承。 interface A { } interface B extends A { } class C implements A { } class D extends C impements B { }   2.4. 多态性 多态性是一种能力,通过它,我们可以创建在不同的编程上下文中表现不同的函数或引用变量。它通常被称为具有多种形式的一个名称。 例如,在大多数编程语言中, '+' 运算符用于添加两个数字和连接两个字符串。根据变量的类型,运算符会更改其行为。这称为运算符重载。 在Java中,多态本质上分为两种: 2.4.1. 编译时多态性 在编译时多态性中,编译器可以在编译时将适当的方法绑定到相应的对象,因为它拥有所有必要的信息并且知道在程序编译期间调用哪个方法。 它通常被称为静态绑定或早期绑定。 在Java中,它是通过使用方法重载来实现的。在方法重载中,方法参数可以随参数的数量、顺序或类型而变化。 class PlusOperator { int sum(int x, int y) { return x + y; } double sum(double x, double y) { return x + y; } String sum(String s1, String s2) { return s1.concat(s2); } }   2.4.2. 运行时多态性 在运行时多态性中,对重写方法的调用在运行时动态解析。将在其上执行方法的对象是在运行时确定的——通常取决于用户驱动的上下文。 它通常被称为动态绑定或方法重写。我们可能听说过动态方法调度这个名字。 在运行时多态性中,我们通常有一个父类和至少一个子类。在类中,我们编写一条语句来执行父类和子类中存在的方法。 使用父类类型的变量给出方法调用。类的实际实例是在运行时确定的,因为父类类型变量也可以存储对父类以及子类实例的引用。 class Animal { public void sound() { System.out.println("Some sound"); } } class Lion extends Animal {public void sound() {System.out.println("Roar");}} class Main {public static void main(String[] args) { //Parent class reference is pointing to a parent object Animal animal = new Animal(); animal.sound(); //Some sound //Parent class reference is pointing to a child object Animal animal = new Lion(); animal.sound(); //Roar }}   3.更多面向对象编程概念 除了上述的四个面向对象编程构建基块之外,还有一些其他概念在构建整体理解方面起着重要作用。 在深入探讨之前,我们需要了解术语“模块”。在一般的编程中,模块是执行独特功能的类或子应用程序。在人力资源应用程序中,一个类可以执行诸如发送电子邮件、生成工资单、计算员工年龄等各种功能。 3.1. 耦合度 耦合度是模块之间相互依赖程度的度量。耦合度指的是软件元素与其他元素之间的联系强度。良好的软件将具有低耦合度。 这意味着一个类应该执行唯一的任务,或者只执行与其他任务无关的任务。例如,一个EmailValidator类只会验证电子邮件。同样,EmailSender类只会发送电子邮件。 如果我们将这两个功能都包含在一个名为EmailUtils的单个类中,那么这就是紧密耦合的示例。 3.2. 内聚度 内聚度是保持模块整体性的内在因素。良好的软件设计将具有高内聚度。 这意味着一个类/模块应该包含执行其功能所需的所有信息,而不依赖于其他内容。例如,一个EmailSender类应该能够配置SMTP服务器,并接受发件人的电子邮件、主题和内容。基本上,它应该只关注发送电子邮件。 应用程序不应该将EmailSender用于发送电子邮件以外的任何其他功能。低内聚度会导致庞大的类,难以维护、理解和降低可重用性。 3.3. 关联 关联指的是具有独立生命周期且彼此没有所有权的对象之间的关系。 以教师和学生为例。多个学生可以与单个教师关联,单个学生也可以与多个教师关联,但它们都有自己的生命周期。 两者都可以独立创建和删除,因此当教师离开学校时,我们不需要删除任何学生,当学生离开学校时,我们也不需要删除任何教师。 3.4. 聚合 聚合指的是具有独立生命周期但具有“拥有关系”的对象之间的关系。它发生在子类和父类之间,其中子对象不能属于另一个父对象。 以手机和手机电池为例。一块电池一次只能属于一个手机。如果手机停止工作,我们从数据库中删除它,手机电池将不会被删除,因为它可能仍然可用。因此,在聚合中,虽然存在所有权,但对象有自己的生命周期。 3.5. 组合 组合指的是对象没有独立生命周期的关系。如果删除父对象,所有子对象都将被删除。 例如,问题和答案之间的关系。一个问题可以有多个答案,但答案不能属于多个问题。如果我们删除一个问题,它的所有答案将自动被删除。 4.最佳实践 4.1. 优先考虑组合而不是继承 继承和组合都促进了代码的可重用性。但在继承与组合之间,更倾向于使用组合。 组合的实现通常从创建各种表示系统必须展现的行为的接口开始。接口使得多态行为成为可能。实现已确定接口的类会根据需要构建并添加到业务领域类中。因此,系统行为可以在没有继承的情况下实现。 interface Printable { print(); } interface Convertible { print(); } class HtmlReport implements Printable, Convertible { } class PdfReport implements Printable { } class XmlReport implements Convertible { } 4.2. 面向接口编程,而不是具体实现 这会导致灵活的代码,可以与接口的任何新实现一起使用。我们应该将接口用作变量、方法的返回类型或方法的参数类型。 接口充当超类类型。通过这种方式,我们可以在不修改现有代码的情况下,在将来创建更多接口的特定实现。 4.3. DRY(不要重复自己) 不要编写重复的代码,而是使用抽象将常见的内容抽象到一个地方。 作为一个基本原则,如果在两个地方写了相同的代码 – 考虑将其提取到一个单独的函数中,并在两个地方调用该函数。 4.4. 封装变化 所有软件都会随着时间的推移而发生变化。因此,将您期望或怀疑将来会发生变化的代码封装起来。 在Java中,使用私有方法来隐藏此类实现,以使客户端不必在进行更改时更改其代码。 还建议使用设计模式来实现封装。例如,工厂设计模式封装了对象创建代码,并提供了灵活性,以后可以引入新类型,而不会影响现有客户端。 4.5. 单一职责原则 这是面向对象编程类设计的SOLID原则之一。它强调一个类应该只有一个责任。 换句话说,我们应该为一个目的编写、更改和维护一个类。这将使我们能够在不担心更改对另一个实体产生影响的情况下进行未来更改。 4.6. 开闭原则 它强调软件组件应该对扩展开放,但对修改关闭。 这意味着我们的类应该设计得当,以便其他开发人员在应用程序中的特定条件下更改控制流时,他们只需要扩展我们的类并重写一些函数,就可以了。 如果其他开发人员由于我们的类所施加的约束而无法设计所需的行为,那么我们应该重新考虑更改我们的类。 在整个面向对象编程范 Paradigm 内还有许多其他概念和定义,我们将在其他教程中学习。 5. 总结 这个Java面向对象编程(OOP)教程讨论了Java中的四个主要OOP特性,附有易于理解的程序和片段。您可以在评论部分提出您的问题。   ...

    2023-08-26 198
  • CentOS7搭建SpringBoot项目整合ELK环境详解

    文章目录 前言 1、ELK概述 2、环境&版本 3、Elasticsearch 3.1、下载Elasticsearch 3.2、安装Elasticsearch 3.3、配置Elasticsearch 3.4、启动Elasticsearch 4、Logstash 4.1、下载Logstash 4.2、安装Logstash 4.3、配置Logstash 4.4、启动Logstash 5、Kibana 5.1、下载Kibana 5.2、安装Kibana 5.3、配置Kibana 5.4、启动Kibana 6、SpringBoot集成ELK 6.1、添加依赖 6.2、修改Logback配置 6.3、启动SpringBoot项目 6.4、在Kibana中查看日志 总结 前言 本文详细介绍了在CentOS 7操作系统上搭建ELK以及在SpringBoot项目中整合ELK的步骤。以下内容来自掘金用户汪小成。 1、ELK概述 ELK代表Elasticsearch、Logstash和Kibana三个开源项目的首字母缩写。这三个项目共同构成了一个成熟且强大的实时日志集中处理方案。在这个方案中,Logstash用于日志收集,Elasticsearch则用于数据存储和索引,而Kibana则提供了一个直观的可视化界面,用于查看存储在Elasticsearch中的日志数据。 2、环境&版本 服务器系统版本、JDK版本、ELK版本信息如下: 环境 版本 端口号 Centos 7.9   JDK 1.8   Elasticsearch 7.2.1 39100 Logstash 7.2.1 39102 Kibana 7.2.1 39101 Elasticsearch、Logstash和Kibana三个开源项目都需要在Java环境下运行,所以需要提前在服务器上安装JDK。 centos的环境搭建的JDK1.8。本文中没有讲述JDK的安装,有需要的朋友可以参考《Centos7 安装JDK1.8》文章。 3、Elasticsearch 3.1、下载Elasticsearch $ wget –c https://mirrors.huaweicloud.com/elasticsearch/7.2.1/elasticsearch-7.2.1-x86_64.rpm 为了更快的下载速度,我选择在华为开源镜像站下载Elasticsearch。 3.2、安装Elasticsearch $ rpm -ivh elasticsearch-7.2.1-x86_64.rpm 3.3、配置Elasticsearch Elasticsearch配置文件位置:/etc/elasticsearch。 进入配置文件所在文件夹: $ cd /etc/elasticsearch 备份配置文件(非必要): $ cp elasticsearch.yml elasticsearch.backup.yml 使用vim打开elasticsearch.yml配置文件,按下i进入编辑模式。修改内容如下: network.host: 0.0.0.0 http.port: 39100 discovery.seed_hosts: ["127.0.0.1:39100"] 配置项说明: network.host用于设置绑定的主机地址,可以是IP地址或主机名。http.port用于设置监听的HTTP端口,出于一些特殊原因,我将elasticsearch的端口号由默认的9200修改为39100。discovery.seed_hosts用于设置集群节点的种子主机地址,用于节点发现和加入集群。 3.4、启动Elasticsearch # 启动Elasticsearch $ sudo systemctl start elasticsearch 将Elasticsearch设置为开机启动(非必要): # 将Elasticsearch设置为开机自启 $ sudo systemctl enable elasticsearch 查看Elasticsearch的运行状态: $ sudo systemctl status elasticsearch 或者,使用如下命令检查Elasticsearch是否启动成功: # 检查Elasticsearch是否启动成功 $ netstat -antp | grep 39100 待Elasticsearch启动成功后,可以使用curl命令来测试Elasticsearch是否正常运行。例如: $ curl http://127.0.0.1:39100 如果返回类似以下内容,说明Elasticsearch已经成功运行: { "name" : "localhost.localdomain", "cluster_name" : "elasticsearch", "cluster_uuid" : "NqlpN5iJQmeSV_TvHqPo6w", "version" : {   "number" : "7.2.1",   "build_flavor" : "default",   "build_type" : "rpm",   "build_hash" : "fe6cb20",   "build_date" : "2019-07-24T17:58:29.979462Z",   "build_snapshot" : false,   "lucene_version" : "8.0.0",   "minimum_wire_compatibility_version" : "6.8.0",   "minimum_index_compatibility_version" : "6.0.0-beta1" }, "tagline" : "You Know, for Search" } 最后,使用如下命令修改Centos防火墙配置开放端口号供外访问: $ sudo firewall-cmd --zone=public --add-port=39100/tcp --permanent 重新加载防火墙规则以使更改生效: $ sudo firewall-cmd --reload 4、Logstash 4.1、下载Logstash 在华为开源镜像站下载Logstash: $ wget –c https://repo.huaweicloud.com/logstash/7.2.1/logstash-7.2.1.rpm 4.2、安装Logstash $ rpm -ivh logstash-7.2.1.rpm 4.3、配置Logstash 在/etc/logstash/conf.d文件夹下创建logstash.conf配置文件,配置文件内容如下: input {   tcp {       host => "0.0.0.0"       port => 39102       mode => "server"       codec => json_lines   } } output {   elasticsearch {       hosts => "localhost:39100"       index => "%{[appname]}-%{+YYYY.MM.dd}"   } } 配置说明: input – 用于定义数据的输入源,即Logstash的数据来源。 tcp – 用于指定Logstash监听指定的IP和端口,接收 TCP 连接传入的数据。 host – 监听的主机IP地址,这里的0.0.0.0表示监听所有可用的网络接口。 port – 监听的端口号。我这里将端口号由默认的9600改为了39102。 mode – 连接模式。 codec – 数据编码解码方式,json_lines表示接收到的数据将以JSON行的形式解析。 output – 用于定义数据的输出目录。 elasticsearch – 表示将数据输出到Elasticsearch集群。 hosts – 用于设置Elasticsearch集群的主机地址和端口号。 index – 用于指定Elasticsearch索引的名称。这里使用 %{[appname]} 表示索引名称从数据中的appname字段获取。%{+YYYY.MM.dd}表示在索引中包含日期信息。 4.4、启动Logstash $ sudo systemctl start logstash 最后,使用如下命令修改Centos防火墙配置开放端口号供外访问: $ sudo firewall-cmd --zone=public --add-port=39102/tcp --permanent 重新加载防火墙规则以使更改生效: $ sudo firewall-cmd --reload 5、Kibana 5.1、下载Kibana $ wget –c https://repo.huaweicloud.com/kibana/7.2.1/kibana-7.2.1-x86_64.rpm 5.2、安装Kibana $ rpm -ivh kibana-7.2.1-x86_64.rpm 5.3、配置Kibana 进入/etc/kibana文件夹,修改kibana.yml配置文件中如下内容: server.port: 39101 server.host: "0.0.0.0" elasticsearch.hosts: ["http://localhost:39100"] i18n.locale: "zh-CN" 配置说明: server.port – 用于指定Kibana服务监听的端口号,这里我将端口号由默认的5601改成了39101。 server.host – 用于指定Kibana服务监听的主机地址。”0.0.0.0″表示监听所有可用的网络接口,即可以从任意IP地址访问Kibana。 elasticsearch.hosts – 用于设置Elasticsearch集群的主机地址和端口号。 i18n.locale – 用于设置界面语言,这里将界面语言设置成了中文。 5.4、启动Kibana $ sudo systemctl start kibana 最后,使用如下命令修改Centos防火墙配置开放端口号供外访问: $ sudo firewall-cmd --zone=public --add-port=39101/tcp --permanent 重新加载防火墙规则以使更改生效: $ sudo firewall-cmd --reload 6、SpringBoot集成ELK Spring Boot应用输出日志到ELK的大体流程如下图所示:说明: Spring Boot应用产生日志数据,使用Logback日志框架记录日志。 Logstash作为日志收集器,接收Spring Boot应用发送的日志数据。 Logstash解析和过滤日志数据,可能会对其进行格式化和处理。处理后的日志数据被发送到Elasticsearch,Elasticsearch将日志数据存储在分布式索引中。 Kibana连接到Elasticsearch,可以查看存储在Elasticsearch中的日志数据。 6.1、添加依赖 修改pom.xml文件,添加如下配置: dependency>    groupId>net.logstash.logbackgroupId>    artifactId>logstash-logback-encoderartifactId>    version>7.2version> dependency> 6.2、修改Logback配置 修改Logback的配置文件: + +   +   60.211.159.140:39102 +   +   +       +       {"appname":"spring-boot-elk"} +   +   +     6.3、启动SpringBoot项目 这一步,我就不废话了。 6.4、在Kibana中查看日志 1、在浏览器地址样中输入服务器IP+Kibana端口号 –> 点击管理 –> 点击索引模式 –> 点击创建索引模式。2、输入索引模式名称 –> 点击下一步。3、设置时间筛选字段名称,我这里没有使用时间筛选。4、点击Discover图标就可以看到Spring Boot项目输出的日志了。 总结 以上就是作者分享的CentOS7搭建Spring Boot项目整合ELK环境全部内容详解,希望对你有帮助! ...

    2023-08-20 247
  • 宝塔面板Nginx防火墙ip白名单无效怎么办?

    对宝塔的Nginx防火墙进行卸载重装或者点过修复后,重新导入数据发现有问题,通过宝塔的备份功能导入的数据ip黑白名单会失效。 今下午突然发现网站对CDN节点ip进行了错误拦截导致无法访问,很莫名其妙,我防火墙明明添加了ip白名单竟然还会拦截。 第一时间怀疑是Fail2ban防爆破插件导致的问题,筛查后排除。 然后排查到宝塔专业版Nginx防火墙上,查看添加的ip白名单和黑名单,没有问题,数据导入后都在。 但是我重新添加ip白名单的时候发现竟然能重复添加?这就有问题了,如果是正常情况下重复添加会有提示的,而宝塔Nginx防火墙我今天刚新安装的应该没有问题,于是怀疑到了宝塔的这个导入导出备份功能。 然后我删掉全部ip白名单手动添加,还是拦截,感觉问题有点大,就把黑名单也清空了。 然后宝塔防火墙正常工作,不再误拦截。 这说明宝塔Nginx防火墙的导入配置导出配置功能是有问题的,重新导入的ip黑白名单混乱,导致异常拦截。 如果你也是碰到这种问题,就把ip黑白名单全部清空然后手动添加吧,不要用宝塔的备份功能。 宝塔防火墙问题版本:Nginx防火墙 9.2.1...

    2023-08-18 221
  • 服务器存储如何选择使用HDD还是SSD

    在选择服务器存储方案时,需要综合考虑多个因素: 性能需求: 如果项目需要高性能、快速的数据访问速度,特别是在虚拟化、数据库等应用中,SSD可能更适合。 存储容量: 如果项目需要大量存储空间,HDD可能是更经济的选择。但是,如果预算允许,也可以考虑使用更大容量的SSD。 可靠性和耐用性: 如果项目需要更高的可靠性和抗冲击性,SSD可能更合适,因为它没有机械部件。 成本预算: HDD通常比SSD更便宜,适用于成本敏感的项目。但是,如果性能要求较高,可能需要权衡性能和成本之间的关系。 未来扩展性: 考虑到项目未来的增长和扩展,可以选择支持更多硬盘的服务器,以便在需要时可以轻松扩展存储容量。 ...

    2023-08-12 151
  • 视频网站如何选择国外服务器?

    地理位置:选择靠近目标用户群体的国外服务器位置是至关重要的。若用户主要集中在中国以外的地区,因您应选择位于用户所在地附近的服务商,以确保视频的传输速度。 带宽和速度:选择带宽足够且方便升级的服务商,以保证视频的传输速度。考虑选择双线或多线云服务器机房,这能提高视频网站用户的访问速度。 攻|击防御: 考虑攻|击性问题,根据自身实际情况选择高防云服务器来防御可能的攻|击。 处理器性能:选择具有卓越处理器的服务器,特别是如果您的网站加载了CPU密集型脚本。 存储容量:选择存储容量足够的服务器,以满足视频网站对存储资源的需求。 带宽和流量:在建设视频网站时,首|选大带宽服务器,以确保足够的带宽和流量支持。 不限制流量:对于内容要求不严格的视频网站,建议选择不限制流量的服务器,以确保用户能够自由地访问和观看视频。 类型和配置:确保服务器的配置能够处理大量并发数据,并满足视频网站对处理能力和网络需求的要求。 网络稳定性:选择网络稳定性较高的境外服务器类型,根据网站业务分布范围和受众群体所在位置进行考虑。 文件传输和储存:对于视频网站,考虑选择具有较大储存容量和传输速度的服务器,以便存储和传输大量的视频文件。 通过考虑这些因素,选择适合视频网站需求的国外服务器,将能够提供稳定的传输速度、高质量的视频播放体验,以及更好的用户体验。 ...

    2023-08-10 157
  • 无服务器 90% 的情况都很糟糕

    无服务器 10% 的情况令人惊叹。剩下的 90% 则是一个危险的黑洞,里面是云锁定、糟糕的测试、差劲的开发体验和复杂的设置。这就是为什么会有一些老人发誓不使用无服务器,同时又有大量的支持者(像我一样)试图把它推广到任何适合的地方。 不管是哪一方,都有一些事项需要留意。对于无服务器的支持者而言: 无服务器应用程序的架构并没有更简单; 无服务器消除 / 简化了 devops,因此,部署 /devops 更简单了; 为了让无服务器产生预期的效果,你必须采用无服务器架构,这与许多公共框架(如 Rails)的最佳实践建议不相符; 没有哪个云提供商的最佳实践是真正的最佳实践。他们的兴趣在于把你锁定,因此,他们会尝试将自己融入到你的开发 / 测试工作流,或者在开发中需要云连接; 在同一个项目中使用多种语言并不是一项特性。 对于无服务器的反对者来说: 几乎可以肯定,遵循云提供商的最佳实践已经让你吃不消了,忽略那些试图锁定你的云提供商,你会过得更好。 运行本地版本是有效的无服务器 DX 的必要条件,任何像样的无服务器架构都很容易像 docker 容器一样运行。 有一种无服务器架构可以让每个人在大多数情况下都满意。但这通常不明显,因为它处于无状态服务器最佳实践和云提供商最佳实践的交叉点上,但永远不会完全是哪一个。 1有效的无服务器架构 好了,现在我们已经冷静下来,我们已经认识到,无服务器不是编程和应用程序架构的救世主。现在可以开始构建简单、易于维护、可测试的应用程序了。 下面是无服务器架构必须做到的一些要点: 一切都必须能够在本地运行,与传统的有状态服务器一样(你需要能够运行自己的系统); 每个端点都应该有针对本地运行的无服务器实例运行的测试; 以一种简单、易于理解的方式处理路由,例如使用文件路径作为端点或一个中心化的 JSON 配置; 完全正常。它应该看起来像一个 npm 包、一个 pip 模块等等。没有人需要通过看图表来理解它是如何工作的; 每个端点所需的样板文件都尽可能少; 整体式的代码组织,每个应用程序一个库,其中包含多个端点。 云提供商应提供以下特性: 自动扩展端点; 自动部署和版本控制; 易于回滚。 2关于无服务器的恐怖故事 我曾见过有人在云提供商的云 IDE 中编写代码,两次测试之间要等 2 分钟。有时,一个端点连接到如此多的云服务,所以真的只能在生产环境中进行测试。有时不是所有端点都在一个库中,而是有很多库,每个库包含不同的系统组件。 开发体验是快速实施的关键,你应该努力保持快速的反馈循环和测试,让你可以快速前进,而不必担心整个系统崩溃。 优质的无服务器提供商每个无服务器提供商都必须经过改造才能成为有效的架构。 每个无服务器提供商都试图让你不可逆转地将它们融入。你不需要把它们融入。遵循最佳实践,除非它违反了“必须在本地运行”的原则,否则你应该没事。 现在,我喜欢以下这两家无服务器提供商: Vercel——基于 AWS Lambda 构建,重视开发体验。优秀的自动部署和版本控制。非常友好的价格。我在把 collegeai.com 重构到 Vercel 之后遭遇了峰值流量,而它在第一天扩展时就没有出现任何严重的问题。你可能需要放弃他们的开发系统(vc dev ),以获得一个有效的容器化 / 本地运行的应用程序,但这并不困难。 Cloudflare Workers——Wrangler(worker 的命令行开发工具)意识到本地开发的重要性,而 cloudflare worker 非常便宜。但是,我要提醒的是,它们对 NodeJS 模块的支持不是很好,所以它们还不是一个重要的选项,除非在低成本扩展绝对关键的情况下。 对于下面这两家提供商,我要提醒你注意: AWS Lambda(直接)——对于应用程序开发人员来说,AWS Lambda 太复杂了,我从未见过一个让人感觉正常、易于理解并且使用 Lambda 在本地运行的架构。 Fastly——如果需要一个销售电话来开始,那么我可以打赌开发体验将很垃圾。 我还没有足够的经验,听说得也不是很多: Netlify——它似乎有一个正确的方法,但是我不理解他们的专业级无服务器定价,为什么人们通常是从这里开始。 这个领域正在迅速变化,当看到新的竞争者和新的架构时,我会更新这里的内容。 3无服务器 90% 的情况都很糟糕,但也有 10% 的情况令人惊叹 炒作没问题,但要有理由支撑。无服务器使应用程序易于扩展和维护。我在 7 年前编写的无服务器应用程序仍然在运行,几乎不需要维护,也几乎不需要任何成本。我相信,无服务器可以使个人能够维护大型应用程序,否则将需要一个团队和稳定的收入流。 ...

    2021-04-08 600

联系我们

在线咨询:点击这里给我发消息

QQ交流群:KirinBlog

工作日:8:00-23:00,节假日休息

扫码关注