0%

Prototype

含义:proto(/ˈproʊtə/)原始, 原型, 原始的

目的:补充JavaScript对于对象的支持,通过protype来实现class中的method

过程:熟悉实例对象<--->构造函数<--->原型 三者之间的关系

1
2
3
4
5
6
7
//构造函数 创建对象
function Dog() {

}
var dog = new Dog();//Person 为构造函数,person为实例对象
dog.name = '柯基';
console.log(dog.name) // 柯基
  • 构造函数通过prototype访问原型(一个类的属性,对象都可以访问)
  • 实例对象通过 _proto_ 访问原型 === 构造函数通过prototype访问原型(原型也有_proto_
  • 实例原型通过constructor访问构造函数(Dog=== Dog.prototype.constructor)

image-20210224154735705

  • 原型遵循向上原则,即找不到就不断向上(prototype)查询
  • 原型因为不停延长形成链,称作原型链,但是 Object.prototype.__proto__ 的值为 null 跟 Object.prototype 没有原型
  • 原型链大概实现了类(Class)以及继承(Extend)的问题,但它并不是复制,是建立一种关联,通过prototype/_proto_ 来访问其他对象的属性和方法,属于委托/借用

Extend

一共分为6种

  • 原型链继承
  • 借用构造函数(经典继承)
  • 组合继承
  • 原型式继承
  • 寄生式继承
  • 寄生组合式继承

原型链继承

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function Parent () {
this.names = ['kevin', 'daisy'];
}
function Child () {}
Child.prototype = new Parent();

var child1 = new Child();

child1.names.push('yayu');

console.log(child1.names); // ["kevin", "daisy", "yayu"]

var child2 = new Child();

console.log(child2.names); // ["kevin", "daisy", "yayu"]

问题:

  • 属性被所有child共享
  • 创建child实例时,不能向parent传参

借用构造函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function Parent (name) {
this.name = name;
}

function Child (name) {
Parent.call(this, name);
}

var child1 = new Child('kevin');

console.log(child1.name); // kevin

var child2 = new Child('daisy');

console.log(child2.name); // daisy

有点:

  • 避免引用类型的属性被所有实例共享
  • 可以在Child中间parent传参

缺点:

  • 方法在构造函数中定义,每次创建势力都会创建一遍方法

组合继承

以上两种方法的组合,为最常用的继承方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
function Parent (name) {
this.name = name;
this.colors = ['red', 'blue', 'green'];
}

Parent.prototype.getName = function () {
console.log(this.name)
}

function Child (name, age) {
Parent.call(this, name);
this.age = age;
}

Child.prototype = new Parent();
Child.prototype.constructor = Child;

var child1 = new Child('kevin', '18');

child1.colors.push('black');
console.log(child1.name); // kevin
console.log(child1.age); // 18
console.log(child1.colors); // ["red", "blue", "green", "black"]

var child2 = new Child('daisy', '20');

console.log(child2.name); // daisy
console.log(child2.age); // 20
console.log(child2.colors); // ["red", "blue", "green"]

link:mysql-docker

支持标签

快速手册

什么是 MySQL?

MySQL 是最受欢迎的,开源的数据库. 凭借被验证过的性能表现,可靠性,易用性, MySQL已经成为基于web的应用程序的 主要选择,包括完整得个人项目和网站项目(电子上午,信息服务),也包括优秀的Facebook Facebook, Twitter, YouTube, Yahoo!

如何使用mysql image

创建 mysql 服务实例

启动 MySQL 比较简单:

1
$ docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag
  • some-mysql 容器名称
  • my-secret-pw 是root账户的密码
  • tag 是mysql的版本

通过mysql命令行连接mysql

以下命令可以启动mysql容器并运行终端,执行SQL语句

1
$ docker run -it --network some-network --rm mysql mysql -hsome-mysql -uexample-user -p
  • some-mysql 容器名称
  • some-network 连接网络(方便容器间访问)

也可以直接运行客户端,访问远程数据库

1
$ docker run -it --rm mysql mysql -hsome.mysql.host -usome-mysql-user -p

更多命令请访问 MySQL documentation

使用docker stack 或docker-compose部署

示例stack.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# Use root/example as user/password credentials
version: '3.1'
services:

db:
image: mysql
command: --default-authentication-plugin=mysql_native_password
restart: always
environment:
MYSQL_ROOT_PASSWORD: example

adminer:
image: adminer
restart: always
ports:
- 8080:8080
  • docker stack deploy -c stack.yml mysql
  • docker-compose -f stack.yml up

启动后, 访问 http://swarm-ip:8080, http://localhost:8080, or http://host-ip:8080

shell访问查看 MySQL 日志

使用 docker exec 可以让你在容器内执行命令,命令如下

1
$ docker exec -it some-mysql bash

容器日志:

1
$ docker logs some-mysql

自定义 MySQL 配置文件

mysql默认配置文件在 /etc/mysql/my.cnf, 也可能指定了额外文件如: /etc/mysql/conf.d or /etc/mysql/mysql.conf.d. 请检查mysqlimage本身的相关文件和目录以了解更多信息

如果 /my/custom/config-file.cnf 是你自定义的文件未知和名字, 你可以这样启动你的mysql 容器

1
$ docker run --name some-mysql -v /my/custom:/etc/mysql/conf.d -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag

你会启动一个用你自定义配置 /etc/mysql/my.cnf and /etc/mysql/conf.d/config-file.cnf, 的mysql容器

不使用cnf 文件配置

很多配置都可以传给 mysqld. 使你自定义容器而不需要 cnf 文件. 如当你想改变默认编码和排序规则,使用 UTF-8 (utf8mb4) 只需要执行如下命令:

1
$ docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci

如果你想看到所有的配置项,只需要执行:

1
$ docker run -it --rm mysql:tag --verbose --help

环境变量

docker run 时,可以一个或多个参数进行配置. 不过需要注意,如果使用已经包含数据库的数据目录启动容器,以下变量不会产生影响,在启动时,任何预先存在的数据库都保持不变,任何之前存在的数据库在容器启动时将保持不变.

MYSQL_ROOT_PASSWORD

该变量是必须的,是root账户的密码.

MYSQL_DATABASE

该变量可选,允许在启动时,指定数据库的名称. 如果提供了用户名/密码,用户会被赋予超级权限.

MYSQL_USER, MYSQL_PASSWORD

可选变量,用于创建新用户和密码,用户将获得超级管理员权限,两个参数都是必须的.

注意:不需要使用该机制来创建root超级用户,默认使用 MYSQL_ROOT_PASSWORD 来创建密码

MYSQL_ALLOW_EMPTY_PASSWORD

可选变量,设置非空值(如yes),允许root用户无密码启动容器. 注意: 除非你知道你在做什么,否则不建议设置为 yes ,因为这将使mysql实例完全不受保护,允许所有人获得完全的超级用户权限.

MYSQL_RANDOM_ROOT_PASSWORD

可选变量,设置非空值(如yes),使用pwgen , 为root用户随机生成密码 .密码将被打印.

MYSQL_ONETIME_PASSWORD

设置用户 初始化完成后过期,在首次登录时候强制修改密码. 任何非空值将激活这个配置,注意:仅支持5.6+版本,以下版本会报错

MYSQL_INITDB_SKIP_TZINFO

默认,entrypoint脚本自动加载CONVERT_TZ()函数需要的时区数据,如果不需要,任何非空值都将禁用时区加载

Docker Secrets

通过环境变量传递敏感信息,还有另一种方法, _FILE 可以附加到前面列的环境变量,使得可以从文件中的变量初始化脚本,特别是,这可以用于存在/run/secrets/<secret_name>中的docker screts从加载密码, 如 :

1
$ docker run --name some-mysql -e MYSQL_ROOT_PASSWORD_FILE=/run/secrets/mysql-root -d mysql:tag

目前仅支持: MYSQL_ROOT_PASSWORD, MYSQL_ROOT_HOST, MYSQL_DATABASE, MYSQL_USER, 和MYSQL_PASSWORD.

初始化新实例

刚启动容器,指定名字的新数据库会被创建,并且根据提供的变量初始化. 此外,它将执行扩展名为.sh, .sql.sql.gz/docker-entrypoint-initdb.d文件夹中).文件将按照字幕顺序执行. 你可以轻松使用dump备份填充,. 默认情况下,sql文件将被保存在 MYSQL_DATABASE 指定的数据库中.

Caveats//告诫

数据存储在哪里

重要内容:有几种方式在容器运行时存储数据. 我们推荐 mysql 用户熟悉可用的选项,包括:

  • 让docker使用自己的内部volume 将数据库文件写入主机系统上的磁盘(而不在容器内)从而管理数据库数据的存储。这也是默认的配置,也非常简单透明。缺点是相比直接部署找文件困难.
  • 在主机上创建一个数据目录,并将其装载到容器内部的一个目录中,使得数据库文件放置在主机已知的位置上,更轻松访问文件,缺点是需要确保目录存在,且有权限和安全机制

Docker 文档是理解不同存储选项和变量的最好起步,并且有很多博客论坛讨论并提供建议,我们将简单展示基本过程:

  1. 创建文件夹在主机如 /my/own/datadir.

  2. 启动 mysql 容器

    1
    $ docker run --name some-mysql -v /my/own/datadir:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag

    -v /my/own/datadir:/var/lib/mysql/my/own/datadir 目录从主机装入容器中作为 /var/lib/mysql 默认不传-v情况下,mysql将写入其他数据文件.

直到初始化完成才有连接

如果容器启动没有初始化数据库,则创建默认数据库. 初始化完成之前不会接受传入连接. 在使用自动化工具如 docker-compose同时启动多个容器时,这可能会导致问题.

如果应用尝试连接不提供服务的mysql,需要继续重试等待连接成功. 官方示例, 详见 WordPress or Bonita.

现用数据库使用

如果在一个有mysql数据目录的volume启动mqsql,应省略 $MYSQL_ROOT_PASSWORD命令; 及时填写也不会生效, 且不会更改预先存在的数据库.

以任意用户身份运行

如果你正确设置了目录权限,或者你需要使用特定的uid/gid运行mysqld,则可以通过 --user 设为任意值(root/0外)来实现所需的权限/配置:

1
2
3
4
$ mkdir data
$ ls -lnd data
drwxr-xr-x 2 1000 1000 4096 Aug 27 15:54 data
$ docker run -v "$PWD/data":/var/lib/mysql --user 1000:1000 --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag

创建备份

大多数工具都会正常工作,尽管他们的使用在某些情况下可能有点复杂, 以确保可以访问mysqld服务器,确保这一点的一个简单方法是使用 docker exec 并从同一容器运行工具,如:

1
$ docker exec some-mysql sh -c 'exec mysqldump --all-databases -uroot -p"$MYSQL_ROOT_PASSWORD"' > /some/path/on/your/host/all-databases.sql

从备份还原数据

1
$ docker exec -i some-mysql sh -c 'exec mysql -uroot -p"$MYSQL_ROOT_PASSWORD"' < /some/path/on/your/host/all-databases.sqlwith any relevant licenses for all software contained within.1

柯里化是一种将使用多个参数的一个函数转换成一系列使用一个参数的函数的技术

1
2
3
4
5
6
7
8
9
10
function add(a, b) {
return a + b;
}

// 执行 add 函数,一次传入两个参数即可
add(1, 2) // 3

// 假设有一个 curry 函数可以做到柯里化
var addCurry = curry(add);
addCurry(1)(2) // 3

前置知识:JavaScript是静态作用域

闭包:访问自由变量的函数

1
2
3
4
5
6
7
var a = 1;//既不是foo的局部变量,也不是foo函数的参数,a为自由变量

function foo() {
console.log(a);
}

foo();//1

即使上下文被销毁,它仍然存在,因为在作用域链上被引用了,是js的一个特性,目前如PHP,Java不会原生支持

面试题

常见的新手面试题,我遇到过好几次(作用域+闭包考点)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
var data = [];

for (var i = 0; i < 3; i++) {
data[i] = function () {
console.log(i);
};
}

data[0]();
data[1]();
data[2]();


//closure
var data = [];

for (var i = 0; i < 3; i++) {
data[i] = (function (i) {
return function(){
console.log(i);
}
})(i);
}

data[0]();//不用找global的i
data[1]();
data[2]();

1.install remote ssh in vscode

2.click remote explorer and select ssh targets

3.click remote ssh configure or press F1 and input remote-ssh:Open configuration file

4.selete path ~/.ssh/config,and modify config file

if you dont have rsa ,please generate keys before

1
2
3
4
5
6
//optional
ssh-keygen
# passphrase can be empty and then generate keys in `~/.ssh`
# put *.pub (public key) to your server (~/.ssh/) and excute `cat id_rsa.pub >> authorized_keys` to merge Previous file
# now rsa keys are ready

1
2
3
4
5
6
7
Host alias
HostName 8.888.88.8
User root
IdentityFile ~/.ssh/id_rsa
RSAAuthentication yes
PubkeyAuthentication yes
PasswordAuthentication no
  • Host alias–>your remote server name
  • hostName–>server ip
  • User–>login username
  • IdentityFile–>private key path
  • RSAAuthentication–>optional
  • PubkeyAuthentication–>optional
  • PasswordAuthentication–>no password login

5.login without password ready

What

ECMAscript 6 原生提供了 Promise 对象。

Promise 对象代表了未来将要发生的事件,用来传递异步操作的消息。

Promise 对象有以下两个特点:

1、对象的状态不受外界影响。Promise 对象代表一个异步操作,有三种状态:

  • pending: 初始状态,不是成功或失败状态。
  • fulfilled: 意味着操作成功完成。
  • rejected: 意味着操作失败。

只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。这也是 Promise 这个名字的由来,它的英语意思就是「承诺」,表示其他手段无法改变。

2、一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise 对象的状态改变,只有两种可能:从 Pending 变为 Resolved 和从 Pending 变为 Rejected。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果。就算改变已经发生了,你再对 Promise 对象添加回调函数,也会立即得到这个结果。这与事件(Event)完全不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的。

1
2
3
4
var promise = new Promise(function(resolve, reject) {
// 异步处理
// 处理结束后、调用resolve 或 reject
});

以上来自:菜鸟https://www.runoob.com/w3cnote/javascript-promise-object.html

Why

因为在2020年01月07日有一篇文章讲了使用promise实现延时队列的一道面试题,因为之前写业务没有用到过所以一直以为用处不大,但今天对接阿里的录音文件识别转文字的接口中,示例代码是一个setInterval轮询得到结果的一种方式,但是他带来了一个很严重的问题

!!没有办法返回前端转文字的结果!!

大概代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
//url:https://help.aliyun.com/document_detail/94242.html?spm=a2c4g.11174283.6.601.15eb7275a8rq00
// 这段代码会异步执行,可以得到结果,但是直接用这个代码返回给前端
client.submitTask(taskParams, options).then((response) => {
console.log(response);
// 服务端响应信息的状态描述StatusText。
var statusText = response.StatusText;
if (statusText != 'SUCCESS') {
console.log('录音文件识别请求响应失败!')
return;
}
console.log('录音文件识别请求响应成功!');
// 获取录音文件识别请求任务的TaskId,以供识别结果查询使用。
var taskId = response.TaskId;
/**
* 以TaskId为查询参数,提交识别结果查询请求。
* 以轮询的方式进行识别结果的查询,直到服务端返回的状态描述为"SUCCESS"、SUCCESS_WITH_NO_VALID_FRAGMENT,
* 或者为错误描述,则结束轮询。
*/
var taskIdParams = {
TaskId : taskId
};
var timer = setInterval(() => {
client.getTaskResult(taskIdParams).then((response) => {
console.log('识别结果查询响应:');
console.log(response);
var statusText = response.StatusText;
if (statusText == 'RUNNING' || statusText == 'QUEUEING') {
// 继续轮询,注意间隔周期。
}
else {
if (statusText == 'SUCCESS' || statusText == 'SUCCESS_WITH_NO_VALID_FRAGMENT') {
console.log('录音文件识别成功:');
var sentences = response.Result;
console.log(sentences);
}
else {
console.log('录音文件识别失败!');
}
// 退出轮询
clearInterval(timer);
}
}).catch((error) => {
console.error(error);
// 异常情况,退出轮询。
clearInterval(timer);
});
}, 10000);
}).catch((error) => {
console.error(error);
});
}

How

使用promise进行包裹,等到promise内部的函数取到了结果在返回

1
2
3
4
5
6
7
8
if (statusText == 'SUCCESS' || statusText == 'SUCCESS_WITH_NO_VALID_FRAGMENT') {
console.log('录音文件识别成功:');
var sentences = response.Result;
console.log(sentences);
//这里新增resolve
} else {
console.log('录音文件识别失败!');
}

外层通过如下代码实现

1
2
3
4
var promise = new Promise(function(resolve, reject) {
// 异步处理
// 处理结束后、调用resolve 或 reject
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
async function getWords() {
return new Promise((resolve, reject) => {
client
.submitTask(taskParams, options)
.then(response => {
console.log(response);
// 服务端响应信息的状态描述StatusText。
const statusText = response.StatusText;
if (statusText != 'SUCCESS') {
console.log('录音文件识别请求响应失败!');
}
console.log('录音文件识别请求响应成功!');
// 获取录音文件识别请求任务的TaskId,以供识别结果查询使用。
const taskId = response.TaskId;
/**
* 以TaskId为查询参数,提交识别结果查询请求。
* 以轮询的方式进行识别结果的查询,直到服务端返回的状态描述为"SUCCESS"、SUCCESS_WITH_NO_VALID_FRAGMENT,
* 或者为错误描述,则结束轮询。
*/
const taskIdParams = {
TaskId: taskId,
};

const timer = setInterval(() => {
client
.getTaskResult(taskIdParams)
.then(response => {
console.log('识别结果查询响应:');
console.log(response);
const statusText = response.StatusText;
if (statusText == 'RUNNING' || statusText == 'QUEUEING') {
// 继续轮询,注意间隔周期。
} else {
if (
statusText == 'SUCCESS' ||
statusText == 'SUCCESS_WITH_NO_VALID_FRAGMENT'
) {
console.log('录音文件识别成功:');
let sentences = '';
for (const s of response.Result.Sentences) {
sentences += s.Text;
}
console.log(response.Result);
resolve(sentences);//**重点**//
// return sentences;
} else {
console.log('录音文件识别失败!');
}
// 退出轮询
clearInterval(timer);
}
})
.catch(error => {
console.error(error);
// 异常情况,退出轮询。
clearInterval(timer);
});
}, 10000);
})
.catch(error => {
console.error(error);
});
});
}
return await getWords();//返回前端,翻译结果

另外记录一件事情,左侧单元图标地址:https://fontawesome.com/v4.7.0/icons/

what

Jupiter = Julia + Python + R

Jupyter notebook(http://jupyter.org/) 是一种 Web 应用,能让用户将说明文本、数学方程、代码和可视化内容全部组合到一个易于共享的文档中。

why

  • 将代码和文档结合在一起,更直观的编写人工智能,大数据的代码
  • 分块运行
  • 直接运行shell不需要切换环境
  • so on

how

  1. Download images
1
2
$docker pull jupyter jupyter/scipy-notebook:latest
$docker run -itd --rm -p 1000:8888 -e JUPYTER_ENABLE_LAB=yes -v /home/zehai/jupyter:/home/jovyan/work --name jupyter jupyter/scipy-notebook:latest
  1. docker logs -f container’s ID and find token
1
2
3
4
5
To access the notebook, open this file in a browser:
file:///home/jovyan/.local/share/jupyter/runtime/nbserver-6-open.html
Or copy and paste one of these URLs:
http://896bb1e66101:8888/?token=fda8565a9b5cd5b8c621b45322ee72f716fd7ddea089fb51
or http://127.0.0.1:8888/?token=fda8565a9b5cd5b8c621b45322ee72f716fd7ddea089fb51
  1. more info visit official docs
  2. enjoy (pics powered by cherevero)

3318a2fadaf085f2bee7f0de3b42971c.png

what

To solve some problems

  • some web only use markdown and can’t upload pictures,such as v2ex.com
  • some pics you don’t want to give it to others for long time,such as your interesting story
  • give your blog’s can speed when download bigger pics
  • and so on

Picture Bed can offer you a excellent platform to share your pictures and protect them, however it has a problem that you need a server to run the service,even though you can use 七牛云,alioss,weibo for free.

why

Chevereto is aim what I find

  • dockerhub has chevereto images
  • Combined with ShareX (only for windows😢),chevereto can write markdown essay easily
  • it has api ,you can make it stronger
  • Chevereto Free v1.2.2 now
  • Something others you can discover by yourself

how

Chevereto is a php project , I use docker to run it

1
2
3
4
5
6
7
8
9
10
docker pull nmtan/chevereto:latest

//use docker-compose.yml(next block)

// or docker run
docker run -it --name chevereto -d -p 8000:80 -v "/home/xxx/images":/var/www/html/images -e "CHEVERETO_DB_HOST=127.0.0.1" -e "CHEVERETO_DB_USERNAME=root" -e "CHEVERETO_DB_PASSWORD=rootpass" -e "CHEVERETO_DB_NAME=chevereto" -e "CHEVERETO_DB_PREFIX=chv_" nmtan/chevereto
//-v save photos in server instead of container
//-e mysql:5.7.31 host,username,password,db_name(db must exist first)
//open chrome and input 127.0.0.1:8000

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
//this is docker-compose.yml
version: '3'

services:
db:
image: mariadb
volumes:
- ./database:/var/lib/mysql:rw
restart: always
networks:
- private
environment:
MYSQL_ROOT_PASSWORD: xxxxx
MYSQL_DATABASE: xxxxx
MYSQL_USER: xxxxx
MYSQL_PASSWORD: xxxxx

chevereto:
depends_on:
- db
image: nmtan/chevereto
restart: always
networks:
- private
environment:
CHEVERETO_DB_HOST: db
CHEVERETO_DB_USERNAME: xxxxxx
CHEVERETO_DB_PASSWORD: xxxxx
CHEVERETO_DB_NAME: xxxxx
CHEVERETO_DB_PREFIX: chv_
volumes:
- ./images:/var/www/html/images:rw
- ./php.ini:/usr/local/etc/php/php.ini:ro
ports:
- 8080:80

networks:
private:


// start command
nohup docker-compose up &> run.log &
disown

You maybe run into a stone wall when you first visit 127.0.0.1:8000

  • Before you can use docker exec -it chevereto bash into container /var/www/html

  • no permission write phots to /home/xxx/images,you can use chmod -R 777 /home/xxx/images

  • no permission update chevereto from 1.1.4 to1.2.2 ,no update possible: /app/install/update/temp/ path,that is no temp folder in /app/install/update/ under version 1.2.0,you can mkdir temp and then chmod -R 777 ./temp and then refresh the webpage ,the prics bed will update successfully

So , you can use ip address to visit your chevereto . However , we usually use domain name such as example.com to visit web, a https isn ecessary as well

  • 1.Use aliyun to apply a free ssl license for a domain name such as pics.example.com
  • 2.Download pem and keys to your server and put it in nginx conf folder
  • 3.Use the conf as follows
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
server {
listen 80;
server_name pics.example.com;
return 301 https://pics.example.com$request_uri;
}

server {
listen 443 ssl;
server_name pics.example.com;
gzip on;

ssl_certificate cert/xxxxxx9_pics.example.com.pem; # pem's filename
ssl_certificate_key cert/xxxxxx9_pics.example.com.key;# key's filename

location / {
proxy_redirect off;
proxy_pass http://dockername;

proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Ssl on;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Frame-Options SAMEORIGIN;

client_max_body_size 100m;
client_body_buffer_size 128k;

proxy_buffer_size 4k;
proxy_buffers 4 32k;
proxy_busy_buffers_size 64k;
proxy_temp_file_write_size 64k;
}
}
    1. And then you can visit https://pics.example.com

That‘s my story that building pics bed ,and hope to help you.

2020-09-28 append

use picgo,upload pictures in typora to chevereto

  1. GitHub download picgo,mac use .dmp,and then install it

  2. open 插件设置,search chevereto and install chevereto 1.0.0

  3. Open 图床设置>Chevereto Uploader and put in params,

    Url is your upload service ip/domain

    Key is chevereto api in Dashboard>Settings>API>API v1 key

    param is not in use now

1
2
Url:https://example.com/api/1/upload
Key:xxx
  1. Click 确定 and 设为默认图库
  2. make sure server is on PicGo设置>设置Server>点击设置,if it is on ,noting should be done

and then we modify config in typaro

  1. Open Typora and open ‘preferences>Images`
  2. Choose Upload images in when Insert and check apply above rules to local images and apply above rules to online images in option, and I suggest you check both of them to approve all pics managed by chevereto
  3. Choose PicGo.app in images Uploader and click Test Uploader to test your upload pictures automatically

for more information ,youcan visit

thanks

what

MQ-message queue

三足鼎立

rocketmq​​ -Made by Java 吞吐量高一些 阿里中间件

rabbitmq -Made by Erlang

Kafka-

以后有更多的了解再补充性能/功能差距

why

功能:解耦(双方通过mq交互)、异步、削峰

应用:

  • 阿里双11

问题:

  • 处理好新增的复杂性
  • 处理好系统可用性

how

之所以选择rabbitmq是因为rocketmq的nameserver所需要的内存太大了,更何况boker,对于1C2G的乞丐机器来说根本跑不起来

1.docker run

Because of rocketmq need more than

1
2
3
4
5
6
7
8
9
docker pull rabbitmq:management

docker run -dit --name rabbitmq -e RABBITMQ_DEFAULT_USER=admin -e RABBITMQ_DEFAULT_PASS=admin -p 15672:15672 -p 5672:5672 rabbitmq:management

--name containername
-e RABBITMQ_DEFAULT_USER 参数用户名,密码同理
-p 端口映射,主机:容器,15672-UI,5672-service
rabbitmq:management image's name

2.Usage

1.open chrome and input ‘localhost:15672’ or ‘192.168.1.1:15672’ then you can touch rabbitmq UI

Overview–the queued msg, msg rate in your server, some global counts, your nodes stats (if u use the above method,you only see one node in the screen ),you also can build a cluster with more nodes

Connections–

Channels–

Exchanges–direct,fanout,headers,match,trace,topic

Queses–

Admin–users management with passport && permission

2.use 5672 in your code

1
2
3
4
5
6
7
8
amqp.connect({
protocol: 'amqp',
hostname: 'example.com',//localhost
port: '5672',
username: 'admin',
password: 'xxx',
vhost: '/',//important
})

more in official docs–> I’m doc

or some blogs–>I’m blog

or my GitHub–>click here