0%

B2B

B2B = Business to Business
商家(泛指企业)对商家的电子商务,即企业与企业之间通过互联网进行产品、服务及信息的交换。通俗的说法是指进行电子商务交易的供需双方都是商家(或企业、公司),他们使用 Internet 的技术或各种商务网络平台(如拓商网),完成商务交易的过程。这些过程包括:发布供求信息,订货及确认订货,支付过程,票据的签发、传送和接收,确定配送方案并监控配送过程等。如阿里巴巴,慧聪网

B2C

B2C = Business to Customer
B2C 模式是中国最早产生的电子商务模式,如今的 B2C 电子商务网站非常的多,比较大型的有唯品会、一号店、亚马逊、苏宁易购、国美在线等。

B2B2C

B2B2C = Business To Business To Customers
所谓 B2B2C 是一种新的网络通信销售方式。第一个 B 指广义的卖方(即成品、半成品、材料提供商等),第二个 B 指交易平台,即提供卖方与买方的联系平台,同时提供优质的附加服务,C 即指买方。卖方可以是公司,也可以是个人,即一种逻辑上的买卖关系中的卖方。如天猫商城、京东商城

C2C

C2C = Consumer to Consumer
C2C 同 B2B、B2C 一样,都是电子商务的几种模式之一。不同的是 C2C 是用户对用户的模式,C2C 商务平台就是通过为买卖双方提供一个在线交易平台,使卖方可以主动提供商品上网拍卖,而买方可以自行选择商品进行竞价。如淘宝,易趣,瓜子二手车

O2O

O2O = Online to Offline
O2O 是新兴起的一种电子商务新商业模式,即将线下商务的机会与互联网结合在了一起,让互联网成为线下交易的前台。这样线下服务就可以用线上来揽客,消费者可以用线上来筛选服务,还有成交可以在线结算,很快达到规模。该模式最重要的特点是:推广效果可查,每笔交易可跟踪。如美团,饿了么

C2B

C2B = Customer to Business
C2B 是电子商务模式的一种,即消费者对企业。最先由美国流行起来的 C2B 模式也许是一个值得关注的尝试。C2B 模式的核心,是通过聚合分散分布但数量庞大的用户形成一个强大的采购集团,以此来改变 B2C 模式中用户一对一出价的弱势地位,使之享受到以大批发商的价格买单件商品的利益。如海尔商城,尚品宅配,某些装修类电商平台,注重个性化服务。

F2C

F2C = Factory to customer
即从厂商到消费者的电子商务模式,如拼多多

当阻塞方法(如sleep())收到中断请求的时候就会抛出InterruptedException异常

线程的状态

线程在一定的条件下会发生状态的改变,下面是线程的一些状态

img

  • 初始(NEW):新建一个线程的对象,还未调用start方法

  • 运行(RUNNABLE):java线程中将已经准备就绪(Ready)和正在运行中(Running)的两种状态都统称为“Runnable”。准备就绪的线程会被放在线程池中等待被调用

  • 阻塞(BLOCKED):是因为某种的原因而放弃了CPU的使用权,暂时的停止了运行。直到线程进入准备就绪(Ready)状态才会有机会转到运行状态

  • 等待(WAITING):该状态的线程需要等待其他线程做出一些特定的动作(通知或者是中断)

  • 超时等待(TIME_WAITING):该状态和上面的等待不同,他可以在指定的时间内自行返回

  • 终止(TERMINATED):线程任务执行完毕

线程阻塞

线程阻塞通常是指一个线程在执行过程中暂停,以等待某个条件的触发。而什么情况才会使得线程进入阻塞的状态呢?

  • 等待阻塞:运行的线程执行wait()方法,该线程会释放占用的所有资源,JVM会把该线程放入“等待池”中。进入这个状态后,是不能自动唤醒的,必须依靠其他线程调用notify()或notifyAll()方法才能被唤醒
  • 同步阻塞:运行的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线程放入“锁池”中
  • 其他阻塞:运行的线程执行sleep()或join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态

线程中断

每一个线程都有一个boolean类型的标志,此标志意思是当前的请求是否请求中断,默认为false。当一个线程A调用了线程B的interrupt方法时,那么线程B的是否请求的中断标志变为true。而线程B可以调用方法检测到此标志的变化。

  1. 阻塞方法:如果线程B调用了造成阻塞的方法,如果是否请求中断标志变为了true,那么它会抛出InterruptedException异常。抛出异常的同时它会将线程B的是否请求中断标志置为false
  2. 非阻塞方法:可以通过线程B的isInterrupted()方法进行检测是否请求中断标志为true还是false,另外还有一个静态的方法interrupted方法也可以检测标志。但是这个静态方法检测完以后会自动的将是否请求中断标志位置为false。例如线程A调用了线程B的interrupt的方法,那么如果此时线程B中用静态interrupted方法进行检测标志位的变化的话,那么第一次为true,第二次就为false。

线程可以检测到自身的标志位的变化,但是他只是一个标志,如果线程本身不处理的话,那么程序还是会执行下去。interrupt() 方法并不能立即中断线程,该方法仅仅告诉线程外部已经有中断请求,至于是否中断还取决于线程自己。

正确处理InterruptedException

有时候阻塞的方法抛出(throw)InterruptedException异常并不合适,例如在Runnable中调用了可中断的方法,因为你的程序是实现了Runnable接口,然后在重写Runnable接口的run方法的时候,那么子类抛出的异常要小于等于父类的异常。而在Runnable中run方法是没有抛异常的,所以此时不能抛出InterruptedException异常。如果此时你只是记录日志的话,那么就是一个不负责任的做法,因为在捕获InterruptedException异常的时候自动的将是否请求中断标志置为了false。至少在捕获了InterruptedException异常之后,如果你什么也不想做,那么就将标志重新置为true,以便栈中更高层的代码能知道中断,并且对中断作出响应

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class TaskRunner implements Runnable {
private BlockingQueue<Task> queue;

public TaskRunner(BlockingQueue<Task> queue) {
this.queue = queue;
}

public void run() {
try {
while (true) {
Task task = queue.take(10, TimeUnit.SECONDS);
task.execute();
}
}
catch (InterruptedException e) {
// Restore the interrupted status
Thread.currentThread().interrupt();
}
}
}

公钥与私钥

公钥本来就是公开的,那岂不是私钥加密的数据根本没有安全性可言?

私钥加密的数据确实没有安全性可言,因为用私钥加密数据根本就不是为了安全性,而是作为一种验证身份的手段。
因为私钥是唯一的,一旦使用公钥对私钥加密的数据解密成功,服务端S就可以完全确定这条消息是由拥有对应私钥的客户端C发出的,而不是第三方伪装者发出的。
所以,公钥加密私钥解密,是为了数据的安全性,而私钥加密公钥解密,则是为了验证数据发送者的身份

Java原生NIO的缺陷

  • 类库和API繁杂
  • 入门门槛高,需要其他额外的知识做铺垫
  • 工作量和难度大,客户端会面临断开,重连,网络闪断,失败缓存,网络拥堵等问题
  • JDK NIO存在臭名昭著的epoll bug,导致Selector空轮询:这个bug会导致linux上cpu 100%

Netty的优势

  • 业界流行的NIO框架之一,健壮性,功能,可定制性,可扩展性都比较好,得到了业界的认可与证明。比如在dubbo框架中的底层应用
  • API使用简单,定制能力强,可以灵活扩展
  • 入门门槛低,易学,功能强大,预置了多种编解码功能,支持多种主流通信协议(http,tpc,udp,socket)
  • 性能高,成熟,稳定

Netty介绍

Netty is a NIO client server framework which enables quick and easy development of network applications such as protocol servers and clients.It greatly simplifies and streamlines network programming such as TCP and UDP socket server.
Netty框架

Netty使用场景

Netty常见的使用场景如下:

互联网行业

在分布式系统中,各个节点之间需要远程服务调用,高性能的RPC框架必不可少,Netty作为异步高新能的通信框架,往往作为基础通信组件被这些RPC框架使用。
典型的应用有:阿里分布式服务框架Dubbo的RPC框架使用Dubbo协议进行节点间通信,Dubbo协议默认使用Netty作为基础通信组件,用于实现各进程节点之间的内部通信。

游戏行业

无论是手游服务端还是大型的网络游戏,Java语言得到了越来越广泛的应用。Netty作为高性能的基础通信组件,它本身提供了TCP/UDP和HTTP协议栈。
非常方便定制和开发私有协议栈,账号登录服务器,地图服务器之间可以方便的通过Netty进行高性能的通信

大数据领域

经典的Hadoop的高性能通信和序列化组件Avro的RPC框架,默认采用Netty进行跨界点通信,它的Netty Service基于Netty框架二次封装实现

Java原生NIO的缺陷

  • 类库和API繁杂
  • 入门门槛高,需要其他额外的知识做铺垫
  • 工作量和难度大,客户端会面临断开,重连,网络闪断,失败缓存,网络拥堵等问题
  • JDK NIO存在臭名昭著的epoll bug,导致Selector空轮询:这个bug会导致linux上cpu 100%

Netty的优势

  • 业界流行的NIO框架之一,健壮性,功能,可定制性,可扩展性都比较好,得到了业界的认可与证明。比如在dubbo框架中的底层应用
  • API使用简单,定制能力强,可以灵活扩展
  • 入门门槛低,易学,功能强大,预置了多种编解码功能,支持多种主流通信协议(http,tpc,udp,socket)
  • 性能高,成熟,稳定

Netty介绍

Netty is a NIO client server framework which enables quick and easy development of network applications such as protocol servers and clients.It greatly simplifies and streamlines network programming such as TCP and UDP socket server.
Netty框架

Netty使用场景

Netty常见的使用场景如下:

互联网行业

在分布式系统中,各个节点之间需要远程服务调用,高性能的RPC框架必不可少,Netty作为异步高新能的通信框架,往往作为基础通信组件被这些RPC框架使用。
典型的应用有:阿里分布式服务框架Dubbo的RPC框架使用Dubbo协议进行节点间通信,Dubbo协议默认使用Netty作为基础通信组件,用于实现各进程节点之间的内部通信。

游戏行业

无论是手游服务端还是大型的网络游戏,Java语言得到了越来越广泛的应用。Netty作为高性能的基础通信组件,它本身提供了TCP/UDP和HTTP协议栈。
非常方便定制和开发私有协议栈,账号登录服务器,地图服务器之间可以方便的通过Netty进行高性能的通信

大数据领域

经典的Hadoop的高性能通信和序列化组件Avro的RPC框架,默认采用Netty进行跨界点通信,它的Netty Service基于Netty框架二次封装实现

为什么需要 WebSocket?

答案很简单,因为 HTTP 协议有一个缺陷:通信只能由客户端发起。举例来说,我们想了解今天的天气,只能是客户端向服务器发出请求,服务器返回查询结果。HTTP协议做不到服务器主动向客户端推送信息。
这种单向请求的特点,注定了如果服务器有连续的状态变化,客户端要获知就非常麻烦。我们只能使用轮询:每隔一段时候,就发出一个询问,了解服务器有没有新的信息。最典型的场景就是聊天室。
轮询的效率低,非常浪费资源(因为必须不停连接,或者HTTP连接始终打开)。因此,工程师们一直在思考,有没有更好的方法。

websocket是HTML5的一个新协议,它允许服务端向客户端传递信息,实现浏览器和客户端双工通信。WebSocket协议在2008年诞生,2011年成为国际标准,所有浏览器都已经支持了。它的最大特点就是,服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,是真正的双向平等对话,属于服务器推送技术的一种。

##WebSocket特点

(1)建立在 TCP 协议之上,服务器端的实现比较容易。

(2)与 HTTP 协议有着良好的兼容性。默认端口也是80和443,并且握手阶段采用 HTTP 协议,因此握手时不容易屏蔽,能通过各种 HTTP 代理服务器。

(3)数据格式比较轻量,性能开销小,通信高效。

(4)可以发送文本,也可以发送二进制数据。

(5)没有同源限制,客户端可以与任意服务器通信。

(6)协议标识符是ws(如果加密,则为wss),服务器网址就是 URL。

WebSocket生命周期

打开事件

端点上建立新链接时,该事件是先于其他任何事件发生之前。该事件发生会产生三部分信息。

  • 创建WebSocket Session对象: 用于表示已经建立好的链接
  • 配置对象: 包含配置端点的信息。
  • 一组路径参数: 用于打开节点握手时,WebSocket端入栈匹配的URI

消息事件

主要是接收WebSocket对话中,另一端发送的消息。链接上的消息将会有三种形式抵达客户端。

  • 文本消息 用String处理

  • 二进制消息 用byteBuffer或者byte[]处理

  • pong消息 用Java WebSocket API中的pong.message接口的实例来处理

错误事件

WebSocket链接或者端点发生错误时产生。可以处理入栈消息时发生的各种异常。入栈消息可能产生的三种异常。

  • WebSocket建立链接时发生错误 SessionException类型
  • WebSocket试图将入栈消息解码成开发人员使用的对象时 EncodeException类型
  • WebSocket端点的其他方法运行时产生的错误,WebSocket实现将记录端点操作过程中产生的任何运行时异常

关闭事件

WebSocket链接端点关闭,做一些清理工作,可以由参与连接的任意一个端点发出。

  • 服务器关闭底层TCP连接
  • 客户端发起TCP Close

BIO (阻塞IO)

服务器程序一个线程负责一个连接,进行请求的处理和响应。当客户端比较多的时候,服务端的线程可能就不够了,这时候对应的请求就没法及时处理了。

伪异步IO(BIO增加线程池)

服务端会维护一个线程池来处理请求端的请求,减少了线程创建销毁开销。当客户端的请求比较多的时候,线程池的线程也是不够的,此时也会出现请求处理阻塞的情况。

NIO

同步非阻塞IO方式,服务端通过缓存区通道多路复用等技术,允许客户端的请求成千上万。读写都首先通过缓冲区来承接,然后通过通道(双向,区别于需要两个InputStreamOutputStream)来传输信息。通过多路复用器轮询通道(select/poll,epoll),看看是否存在读或者写时间,然后再进行处理,大大提升了IO处理的性能和稳定性.由于操作复杂,Netty横空出世。

AIO

AIO又称为NIO2.0,在JDK7才开始支持(但Linux平台下没有真正的异步IO实现,如windows下的IOCP技术,只能用epoll模拟异步IO)。真正的异步IO,简化了NIO的通信模型。它是连接注册读写事件和回调函数,读写方法异步,同时它是主动通知程序。
AIO异步通信提供了两种方式获取操作结果:第一种方式是通过java.util.concurrentFuture类来表示异步操作的结果;第二种方式是在执行异步操作的时候传入一个java.nio.channels.CompletionHandler接口的实现类作为操作完成回调。
AIO的异步套接字回调,是真正的异步非阻塞IO, .对应于Unix网络编程中的事件驱动IO,不需要通过多路复用器对被注册的通道进行轮询操作即可实现异步读写,从而简化NIO的编程模型。

对比

IO通信方式 客户端:处理线程 IO类型 可靠性 调试难度 吞吐量
BIO M:M 同步阻塞 简单
伪异步IO(线程池) M:N (N<M) 同步阻塞 比较差 简单
NIO M:1 同步非阻塞 比较高 复杂
AIO(异步NIO) M:0 异步非阻塞 比较高 比较复杂

阻塞式的I/O模型需要每个链接开一个线程(或进程),当线程数达到10k级别时,内存占用上下文切换(context switch)导致系统的开销很大。

为什么Netty使用NIO而不是AIO?

参考链接

  • Netty不看重Windows上的使用,在Linux系统上,AIO的底层实现仍使用EPOLL,没有很好实现AIO,因此在性能上没有明显的优势,而且被JDK封装了一层不容易深度优化
  • Netty整体架构是reactor模型, 而AIO是proactor模型, 混合在一起会非常混乱,把AIO也改造成reactor模型看起来是把epoll绕个弯(Linux用epoll实现AIO)又绕回来
  • AIO还有个缺点是接收数据需要预先分配缓存, 而不是NIO那种需要接收时才需要分配缓存.所以对连接数量非常大但流量小的情况, AIO内存浪费很多
  • Linux上AIO不够成熟,处理回调结果速度跟不到处理需求,比如外卖员太少,顾客太多,供不应求,造成处理速度有瓶颈.
  • Netty作者原话:
    Not faster than NIO (epoll) on unix systems (which is true).
    There is no daragram suppport.
    Unnecessary threading model (too much abstraction without usage).

man 命令

man 命令名

man是manual的简写
man ls

man -f 命令名

man帮助文档,可以按级别查看:
man -f 命令名相当于whatis 命令名
举例:
shell man -5 passwd #系统所有用户信息 man -4 null #系统黑洞 man -8 ifconfig
如果只有一种等级的帮助文档,直接man 命令名即可
在这里插入图片描述

man -k 命令名

man查看和命令相关的所有帮助:
man -k 命令名相当于apropos 命令名
如:apropos passwd

--help 选项帮助

比较常用,通过命令选项获取帮助,如ls --help

help获取shell内部命令的帮助

help shell内部命令获取shell内部命令的帮助

shell whereis cd #检查是否是shell内部命令,whereis只能找到外部命令的可执行文件位置 help cd #获取帮助 help ls #ls不是内部命令,所以找不到帮助文件
shell内部命令是最基本的命令

info详细命令帮助

info 命令名帮助文档,很详细,用得少.
在这里插入图片描述

.zip格式

压缩文件

zip 文件.zip 源文件

压缩文件夹

zip -r 文件夹.zip 源目录

解压

unzip 文件.zip

.gz格式

压缩文件

gzip 源文件
压缩为.gz格式,且源文件会消失
gzip -c 源文件 > 源文件.gz
压缩为.gz格式,保留源文件,不常用,”-c”表示把压缩文件输出到屏幕,”>”表示输出重定向

压缩目录(下的所有子文件)

gzip -r 目录
压缩目录下的所有子文件,但是不能压缩目录.(很不方便,不常用)

解压

gzip -d 压缩文件gunzip 压缩文件

解压目录(下的所有子文件)

gunzip -r 目录

.bz2格式

压缩文件

bzip2 源文件
不保留源文件
bzip2 -k 源文件
保留源文件

bzip2命令不能压缩目录!

解压文件

bzip2 -d 源文件bunzip2 源文件
-k保留压缩文件

.gz和.bz2对目录的处理不太友好,下面介绍tar打包命令

tar打包命令

打包

tar -cvf 打包名 源文件
选项 说明
-c 打包
-v 显示过程
-f 指定打包后的文件名

tar -cvf xxx.tar xxx

解包

tar -xvf 打包名

tar -xvf xxx.tar

打包+压缩为.gz

tar -zcvf 打包名.tar.gz 源文件 [源文件2] [源文件3]...

-z代表.gz,可以有多个源文件,空格隔开

解压缩.tar.gz

tar -zxvf 打包名.tar.gz [-C 新位置]

-z代表.gz

打包+压缩为.bz2

tar -jcvf 打包名.tar.bz2 源文件

-j代表.bz2,,可以有多个源文件,空格隔开

解压缩.tar.bz2

tar -jxvf 打包名.tar.bz2 [-C 新位置]

-j代表.bz2

查看压缩包,不解压

tar -ztvf 打包名.tar.gz
tar -jtvf 打包名.tar.bz2

-t代表test,查看文件内容.

目录分类

/usr 系统软件资源目录
/bin /usr/bin 系统命令,所有用户可执行
/sbin /usr/sbin 系统命令,仅root可执行
/boot 系统启动数据
/etc 系统默认配置文件
/dev 硬件设备文件
/lib 系统功能函数库,so文件
/sys /proc 内存挂载点,直接写入内存,不能动
/var 系统可变文档目录

目录操作

1
2
3
4
5
6
7
8
9
10
cd    # 等同于 cd ~ 回家
cd - # 上次目录
ls -lh # --long --human人性化显示大小 -i查看文件inode号
ll # ls -l
pwd # print working dir
mkdir -p xxxx # -p 递归创建
rm -r xxxx #删除目录
cp -r src dst # -r复制目录 -p同时复制文件属性(如修改时间) -d若为链接文件,则复制链接属性
cp -a src dst # --all相当于 cp -rpd
mv src dst #剪切文件和目录,重命名 目录不需要-r

链接文件

  • 硬链接 文件索引表中拥有相同的inode号和存储block块,看做同一个文件
    创建后文件引用计数加1
    不能跨分区创建硬链接;目录不能创建硬链接.
    有限制,易混淆,平时不建议用
  • 软链接自己的inode号和block块,但数据块中只保存原文件的文件名和inode号
    类似win快捷方式,删除原文件,软链接不可用
    block中文件名(路径)和inode号都符合才找得到
    软链接文件权限都为rwxrwxrwx,是否可以访问要看原文件的权限
1
ln -s src dis  # link  -s 软链接  src要写绝对路径!除非src和dst在同一目录

文件搜索

locate 文件名

速度快,在数据库(索引)中按文件名查找文件,数据库在/var/lib/mlocate一般一天一更新,updatedb立即更新.
搜索时的排除项(不搜索的内容)配置在/etc/updatedb.conf,如

1
2
3
4
PRUNE_BIND_MOUNTS="yes"
# PRUNENAMES=".git .bzr .hg .svn"
PRUNEPATHS="/tmp /var/spool /media /home/.ecryptfs /var/lib/schroot"
PRUNEFS="NFS nfs nfs4 rpc_pipefs afs binfmt_misc proc smbfs autofs iso9660 ncpfs coda devpts ftpfs devfs mfs shfs sysfs cifs lustre tmpfs usbfs udf fuse.glusterfs fuse.sshfs curlftpfs ecryptfs fusesmb devtmpfs"

whereis 命令名

搜索(外部)命令,配置及其帮助文档所在位置,-b仅可执行文件,-m仅帮助文档.
有些命令找不到,如cd,因为它是shell的内置命令.

1
2
whereis ls
ls: /bin/ls /usr/share/man/man1/ls.1.gz

which 命令名

类似whereis,搜索(外部)命令所在位置及其别名.

echo $PATH

PATH环境变量定义的是系统搜索路径.

find [范围] [选项]

功能非常强大,可能较慢.
find / -name 文件名
文件名需完全匹配,部分匹配用通配符:

符号 意义
* 匹配任意字符
? 匹配任意一个字符
[ ] 匹配任意一个中括号内的字符

find / -iname 文件名 不区分大小写
find / -user 用户名 查找某用户的文件
find / -nouser 查找没有所有者的文件,比如内核创建的文件,外来文件等
find /var/log/ -mtime +10查找10天前修改的文件,一般是日志文件.单位也支持分钟.

参数 说明 参数 说明
-atime 文件访问时间 -10 10天内
-ctime 文件属性修改时间 10 第10天
-mtime 文件修改时间 +10 10天前

find . -size 25k
查找当前目录下大小为25k的文件
注意大小写:

参数 说明 参数 说明
-25k 小于25kb -4M 小于4Mb
25k 等于25kb 4M 等于4Mb
+25k 大于25kb +4M 大于4Mb

find /root -inum 25225
查找inode节点为25225的文件
find /etc -size +20k -a -size -50k
多条件查询,在/etc下找大于20kb小于50kb的文件,-a(and) -o(or)
find /etc -size +20k -a -size -50k -exec ls -lh {} \;
显示查找结果的详细信息,多执行了ls -lh
对find结果执行操作:-exec/-ok 增加的命令 {} \ ;

grep [选项] "字符串" 文件名

在文件当中包含匹配符合条件的,是部分匹配, -i忽略大小写 -v 排除指定字符串