简单理解

三资握手的目的是:确认自己的接收能力和发送能力OK,还要确认对方的接收能力和发送能力OK;

  1. A发送给B,B收到了; B知道自己的接收能力OK,对方的发送能力OK;
  2. B回复给A,A收到了; A知道自己的接收能力OK,自己的发送能力OK,对方的接收能力OK,对方的发送能力OK;(但是B还不知道自己的发送能力和A的接收能力是否OK,所以需要第三次握手)
  3. A发送给B,B收到了; B知道自己的发送能力OK;A的接收能力OK;

状态机

三次握手

为什么建链接要三次?

保证能成功通知对方自己的ISN(Initial Sequence Number,这个ISN是作为自己以后数据通信的序号)。

主要是要初始化Sequence Number 的初始值。通信的双方要互相通知对方自己的初始化的Sequence Number(缩写为ISN:Inital Sequence Number)——所以叫SYN,全称Synchronize Sequence Numbers。也就上图中的 x 和 y。这个号要作为以后的数据通信的序号,以保证应用层接收到的数据不会因为网络上的传输的问题而乱序(TCP会用这个序号来拼接数据)。

如何保证数据到达

数据重传机制

示例

客户端:C (192.168.103.34)
服务端:S (14.18.201.48)

第一次握手:
首先C发起连接请求 [syn] Seq=2070720725
C进入SYN_SEND状态;

第二次握手:
接着S收到请求后,返回 [syn ack] Seq=3747916590 Ack=2070720726
S进入SYN_RECV状态;

第三次握手:
C收到S返回的信息,验证成功后返回确认信息 [ack] Seq=2070720726 Ack=3747916590
C进入ESTABLISH状态。S收到后也进入ESTABLISH状态。

注意:wireshark默认显示的sequence number是相对的数字 ,可以通过如下图的方式取消

参考资料

Basics of Computer Networking - GeeksforGeeks

幂等

幂等_百度百科

在编程中一个幂等操作的特点是其任意多次执行所产生的影响均与一次执行的影响相同。

理解HTTP幂等性 - Todd Wei - 博客园

另一种更轻量级的解决方案是幂等设计。我们可以通过一些技巧把withdraw变成幂等的,比如:

1
2
int create_ticket() 
bool idempotent_withdraw(ticket_id, account_id, amount)

create_ticket的语义是获取一个服务器端生成的唯一的处理号ticket_id,它将用于标识后续的操作。idempotent_withdraw和withdraw的区别在于关联了一个ticket_id,一个ticket_id表示的操作至多只会被处理一次,每次调用都将返回第一次调用时的处理结果。这样,idempotent_withdraw就符合幂等性了,客户端就可以放心地多次调用。

基于幂等性的解决方案中一个完整的取钱流程被分解成了两个步骤:1.调用create_ticket()获取ticket_id;2.调用idempotent_withdraw(ticket_id, account_id, amount)。虽然create_ticket不是幂等的,但在这种设计下,它对系统状态的影响可以忽略,加上idempotent_withdraw是幂等的,所以任何一步由于网络等原因失败或超时,客户端都可以重试,直到获得结果。

POST 和 PUT 在幂等性方面有所不同

The POST method is used to request that the origin server accept the entity enclosed in the request as a new subordinate of the resource identified by the Request-URI in the Request-Line …… If a resource has been created on the origin server, the response SHOULD be 201 (Created) and contain an entity which describes the status of the request and refers to the new resource, and a Location header.
The PUT method requests that the enclosed entity be stored under the supplied Request-URI. If the Request-URI refers to an already existing resource, the enclosed entity SHOULD be considered as a modified version of the one residing on the origin server. If the Request-URI does not point to an existing resource, and that URI is capable of being defined as a new resource by the requesting user agent, the origin server can create the resource with that URI.
POST所对应的URI并非创建的资源本身,而是资源的接收者。
比如:POST http://www.forum.com/articles的语义是在http://www.forum.com/articles下创建一篇帖子,HTTP响应中应包含帖子的创建状态以及帖子的URI。两次相同的POST请求会在服务器端创建两份资源,它们具有不同的URI;所以,POST方法不具备幂等性。而PUT所对应的URI是要创建或更新的资源本身。比如:PUT http://www.forum/articles/4231的语义是创建或更新ID为4231的帖子。对同一URI进行多次PUT的副作用和一次PUT是相同的;因此,PUT方法具有幂等性。

https://www.cnblogs.com/weidagang2046/archive/2011/06/04/idempotence.html

How to Set JVM Proxy Setting Without Touching the Code

-X 参数

On the basis of how we specify JVM option it can be divided into two parts, JVM Options which starts with –X and those which starts with -XX:

  1. JVM Options that begin with -X are non-standard (thy are not guaranteed to be supported on all JVM implementations), and are subject to change without notice in subsequent releases of the JDK.
  2. JVM Options or parameters which are specified with -XX are not stable and are not recommended for casual use. These options are subject to change without notice also.

10 Examples of HotSpot JVM Options in Java

【推荐】给 JVM 环境参数设置-XX:+HeapDumpOnOutOfMemoryError 参数,让 JVM 碰到 OOM 场
景时输出 dump 信息。
说明:OOM 的发生是有概率的,甚至相隔数月才出现一例,出错时的堆内信息对解决问题非常
有帮助。
// 《阿里巴巴 Java 开发手册 1.4.0pdf - p34》

-D参数

参数 -D 是 Java 自带的,其功能是通过命令行设置一个 Java 系统属性。

常用参数

-Xms2G
-Xmx2G
-XX:NewRatio=4
-XX:SurvivorRatio=8
-XX:UseParNewGC
-XX:UseParallelOldGC
-XX:UseConcMarkSweepGC
-XX:+PrintGC
-XX:+PrintGCDetails

logback

SpringBoot 日志处理之 Logback - 掘金

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
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<contextName>logback-spring-demo-dev</contextName>
<property name="pattern" value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg %n"/>
<property name="pattern-color" value="%yellow(%d{yyyy-MM-dd HH:mm:ss.SSS}) [%thread] %highlight(%-5level) %green(%logger{50}) - %highlight(%msg) %n"/>
<property name="LOG_HOME" value="logs"/>

<!-- 控制台输出 -->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>${pattern}</pattern>
</encoder>
</appender>

<!-- 控制台输出-带颜色 -->
<appender name="CONSOLE-WITH-COLOR" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>${pattern-color}</pattern>
</encoder>
</appender>

<!-- 文件输出 -->
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${LOG_HOME}/all.%d.%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>10MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<maxHistory>30</maxHistory>
</rollingPolicy>

<encoder>
<pattern>${pattern}</pattern>
</encoder>
</appender>


<root level="INFO">
<appender-ref ref="CONSOLE-WITH-COLOR"/>
<appender-ref ref="FILE"/>
</root>

<logger name="com.example.logbackdemo.IndexAction" level="info" additivity="false">
<appender-ref ref="CONSOLE"/>
</logger>

</configuration>

日志

How to define a live template

Go to File->Settings->Editor->Live Templates.
In the right panel tree select category other.
Click the plus (+) sign on the top right, select Live Template.
Set
    Abbreviation: log
    Description: Inserts private static Logger for slf4j
    Template text: private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger($CLASS_NAME$.class);$END$
Now click the Edit Variables button, we will tell the IDE what $CLASS_NAME$ means here. $END$ means where to place the cursor after template expansion.
    Name: CLASS_NAME
    Expression: className()
    Default value: leave empty
    Skip if defined: true (check the checkbox)
At the very bottom look for text Applicable in with a link Change next to it, click it. Select Java->declaration.

Congratulations, you’re done! Just type log and press Tab anywhere in the class declaration.

有颜色的 log4j

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
log4j.debug=false
#
# Default level is INFO
log4j.rootLogger=DEBUG,StdoutErrorFatal,StdoutWarn,StdoutInfo,StdoutDebug,StdoutTrace
#
# and for com.some.package.* log everything
log4j.logger.com.some.package=TRACE
#
log4j.appender.StdoutErrorFatal=org.apache.log4j.ConsoleAppender
log4j.appender.StdoutErrorFatal.layout=org.apache.log4j.PatternLayout
log4j.appender.StdoutErrorFatal.layout.conversionPattern=\u001b[31;1m%d{HH:mm:ss,SSS} %-5p - %-26c - [user:%X{username}] %m\n
log4j.appender.StdoutErrorFatal.threshold=ERROR
#
log4j.appender.StdoutWarn=org.apache.log4j.ConsoleAppender
log4j.appender.StdoutWarn.layout=org.apache.log4j.PatternLayout
log4j.appender.StdoutWarn.layout.conversionPattern=\u001b[33;1m%d{HH:mm:ss,SSS} %-5p - %-26c - [user:%X{username}] %m\n
log4j.appender.StdoutWarn.threshold=WARN
log4j.appender.StdoutWarn.filter.filter1=org.apache.log4j.varia.LevelRangeFilter
log4j.appender.StdoutWarn.filter.filter1.levelMin=WARN
log4j.appender.StdoutWarn.filter.filter1.levelMax=WARN
#
log4j.appender.StdoutInfo=org.apache.log4j.ConsoleAppender
log4j.appender.StdoutInfo.layout=org.apache.log4j.PatternLayout
log4j.appender.StdoutInfo.layout.conversionPattern=\u001b[0m%d{HH:mm:ss,SSS} %-5p - %-26c - [user:%X{username}] %m\n
log4j.appender.StdoutInfo.threshold=INFO
log4j.appender.StdoutInfo.filter.filter1=org.apache.log4j.varia.LevelRangeFilter
log4j.appender.StdoutInfo.filter.filter1.levelMin=INFO
log4j.appender.StdoutInfo.filter.filter1.levelMax=INFO
#
log4j.appender.StdoutDebug=org.apache.log4j.ConsoleAppender
log4j.appender.StdoutDebug.layout=org.apache.log4j.PatternLayout
log4j.appender.StdoutDebug.layout.conversionPattern=\u001b[0;36m%d{HH:mm:ss,SSS} %-5p - %-26c - [user:%X{username}] %m\n
log4j.appender.StdoutDebug.threshold=DEBUG
log4j.appender.StdoutDebug.filter.filter1=org.apache.log4j.varia.LevelRangeFilter
log4j.appender.StdoutDebug.filter.filter1.levelMin=DEBUG
log4j.appender.StdoutDebug.filter.filter1.levelMax=DEBUG
#
log4j.appender.StdoutTrace=org.apache.log4j.ConsoleAppender
log4j.appender.StdoutTrace.layout=org.apache.log4j.PatternLayout
log4j.appender.StdoutTrace.layout.conversionPattern=\u001b[0;30;1m%d{HH:mm:ss,SSS} %-5p - %-26c - [user:%X{username}] %m\n
log4j.appender.StdoutTrace.threshold=TRACE
log4j.appender.StdoutTrace.filter.filter1=org.apache.log4j.varia.LevelRangeFilter
log4j.appender.StdoutTrace.filter.filter1.levelMin=TRACE
log4j.appender.StdoutTrace.filter.filter1.levelMax=TRACE

完整配置: http://javapub.iteye.com/blog/866664

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
66
67
68
69
70
log4j.rootLogger=CONSOLE,FILE
log4j.addivity.org.apache=true

# 应用于控制台
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.Threshold=INFO
log4j.appender.CONSOLE.Target=System.out
log4j.appender.CONSOLE.Encoding=GBK
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n

# 每天新建日志
log4j.appender.A1=org.apache.log4j.DailyRollingFileAppender
log4j.appender.A1.File=C:/log4j/log
log4j.appender.A1.Encoding=GBK
log4j.appender.A1.Threshold=DEBUG
log4j.appender.A1.DatePattern='.'yyyy-MM-dd
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L : %m%n

#应用于文件
log4j.appender.FILE=org.apache.log4j.FileAppender
log4j.appender.FILE.File=C:/log4j/file.log
log4j.appender.FILE.Append=false
log4j.appender.FILE.Encoding=GBK
log4j.appender.FILE.layout=org.apache.log4j.PatternLayout
log4j.appender.FILE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n

# 应用于文件回滚
log4j.appender.ROLLING_FILE=org.apache.log4j.RollingFileAppender
log4j.appender.ROLLING_FILE.Threshold=ERROR
log4j.appender.ROLLING_FILE.File=rolling.log
log4j.appender.ROLLING_FILE.Append=true
log4j.appender.CONSOLE_FILE.Encoding=GBK
log4j.appender.ROLLING_FILE.MaxFileSize=10KB
log4j.appender.ROLLING_FILE.MaxBackupIndex=1
log4j.appender.ROLLING_FILE.layout=org.apache.log4j.PatternLayout
log4j.appender.ROLLING_FILE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n

#自定义Appender
log4j.appender.im = net.cybercorlin.util.logger.appender.IMAppender
log4j.appender.im.host = mail.cybercorlin.net
log4j.appender.im.username = username
log4j.appender.im.password = password
log4j.appender.im.recipient = yyflyons@163.com
log4j.appender.im.layout=org.apache.log4j.PatternLayout
log4j.appender.im.layout.ConversionPattern =[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n

#应用于socket
log4j.appender.SOCKET=org.apache.log4j.RollingFileAppender
log4j.appender.SOCKET.RemoteHost=localhost
log4j.appender.SOCKET.Port=5001
log4j.appender.SOCKET.LocationInfo=true
# Set up for Log Facter 5
log4j.appender.SOCKET.layout=org.apache.log4j.PatternLayout
log4j.appender.SOCET.layout.ConversionPattern=[start]%d{DATE}[DATE]%n%p[PRIORITY]%n%x[NDC]%n%t[THREAD]%n%c[CATEGORY]%n%m[MESSAGE]%n%n
# Log Factor 5 Appender
log4j.appender.LF5_APPENDER=org.apache.log4j.lf5.LF5Appender
log4j.appender.LF5_APPENDER.MaxNumberOfRecords=2000

# 发送日志给邮件
log4j.appender.MAIL=org.apache.log4j.net.SMTPAppender
log4j.appender.MAIL.Threshold=FATAL
log4j.appender.MAIL.BufferSize=10
log4j.appender.MAIL.From=yyflyons@163.com
log4j.appender.MAIL.SMTPHost=www.wusetu.com
log4j.appender.MAIL.Subject=Log4J Message
log4j.appender.MAIL.To=yyflyons@126.com
log4j.appender.MAIL.layout=org.apache.log4j.PatternLayout
log4j.appender.MAIL.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n

Spring MVC + Log4j example

https://tutorials.ubuntu.com/tutorial/install-and-configure-samba#0

https://blog.csdn.net/wbaction/article/details/72758673

install

1
sudo apt-get install samba

config

1
sudo vim /etc/samba/smb.conf

添加在后面

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[smbshare]
comment = samba home directory
path = /home/user/w/smbshare
public = yes
browseable = yes
public = yes
read only = no
valid users = user
create mask = 0777
directory mask = 0777
force user = nobody
force group = nogroup
available = yes
```

```sh
chmod 777 /home/user/w/smbshare

add user

1
sudo smbpasswd -a $USER

restart

1
sudo service smbd restart

uninstall

1
sudo apt remove --purge samba samba-common

reinstall

sudo apt remove –purge samba samba-common
sudo apt install samba

面试题

Spring MVC 的全流程是什么?

mvc_flow
https://m.imooc.com/collector/read/60

在 Spring MVC 中,为什么 @RequestBody 可以从 JSON 转换出 Java 对象,而 @ResponseBody 可以将控制器返回转换出 JSON 数据集?

HttpMessageConverter
https://m.imooc.com/collector/read/62

MyBatis 存在哪些组件,各个组件的生命周期是怎么样的,我们应该怎么使用它们?

SqlSessionFactory
SqlSession
Mapper

Configuration
Plugin
TypeHandler
Alias

https://m.imooc.com/collector/read/63

MyBatis 的 TypeHandler 的作用是什么,我们应该如何使用它?

实现从数据库和POJO之间的相互转换。

使用

  1. 实现TypeHandler
  2. 注册到MyBatis上下文
  3. 在mapper的xml文件中使用:如#{sex, typeHandler=com.imooc.ssm.typehandler.SexTypeHandler}

https://m.imooc.com/collector/read/65

什么是 MyBatis 插件技术?我们应该如何开发 MyBatis 插件?

通过动态代理的方式来修改MyBatis的底层内容;
插件应用:如分页插件、性能分析插件

开发步骤:

  1. 实现Inteceptor
  2. 在MyBatis上下文中注册

https://m.imooc.com/collector/read/66

Spring 数据库事务机制是怎么样的?在什么时候 Spring 会回滚事务?

保证两个操作要么都成功,要么都失败。
Spring 数据库事务流程是通过Spring AOP实现的,而Spring AOP则是通过动态代理技术来实现的。

执行业务的过程中,如果发生异常且满足事务配置,则会回滚事务(rollback)。
如果一切正常或者异常是事务配置允许的,则会提交事务(commit)。

https://m.imooc.com/collector/read/71

我们是使用什么注解启用 Spring 数据库事务机制?

@Transactional
https://m.imooc.com/collector/read/71

数据库隔离级别分为几个,分别是什么?

4个。

未提交读:Read uncommited
提交读:Read commit
可重复读:Repeatable read
序列化:Serializable
https://m.imooc.com/collector/read/73

各个隔离级别可能出现什么问题,请举详细实例?

隔离级别\现象 脏读 不可重复读 幻读
未提交读:Read uncommited v v v
提交读:Read commit x v v
可重复读:Repeatable read x x v
序列化:Serializable x x x

https://m.imooc.com/collector/read/73

不可重复读和序列化两个隔离级别有什么区别?

是否会出现幻读
https://m.imooc.com/collector/read/73

我们一般依据什么标准选择隔离级别?

选择隔离级别主要从防止丢失更新和性能两方面来考虑
https://m.imooc.com/collector/read/73

一般企业用哪个隔离级别?默认的隔离级别是哪个?Oracle 和 MySQL 对隔离级别的支持情况如何?

一般企业用的是:提交读:Read这个级别,它适合在高并发的场景下使用。
默认的隔离级别是:Isolation.DEFAULT,Oracle和MySQL有不同的设置:Oracle使用的是提交读:Read,MySQL使用的是可重复读:Repeatable

MySQL支持全部4个级别;
Oracle只支持提交读:Read序列化:Serializable两个级别;

https://m.imooc.com/collector/read/73

Spring 数据库传播行为有几种?分别是什么?默认的是什么?

7种
propagation

默认的是PROPAGATION_REQUIRED
https://m.imooc.com/collector/read/74

什么场景下使用 NESTED 事务传播行为?

子事务方法采用独立的事务模式,如果子方法发生异常,也不回滚原方法事务方法的事务。
(对于支持保护点(savepoint)的数据库使用保护点,否则Spring就会创建新的数据库事务来运行它)

https://m.imooc.com/collector/read/74

NESTED 事务和 REQUIRES_NEW 两个传播行为有什么不同?

首先NESTED是延续当前事务,NESTED只是回滚子方法执行过的SQL,而不是全局回滚,但是他不能重新设置事务的属性,
比如不能重新设置事务的隔离级别、超时时间和锁等。
而REQUESTS_NEW会重新建事务,我们可以重新设置事务的属性。
https://m.imooc.com/collector/read/74

0%