0%

1、域名解析

实质:
将域名正向解析到可访问的 ip,或将 ip 反向解析回域名

2、实现方式

  • DNS 服务器
  • Nginx/hosts 文件

优略比较

DNS Nginx/hosts
共同点 1、配置域名,映射 ip
2、要求:连接的各服务器能ping通 (此内容也导致第3点)
3、不能内网穿透 (通过dns进行google外网访问行不通)
实现方法 1、服务端安装bind程序
2、客户端中dns配置服务端地址
1、安装nginx(客户端服务端皆可)
2、客户端hosts文件配置nginx服务器ip和域名映射关系
其他 需解决代理后不能访问其他网址问题:
解决方法:添加dns配置114.114.114.114
可以用其他功能:
1、静态资源映射
2、负载均衡
3、网关代理
4、。。。

3、游戏私服部署方案

要求

  • 将 0101.90yx.top 映射到 192.168.1.10 服务器上

3.1、内网部署

  1. 在 192.168.1.8 安装 dns 服务器
  2. 将 192.168.1.10 映射到 0101.90yx.top 域名上
  3. 将手机与服务器连接到相同网络
  4. 将手机网络的网关手动修改为:192.168.1.8、114.114.114.114
  5. 访问测试

3.2、外网部署

  1. 在外网服务器安装 bind 程序:120.79.79.145(阿里云服务器)
  2. 开放 120.79.79.145 的 53 端口
  3. 将 120.79.79.145 映射到 0101.90yx.top 域名上
  4. 安装 nginx 程序,添加网关,将 120.79.79.145 的请求转到二级域名 game.foxhello.cn
  5. 通过 frps 将内网地址 192.168.1.10 的服务挂到 game.foxhello.cn 上
  6. 将手机网络的网关手动修改为:120.79.79.145、114.114.114.114
  7. 访问测试

搭建步骤

  1. 安装 bind 服务(DNS 服务器)
    yum -y install bind*
  2. 查看所有服务,设置开机运行 named 服务
  • 查看所有服务
    systemctl list-unit-files
  • 设置开机运行 named 服务
    systemctl enable named.service
  1. 修改配置文件
    vim /etc/named.conf
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

options {
listen-on port 53 { any; };
listen-on-v6 port 53 { ::1; };
directory "/var/named";
dump-file "/var/named/data/cache_dump.db";
statistics-file "/var/named/data/named_stats.txt";
memstatistics-file "/var/named/data/named_mem_stats.txt";
recursing-file "/var/named/data/named.recursing";
secroots-file "/var/named/data/named.secroots";
allow-query { any; };

/*
- If you are building an AUTHORITATIVE DNS server, do NOT enable recursion.
- If you are building a RECURSIVE (caching) DNS server, you need to enable
recursion.
- If your recursive DNS server has a public IP address, you MUST enable access
control to limit queries to your legitimate users. Failing to do so will
cause your server to become part of large scale DNS amplification
attacks. Implementing BCP38 within your network would greatly
reduce such attack surface
*/
recursion yes;

dnssec-enable no;
dnssec-validation no;

/* Path to ISC DLV key */
bindkeys-file "/etc/named.root.key";

managed-keys-directory "/var/named/dynamic";

pid-file "/run/named/named.pid";
session-keyfile "/run/named/session.key";
};

logging {
channel default_debug {
file "data/named.run";
severity dynamic;
};
};

zone "." IN {
type hint;
file "named.ca";
};

include "/etc/named.rfc1912.zones";
include "/etc/named.root.key";

  1. 重启 named 服务
    systemctl restart named.service

  2. 设置防火墙规划,开放 53 端口

1
2
3
4
5
6
7
8
9
10
11
12
13
>systemctl stop firewalld.service  #关闭firewalld防火墙

>yum install iptables-services #安装iptables防火墙

>iptables -I INPUT -p tcp --dport 53 -j ACCEPT #放行TCP协议的53端口

>iptables -I INPUT -p udp --dport 53 -j ACCEPT #放行UDP协议的53端口

>systemctl enable iptables #允许防火墙开机运行

//查看规划是否生效

>iptables -L

显示已生效,然后保存防火墙配置,使其以后都生效:

>/sbin/service iptables save

  1. 查看 DNS 的配置文件目录
    rpm -lq bind
  • /etc/named.conf DNS 服务器属性
  • /etc/named.rfc1912.zones 区域属性
  • /var/named/data 存放区域文件的目录,用于定义域名对应的内网 IP 和相关配置
  1. 修改域名配置文件
    vi /etc/named.rfc1912.zones
    在尾部添加 test.com 的域名
1
2
3
4
5
6
7
8

zone "test.com" IN {
type master;
file "test.com.zone";
allow-update { none; };
};


  1. 添加 DNS 解析配置文件
    vi /var/named/test.com.zone
    文件内容如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
$TTL 1D
@ IN SOA test.com. rname.invalid. (
0 ; serial
1D ; refresh
1H ; retry
1W ; expire
3H ) ; minimum
NS @
A 127.0.0.1
AAAA ::1
NS ns.test.com.
ns IN A 192.168.92.82
www IN A 192.168.92.82
email IN A 192.168.92.82 # 服务器地址

检查配置是否有错误:
named-checkzone oa.com /var/named/test.com.zone

如图提示无错误,重启 DNS 服务器
systemctl restart named.service

  1. 测试

参考地址

xxl-job && datax-web 源码内容

问题

日志相关

  • 日志文件是如何生成 ?
    通过生成日志文件,追加日志。见附录 日志流程图
  • 日志格式使用的是 logback.xml ?
    否,代码写死,见 NtiJobLogger.java
  • 读取日志时如何从某行开始读取 ?
    通过 io 流包装类,LineNumberReader.java

停止线程

  • 直接使用 interrupt 能时线程停止 ?
    能停止线程,process.waitFor()触发报中断异常,但是 datax 任务会执行任务结束
  • 如何获取 Process process = Runtime.getRuntime().exec(command)的进程 id
    通过 java.lang.UNIXProcess 获取
  • 进程 id 如何返回管理平台
    通过 ProcessCallbackThread 单独线程处理、平台提供 processCallback 接口进行回调

xxl-job 交互流程

  • 如何选择执行器 ?
    通过 TriggerParam 参数调用 Executor 的实现类 ExecutorBizImpl 的 run 方法进行判断,类型见 GlueTypeEnum
  • 运行参数是如何传递的 ?
    通过 TriggerParam 参数 executorParams\replaceParam\jvmParam\replaceParamType\extendedParam 等属性进行传递

netty 相关

  • demo 程序
  • 封包解包&&粘包 ?
    将消息分为消息头和消息体,消息头中包含表示信息的总长度(或者消息体长度)的字段
  • 交互时:客户端发送服务端 / 服务端发送客户端 封包解包 区别 ?
    TODO

附录

1、日志流程图

2、NtiJobLogger.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
/**
* append log
*
* @param callInfo
* @param appendLog
*/
private static void logDetail(StackTraceElement callInfo, String appendLog) {
// "yyyy-MM-dd HH:mm:ss [ClassName]-[MethodName]-[LineNumber]-[ThreadName] log";
StringBuffer stringBuffer = new StringBuffer();
stringBuffer.append(DateUtil.formatDateTime(new Date())).append(" ")
.append("[" + callInfo.getClassName() + "#" + callInfo.getMethodName() + "]").append("-")
.append("[" + callInfo.getLineNumber() + "]").append("-")
.append("[" + Thread.currentThread().getName() + "]").append(" ")
.append(appendLog != null ? appendLog : "");
String formatAppendLog = stringBuffer.toString();

// appendlog
String logFileName = NtiJobFileAppender.contextHolder.get();
if (logFileName != null && logFileName.trim().length() > 0) {
NtiJobFileAppender.appendLog(logFileName, formatAppendLog);
} else {
logger.info(">>>>>>>>>>> {}", formatAppendLog);
}
}

3、文件按行读取

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
LineNumberReader reader = null;
try {
//reader = new LineNumberReader(new FileReader(logFile));
reader = new LineNumberReader(new InputStreamReader(new FileInputStream(logFile), "utf-8"));
String line = null;

while ((line = reader.readLine()) != null) {
// [from, to], start as 1
toLineNum = reader.getLineNumber();
if (toLineNum >= fromLineNum) {
logContentBuffer.append(line).append("\n");
}
}
} catch (IOException e) {
logger.error(e.getMessage(), e);
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
logger.error(e.getMessage(), e);
}
}
}

4、读取进程 id

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
public static String getProcessId(Process process) {
long pid = -1;
Field field;
if (Platform.isWindows()) {
try {
field = process.getClass().getDeclaredField("handle");
field.setAccessible(true);
pid = Kernel32.INSTANCE.GetProcessId((Long) field.get(process));
} catch (Exception ex) {
logger.error("get process id for windows error {0}", ex);
}
} else if (Platform.isLinux() || Platform.isAIX()) {
try {
Class<?> clazz = Class.forName("java.lang.UNIXProcess");
field = clazz.getDeclaredField("pid");
field.setAccessible(true);
pid = (Integer) field.get(process);
} catch (Throwable e) {
logger.error("get process id for unix error {0}", e);
}
}
return String.valueOf(pid);
}


<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna</artifactId>
<version>4.1.0</version>
</dependency>

import com.sun.jna.Library;
import com.sun.jna.Native;

/**
* Kernel32
*
* @author jingwk
* @version 1.0
* @since 2019/11/09
*/

public interface Kernel32 extends Library {
Kernel32 INSTANCE = (Kernel32) Native.loadLibrary("kernel32", Kernel32.class);

long GetProcessId(Long hProcess);
}

5、Executor 执行器类型

1
2
3
4
5
6
7
8
9
10
11
12
BEAN("BEAN", false, null, null),
GLUE_GROOVY("GLUE(Java)", false, null, null),
GLUE_SHELL("GLUE(Shell)", true, "bash", ".sh"),
GLUE_PYTHON("GLUE(Python)", true, "python", ".py"),
GLUE_PHP("GLUE(PHP)", true, "php", ".php"),
GLUE_NODEJS("GLUE(Nodejs)", true, "node", ".js"),
GLUE_POWERSHELL("GLUE(PowerShell)", true, "powershell", ".ps1");

private String desc;
private boolean isScript;
private String cmd;
private String suffix;

实现类

  • MethodJobHandler: bean 模式使用
  • GlueJobHandler: groovy 使用
  • ScriptJobHandler: isScript=true 使用

密码访问

https://zhuanlan.zhihu.com/p/111228599

1. 安装 htpasswd 工具

1
2
3
4
5
6
7
8
9
yum install httpd-tools -y

[sandu@bogon conf]$ sudo mkdir passwd
[sandu@bogon conf]$ sudo htpasswd -c passwd/passwd sandu
New password:
Re-type new password:
Adding password for user sandu
[sandu@bogon conf]$ cat passwd/passwd
sandu:$apr1$J5Sg0fQD$KDM3Oypj8Wf9477PHDIzA0

修改 nginx 配置文件

1
2
3
4
5
6
7
8
9
10
server {
listen 80;
server_name localhost;
.......
#新增下面两行
auth_basic "Please input password"; #这里是验证时的提示信息
auth_basic_user_file /usr/local/openresty/nginx/conf/passwd/passwd; # 这里是密码文件,可以填写绝对路径
location /{
.......
}

问题定位

结合日志进行定位

1
2
#全局错误日志定义类型,[ debug | info | notice | warn | error | crit ]
error_log /var/log/nginx/error.log info;

负载均衡

1
2
3
4
5
6
7
8
9
10
11
12
13
upstream myserver {
server 192.168.24.200:8080;
server 192.168.24.205:8080;
}
server {
....
location / {
proxy_pass myserver;#请求转向mysvr 定义的服务器列表
proxy_redirect off;
proxy_set_header X-Real-IP $remote_addr;
#后端的Web服务器可以通过X-Forwarded-For获取用户真实IP
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}

1、热备:如果你有 2 台服务器,当一台服务器发生事故时,才启用第二台服务器给提供服务。服务器处理请求的顺序:AAAAAA 突然 A 挂啦,BBBBBBBBBBBBBB…..

1
2
3
4
upstream myserver {
server http://192.168.24.200:8080;
server http://192.168.24.205:8080; backup; #热备
}

2、轮询:nginx 默认权重就是轮询,都默认为 1,服务器处理请求的顺序:ABABABABAB….

1
2
3
4
upstream myserver {
server 192.168.24.200:8080;
server 192.168.24.205:8080;
}

3、加权轮询:跟据配置的权重的大小而分发给不同服务器不同数量的请求。如果不设置,则默认为 1。下面服务器的请求顺序为:ABBABBABBABBABB….

1
2
3
4
upstream myserver {
server 192.168.24.200:8080 weight=1;
server 192.168.24.205:8080 weight=2;
}

4.ip_hash:nginx 会让相同的客户端 ip 请求相同的服务器。

1
2
3
4
5
upstream myserver {
server 192.168.24.200:8080
server 192.168.24.205:8080
ip_hash;
}

5.关于 nginx 负载均衡配置的几个状态参数讲解。
down,表示当前的 server 暂时不参与负载均衡。
backup,预留的备份机器。当其他所有的非 backup 机器出现故障或者忙的时候,才会请求 backup 机器,因此这台机器的压力最轻。
max_fails,允许请求失败的次数,默认为 1。当超过最大次数时,返回 proxy_next_upstream 模块定义的错误。
fail_timeout,在经历了 max_fails 次失败后,暂停服务的时间。max_fails 可以和 fail_timeout 一起使用。
weight 默认为 1.weight 越大,负载的权重就越大。

1
2
3
4
upstream myserver {
server 192.168.24.200:8080 weight=2 max_fails=2 fail_timeout=2;
server 192.168.24.205:8080 weight=1 max_fails=2 fail_timeout=1;
}

个人能力要求

  • 个人能力要求
    • 团队管理
      • 团队构成的5P要素
      • 技术团队管理体系
      • 团队情结管理4A模型
      • 团队文化建设三步法
      • 中欧中基层管理者胜任力模型
    • 业务理解
      • SWOT战略分析法
      • 业务理解的三个阶段
      • 产品-市场匹配
      • 产品思维:用户体验五要素
    • 商业思维
      • 设计思维-斯坦福的创新课
      • 四种大数据分析方法
      • 五看三定商业模式思维模型
    • 个人成长
      • 番茄工作法
      • 邓宁-克鲁格心里效应
      • 影响力模型:如何展示非权力的领导魅力
      • EQ-I情商模型
    • 技术前瞻
      • 平衡即分卡(BSC)
      • 领域、业务、业务模型的关系
      • 新兴科技技术成熟度曲线
      • 用户全生命周期数据模型

岗位能力要求

  • 岗位能力要求
    • 程序员-技术规划
      • 目标设定
      • 技术分解
      • 计划制定
    • 项目经理
      • 工作任务分解
      • 目标管理
      • 时间管理
      • 管理思维
    • 技术经理
      • 九宫格人才盘点
      • 向上管理
      • 下达绩效目标
    • 技术总监
      • 领导力培养
      • 架构能力
      • 看懂财务报表
    • CTO
      • 组织能力建设
      • 技术性视野
      • 竞争态势分析
      • 预算管理
      • 演讲沟通能力

发展力知识地图

  • 发展力知识地图
    • 学习力
      • 学习金字塔
      • 费曼技巧
      • 刻意学习
      • RIA阅读法
      • 二八定律
    • 思考力
      • 黄金圈法则
      • 5W1H分析法
      • 思维导图
      • 10/10/10法则
    • 创造力
      • 六顶思考帽
      • 头脑风暴
      • 逆向思维
      • 类比思维
      • SCAMPER创新新思维模型
    • 设计力
      • 设计思维
      • 最小可行产品(MVP)
      • 峰终定律
      • AARRR漏斗模型
      • 上瘾模型
    • 共情力
      • 五大圈层模型
      • 高效倾听模型
      • 情绪ABC模型
      • 乔哈里视窗
      • 冰山模型
    • 故事力
      • 故事五要素
      • SCQA模型
      • STAR模型
      • STORY模型
      • 英雄之旅模型
    • 领导力
      • 领导力梯队
      • 情景领导力模型
      • GROW教练模型
      • 管理4C模型
      • TOPIC模型
    • 整合力
      • 杠杆思维
      • POA行动
      • 系统思维
      • 整合思维模型
      • 多元思维模型

代码格式化

  1. 安装插件
  • ESlint
  • vetur
  • Prettier - Code formatter
  1. 设置(Ctrl+S 即可保存)
  • 在 vscode 的文件-首选项-设置里
  • ESLint Edit in setting.json
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
{
"javascript.updateImportsOnFileMove.enabled": "always",
"git.enableSmartCommit": true,
"explorer.confirmDelete": false,
"diffEditor.ignoreTrimWhitespace": false,
// start --------
"editor.formatOnType": true,
"editor.formatOnSave": true,
"vetur.format.defaultFormatter.html": "prettier",
"vetur.format.defaultFormatter.js": "prettier-eslint", //让vue中的js按编辑器自带的ts格式进行格式化
"vetur.format.defaultFormatter.css": "prettier",
"vetur.format.defaultFormatterOptions": {
// "js-beautify-html": {
// "wrap_attributes": "force-aligned"
// }
"prettier": {
// 格式化不加分号
"semi": false,
// 单行超过100个长度的时候开始换行
"eslintIntegration": true
}
},
"eslint.options": {
"plugins": [".js", ".vue", "html"]
},
"prettier.eslintIntegration": true,
// end --------
"emmet.includeLanguages": {},
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
},
"eslint.codeAction.disableRuleComment": {

}
}