0%

搭建步骤

  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": {

}
}

面向对象

  • 面向对象分析 OOA(Object Oriented Analysis)
  • 面向对象设计 OOD(Object Oriented Design)
  • 面向对象编程 OOP(Object Oriented Programming)

结果:类的设计

  1. 程序被拆解为哪些类
  2. 每个类有哪些属性方法
  3. 类和类之间如何交互

面向对象分析:搞清楚做什么
面向对象设计:搞清楚怎么做
面向对象编程:将分析和设计的结果翻译成代码的过程

UML 使用

  • 类图
  • 用例图
  • 顺序图
  • 活动图
  • 状态图
  • 组件图

类间关系

  • 泛化
  • 实现
  • 关联
  • 聚合
  • 组合
  • 依赖

面向对象-封装、抽象、继承、多态

- 封装 抽象 继承 多态
对象
What
隐藏信息
保护数据访问
隐藏具体实现
使用者只需关心功能
无需关心实现
表示 is-a 关系
分为单继承和多继承
子类替换父类
在运行时调用子类的实现
方法
How
暴露有限接口和属性
需要编程语言提供访问控制的语法
通过接口类或者抽象类实现
特殊语法机制非必须
需要编程语言提供特殊语法机制
例如 Java 的 “extends”, C++ 的 “:”
需要编程语言提供特殊的语法机制
比如继承、接口类、duck-typing
目的
Why
提高代码可维护性
降低接口复杂度,提高类的易用性
提高代码的扩展性、维护性
降低复杂度,减少细节负担
解决代码复用问题 提高代码扩展性和复用性

只读

只读列表

Collections.unmodifiableList()

面向过程

Constants:拆解为功能更加单一的类,否则会导致依赖类的重新编译
Utils:只包含静态方法
MVC:(基于贫血模型的开发模式)

充血模型

边界清晰(耦合低)、功能内敛(高内聚)

抽象&&接口

- 抽象 接口
定义 What 1、不允许实例化,只能被继承
2、可包含属性和方法,包含抽象方法
3、子类继承抽象类必须重写抽象方法
1、具有某些功能,或称为协议(contract)
2、不允许实例化,只能被实现
3、不包含属性和普通方法,只声明方法,default 方法
4、类实现接口时,必须实现声明中的所有方法
方法 how abstract-extends interface-implements
目的 Why 解决复用问题,适用于 is-a 的关系 1、解决方法抽象问题,适用于 has-a 的关系
2、表示具有某一组行为特性,是为了解决解耦问题,隔离接口和具体的实现,提高代码的扩展性

一、抛砖引玉

  • 数据结构和算法:是教如何写高效代码
  • 设计模式:如何写出可扩展、可读、可维护的高质量代码

二、头脑风暴

  • 设计模式
    • 引出问题(开发通用模块注意问题?)
      • 如何分层、分模块?
      • 应该怎么划分类?
      • 每个类应该具有哪些属性、方法?
      • 怎么设计类之间的交互?
      • 该用继承还是组合?
      • 该使用接口还是抽象类?
      • 怎么做到解耦、高内聚低耦合?
      • 该用单例模式还是静态方法?
      • 用工厂模式创建对象还是直接 new 出来?
      • 如何避免引入设计模式提高扩展性的同时带来的降低可读性问题?
    • 评价标准:代码质量
      • 可维护性
        • 在不破坏原有代码设计、不引入新 bug 情况下,能够快速修改或添加代码
      • 可读性
        • 代码是否符合编码规范
        • 命名是否达意
        • 注释是否详尽
        • 函数是否长短合适
        • 模块划分是否清晰
        • 是否符合高内聚低耦合等
      • 可扩展性
        • 对修改关闭,对扩展开放
      • 灵活性
        • 易扩展、易复用、易使用
      • 简洁性(简单、复杂)
        • 思从深而行从简
        • KISS:keep it simple,stupid
      • 可复用性
        • DRY:Donot repeat yourself
        • 继承多态(面向对象特性)
        • 单一职责(设计原则)
        • 解耦、高内聚、低耦合(重构技巧)
      • 可测试性
        • 重构时
    • 设计思想(面向对象)-基础
      • 封装、抽象、继承、多态
      • 面向对象编程 vs 面向过程编程
      • 面向对象分析、设计、编程
      • 接口 vs 抽象类
      • 基于接口而非实现编程
      • 多用组合少用继承
      • 贫血模型和充血模型
    • 设计原则-场景
      • SOLID 原则-SRP 单一职责原则
      • SOLID 原则-OCP 开闭原则
      • SOLID 原则-LSP 里氏替换原则
      • SOLID 原则-ISP 接口隔离原则
      • SOLID 原则-DIP 依赖倒置原则
      • DRY 原则、KISS 原则、YAGNI 原则、LOD 法则
    • 设计模式-设计问题
      • 创建型
        • 单例模式、工厂模式(工厂方法和抽象工厂)、建造者模式
        • 原型模式
      • 结构型
        • 代理模式、桥接模式、装饰者模式、适配器模式
        • 门面模式、组合模式、享元模式
      • 行为型
        • 观察者模式、模板模式、策略模式、职责链模式、迭代器模式、状态模式
        • 访问者模式、备忘录模式、命令模式、解释器模式、中介模式
    • 编码规范-可读性
      • 20 条最快速改善代码质量的编程规范
    • 重构技巧-保证质量
      • 目的 why、对象 what、时机 when、方法 how
      • 单元测试和代码的可测试性
      • 大重构(大规模高层次)
      • 小重构(小规模低层次)

三、附录

代码质量描述

灵活性(flexibility)、可扩展性(extensibility)、可维护性(maintainability)、可读性(readability)、可理解性(understandability)、易修改性(changeability)、可复用(reusability)、可测试性(testability)、模块化(modularity)、高内聚低耦合(high cohesion loose coupling)、高效(high effciency)、高性能(high performance)、安全性(security)、兼容性(compatibility)、易用性(usability)、整洁(clean)、清晰(clarity)、简单(simple)、直接(straightforward)、少即是多(less code is more)、文档详尽(well-documented)、分层清晰(well-layered)、正确性(correctness、bug free)、健壮性(robustness)、鲁棒性(robustness)、可用性(reliability)、可伸缩性(scalability)、稳定性(stability)、优雅(elegant)、好(good)、坏(bad)……

主流思想

面向过程、面向对象、函数式编程

设计模式-类模式