2021年12月

nginx 的三大作用

nginx 的三大作用分别是:http 静态资源服务器与虚拟主机、反向代理、负载均衡。
为什么要使用 nginx 来做http静态资源服务器呢?因为他性能优越,能更好的支持高并发连接,5万个/每秒。

http 静态资源服务器配置 以及虚拟主机

server {
    listen       80;
    server_name  www.wlmqtc.com;
    location / {
        root   html;
        index  index.html index.htm;
    }
}

通常,使用 nginx 作为 http 静态资源服务器时,只需配置 server 段 的三个地方

  1. listen 监听端口
  2. server_name 域名或者IP
  3. location 下的 root 资源所在目录

注意 可以有多个 server 段 ,所以,nginx 也可以用来做虚拟主机

反向代理配置

upstream myhost {
    server 127.0.0.1:8080;
}
server {
    listen       80;
    server_name  www.wlmqtc.com;
    location / {
        proxy_pass  http://myhost;
    }
}

第一个问题, 什么是反向代理? 反向代理是相对于正向代理而言的。正向代理是面向客户端做代理,反向代理就是与之相反,是面向服务

端做代理。

反向代理时候,需要增加一个 upstream 段 ,并为他取一个任意自定义的名字,例如,我为他取名 myhost ,同时指定一台被代理的主机即可


而后,在 location 中,注释或删除掉 root 和 index,
最后,在 location 中,增加一个配置 proxy_pass http://myhost;

经过以上配置后,当客户端访问 http://www.wlmqtc.com 时,反向代理就会到上游主机中寻找资源(此处就是 127.0.0.1:8080 ),最终将资

源返回到客户端。

负载均衡配置

upstream myhost {
    server 127.0.0.1:10080;
    server 127.0.0.1:10010;
    server 127.0.0.1:10086;
    server 127.0.0.1:10087;
}
server {
    listen       80;
    server_name  www.wlmqtc.com;
    location / {
        proxy_pass  http://myhost;
    }
}

负载均衡很简单,当 upstream 段 内包含多个主机时,将会自动启用默认策略(轮询)。

四种负载均衡策略

名称策略适用
轮询默认策略,依次访问所有主机
weight加权策略,值越大被访问几率越大,默认值=1适合各个主机配置差别较大时适用
ip_hashIP区分策略适合有状态服务,如:session
least_conn最少连接策略适合请求处理时间长短不一的情况

几个参数

参数作用默认值
fail_time_out连接超时时间,与 max_fails 配合使用10s
max_fails最大失败次数,超出将被 down 。1s
backup备用主机,当其他主主机不可用时,访问这个
down手动标记主机宕机

max_fails 补充说明: 在一个 fail_time_out 周期内,发生 max_fails 次失败 ,该主机将被标记为 down ,所有请求将不会转发到此

,只有到了下一周期才会重新启用此主机。

参数可以混用

# 多种参数策略可以混用
upstream myhost {
    ip_hash;
    least_conn; 
    server 127.0.0.1:10080 weight=2;
    server 127.0.0.1:10010 backup;
    server 127.0.0.1:10086 max_fails=3 fail_timeout=20;
    server 127.0.0.1:10087 down;
}

其他注意:

ip_hash 策略是根据客户端 IP 分配主机的,每个客户端访问的主机是固定的,所以有一些需要注意的地方

  • ip_hash 策略不能与 backup 同时使用
  • ip_hash 策略必须手动对主机做宕机,即标记 down

两个问题

openssl 是什么
openssl 就是 加密解密的一套工具包。首先,SSL是一种协议。openssl 全称 Open Secure Sockets Layer,翻译为:开源的安全套接层协议。

RSA 是什么
RSA是一种算法。有一年,在麻省理工学院(MIT),有三位同事联手设计了一种非对称加密算法,这三人分别是:(Ron Rivest)、(Adi Shamir)、(Leonard Adleman),RSA分别取自三人名字的首字母。

几个概念

  1. 公匙 ,任何人都可以下载、查看、使用的秘钥
  2. 私匙 ,只能自己使用,不可泄露的秘钥
  3. 明文 , 加密前的数据(不一定是文字,也可以是图片、视频等)
  4. 密文 , 加密后的数据(同上)

应用场景

数据加密 / 解密
加密过程:公匙 + 明文 = 密文
解密过程:私匙 + 密文 = 明文

数字签名
数字签名的目的不是加密(保密),而是为了防止伪造。
签名过程:私匙 + 明文 = 密文
验签过程:公匙 + 密文 = 明文

Tips:如果 公匙 + 密文 ,能够成功解出明文,则表明数据确实来自持有特定私匙的某人(身份合法),进一步证明接收到的数据是未经篡改的,可信赖的。

简单应用

生成私匙

openssl genrsa -out private.key

从私匙中提取出公匙

openssl rsa -in private.key -out public.key -pubout

加密一份文件

openssl rsautl -encrypt -in hello.txt -inkey public.key -out helloEncrypt.txt -pubin

解密一份文件

openssl rsautl -decrypt -in helloEncrypt.txt -inkey private.key -out helloDecryp.txt

灵魂拷问,啥是UML?UML全拼:Unified Modeling Language 统一建模语言。

UML类图作用

在软件工程中,类图以全局观的方式描述了系统的设计和结构,表明了系统中各部件之间的关系,是系统设计阶段的重要模型

UML类图中的几种关系

泛化(Generalization), 实现(Realization),关联(Association),聚合(Aggregation),组合(Composition),依赖(Dependency)

泛化关系 Generalization

意义:是一种继承关系 class A extends B(){}
图形:空心三角 + 实线 ,三角指向基类

实现关系 Realization

意义:是一个实现关系 class A implements B(){}
图形:空心三角 + 实线,三角指向接口

关联关系 Association

class Person{
  Address address;
}

意义:与对象之间存在的一种 固定关系
图形:箭头 + 实线,箭头指向被关联对象

聚合关系 Aggregation

意义:对象与对象的弱拥有关系,has-a关系,部分与整体的关系,对象各自有自己的生命周期
图形:空心菱形 + 实线 + 箭头,箭头指向被拥有者(部分)
一句话帮助理解:铁打的营盘,流水的兵

组合关系 Composition

意义:对象与对象的强拥有关系,contains-a关系,部分与整体的关系,对象的生命周期一致
图形:实心菱形 + 实线 + 箭头,箭头指向被拥有者,箭头指向被拥有者(部分)
一句话帮助理解:皮之不存,毛将焉附

依赖关系 Dependency

class Person{
  void calcuate(Head head){
    ……
  }
}

意义:对象与对象之间存在的一种 依赖(或者叫使用)关系
图形:箭头 + 虚线,箭头指向被依赖对象
一句话帮助理解:没有你,这件事办不成

其他 常用符号

- == private
# ==protected
~ ==default(包权限)
_ ==static
斜体 ==abstract

为什么要改变 this 的指向?因为 this 的指向太灵活,太模糊,时不时的让丈二和尚摸不着头脑。或者一些其他的原因,需要让 this 指向其他对象,从而可以使用其他对象的方法。

用法示例

function f(x, y){
    console.log(this.x + this.y)
}

// 定义全局变量
var x=3, y =4;

// 在 nums 对象中定义
var nums={
    x:40,
    y:60
}

f(x,y) // 7

f.call(nums,x,y) //100
f.apply(nums,[x,y]) //100

var f2 = f.bind(nums,x,y) //Function
f2() //100

call() 与 apply()

f.call(nums,x,y)
f.apply(nums,[x,y])

将 f 中的 this 指向更改为 nums 对象,此时 x 与 y 的值均是 nums 对象中定义的

call() 与 apply() 的区别
两者的区别,主要在于传参的形式不同,call() 需要一个参数列表,一个一个的写参数,apply()则需要一个数组作为参数

特殊的bind()

f.bind(nums,x,y)() // 100

var f2 = f.bind(nums,x,y) //Function
f2() // 100

bind()的特殊在于他的返回值,是一个 Function ,所以需要使用括号 () 调用一下

案例

理解之后,套用一个经典案例,Math 对象对一个数组求最值

var arr = [1,3,5,7,9]

Math.max.apply(null,arr)
Math.min.apply(null,arr)

引入依赖

pom.xml中引入依赖spring-boot-starter-activemq

生产者(producer) 和 消费者(consumer)都会用到的代码

// 1.获取连接工厂
ConnectionFactory factory = new ActiveMQConnectionFactory("tcp://127.0.0.1:61616");

// 2.创建连接对象
Connnection connection = factory.createConnection();

// 3.启动连接
connection.start();

// 4.创建会话
Session session = connection.createSession(false,Session.AUTO_ACKNOWLEDGE);

// 5.创建消息类型(主题或者队列)
Destination destination = session.createQueue("queue_style");
Destination destination = session.createTopic("Topic_style");

生产者(producer)


// 创建生产者
MessageProducer producer = session.createProducer(destination);

// 创建消息
TextMessage textMessage = session.createTextMessage("来自生产者创建的消息");

// 生产者发送消息
producer.send(textMessage);

消费者(consumer)


// 创建消费者
MessageConsumer consumer = session.createConsumer(destination);

// 为消费者设置监听器
consumer.setMessageListener(new MessageListener() {
            @Override
            public void onMessage(Message message) {
        // 消费者接收的消息对象
                TextMessage textMessage = (TextMessage) message;
            }