ORM 设计模式

什么是ORM?

ORM全称Object Relational Mapping,中文是对象关系映射。它其实是创建了一个可在编程语言里使用的–“虚拟对象数据库”。我们在具体的操作实体对象的时候,就不需要再去和复杂的 SQL 语句打交道,只需简单的操作实体对象的属性和方法。至于这个对象里的数据该怎么存储又该怎么获取,通通不用关心。大大缩短了程序员的编码时间,减少了程序员对数据库的学习成本。对于敏捷开发和团队合作开发来说,好处是非常非常大的。

当然,省事的东西往往是靠牺牲性能换来的,ORM也不例外,在处理多表联查、where条件复杂之类的查询时,ORM的语法会变得复杂因而降低效率,而且越是功能强大的ORM越是消耗内存。

ORM一般都针对数据模型提供了一下常见的接口函数,比如:create(), update(), save(), load(), find(), find_all(), where()等,也就是讲sql查询全部封装成了编程语言中的函数,通过函数的链式组合生成最终的SQL语句。

常见的ORM框架有:Java的Hibernate、以及很多php框架自带的ORM库。

数据库的设计模式

  • Row Data Gateway
  • Table Data Gateway
  • Active Record(活动记录)
  • Data Mapper(数据映射)
  • Identity Map

Row Data Gateway

一个对象扮演的角色就像是数据库中单行记录,每个对象对应一行.


Chrome 的内存优化插件 Great Suspender

平时打开Chrome,常常打开十几个网页标签或者更多。内存消耗极快。尤其是在打开5、60个标签页的时候,电脑基本上就出现准备死机的征兆了。每当出现这种情况时,操作系统就开始把数据分载到硬盘的缓存中,此时机器的速度就严重下降。

Great Suspender的目的是节省内存,效果很好。它会暂时关闭掉所有标签的网页响应,除了现在你正在阅读的这个,而当你切换到另一个标签时,它就会重载这个标签的网页。

(内存优化插件Great Suspender)

参考资料


转载 | Docker常用命令

  1. 查看docker信息(version、info)

     # 查看docker版本
     $docker version
    
     # 显示docker系统的信息
     $docker info
    
  2. 对image的操作(search、pull、images、rmi、history)

     # 检索image
     $docker search image_name
    
     # 下载image
     $docker pull image_name
    
     # 列出镜像列表; -a, --all=false Show all images; --no-trunc=false Don't truncate output; -q, --quiet=false Only show numeric IDs
     $docker images
    
     # 删除一个或者多个镜像; -f, --force=false Force; --no-prune=false Do not delete untagged parents
     $docker rmi image_name
    
     # 显示一个镜像的历史; --no-trunc=false Don't truncate output; -q, --quiet=false Only show numeric IDs
     $docker history image_name
    
  3. 启动容器(run)

    docker容器可以理解为在沙盒中运行的进程。这个沙盒包含了该进程运行所必须的资源,包括文件系统、系统类库、shell 环境等等。但这个沙盒默认是不会运行任何程序的。你需要在沙盒中运行一个进程来启动某一个容器。这个进程是该容器的唯一进程,所以当该进程结束的时候,容器也会完全的停止。

     # 在容器中运行"echo"命令,输出"hello word"
     $docker run image_name echo "hello word"
    
     # 交互式进入容器中
     $docker run -i -t image_name /bin/bash
    
     # 在容器中安装新的程序
     $docker run image_name apt-get install -y app_name
     Note:  在执行apt-get 命令的时候,要带上-y参数。如果不指定-y参数的话,apt-get命令会进入交互模式,需要用户输入命令来进行确认,但在docker环境中是无法响应这种交互的。apt-get 命令执行完毕之后,容器就会停止,但对容器的改动不会丢失。
    
  4. 查看容器(ps)

     # 列出当前所有正在运行的container
     $docker ps
     # 列出所有的container
     $docker ps -a
     # 列出最近一次启动的container
     $docker ps -l
    
  5. 保存对容器的修改(commit)

    当你对某一个容器做了修改之后(通过在容器中运行某一个命令),可以把对容器的修改保存下来,这样下次可以从保存后的最新状态运行该容器。

     # 保存对容器的修改; -a, --author="" Author; -m, --message="" Commit message
     $docker commit ID new_image_name
     Note:  image相当于类,container相当于实例,不过可以动态给实例安装新软件,然后把这个container用commit命令固化成一个image。
    
  6. 对容器的操作(rm、stop、start、kill、logs、diff、top、cp、restart、attach)

     # 删除所有容器
     $docker rm `docker ps -a -q`
    
     # 删除单个容器; -f, --force=false; -l, --link=false Remove the specified link and not the underlying container; -v, --volumes=false Remove the volumes associated to the container
     $docker rm Name/ID
    
     # 停止、启动、杀死一个容器
     $docker stop Name/ID
     $docker start Name/ID
     $docker kill Name/ID
    
     # 从一个容器中取日志; -f, --follow=false Follow log output; -t, --timestamps=false Show timestamps
     $docker logs Name/ID
    
     # 列出一个容器里面被改变的文件或者目录,list列表会显示出三种事件,A 增加的,D 删除的,C 被改变的
     $docker diff Name/ID
    
     # 显示一个运行的容器里面的进程信息
     $docker top Name/ID
    
     # 从容器里面拷贝文件/目录到本地一个路径
     $docker cp Name:/container_path to_path
     $docker cp ID:/container_path to_path
    
     # 重启一个正在运行的容器; -t, --time=10 Number of seconds to try to stop for before killing the container, Default=10
     $docker restart Name/ID
    
     # 附加到一个运行的容器上面; --no-stdin=false Do not attach stdin; --sig-proxy=true Proxify all received signal to the process
     $docker attach ID
     Note: attach命令允许你查看或者影响一个运行的容器。你可以在同一时间attach同一个容器。你也可以从一个容器中脱离出来,是从CTRL-C。
    
  7. 保存和加载镜像(save、load)

    当需要把一台机器上的镜像迁移到另一台机器的时候,需要保存镜像与加载镜像。

     # 保存镜像到一个tar包; -o, --output="" Write to an file
     $docker save image_name -o file_path
     # 加载一个tar包格式的镜像; -i, --input="" Read from a tar archive file
     $docker load -i file_path
    
     # 机器a
     $docker save image_name > /home/save.tar
     # 使用scp将save.tar拷到机器b上,然后:
     $docker load < /home/save.tar
    

8、 登录registry server(login)

    # 登陆registry server; -e, --email="" Email; -p, --password="" Password; -u, --username="" Username
    $docker login
  1. 发布image(push)

     # 发布docker镜像
     $docker push new_image_name
    
  2. 根据Dockerfile 构建出一个容器

    #build –no-cache=false Do not use cache when building the image -q, –quiet=false Suppress the verbose output generated by the containers –rm=true Remove intermediate containers after a successful build -t, –tag=”” Repository name (and optionally a tag) to be applied to the resulting image in case of success $docker build -t image_name Dockerfile_path

转载自 tuicool

其他资料


Linux 判断一个命令是否存在

在命令行时,我们常使用 which xxx 或者 whereis xxx 来判断某个命令是否存在。然而在编写 bash 时,应该避免使用 which 命令。

原因是 which 做为一个外部的工具,并不一定存在,在发行版之间也会有区别,有的系统的 which 命令不会设置有效的 exit status,存在一定的不确定性。

Bash 提供的内建命令如 hash、type、command 可以达到要求。例如:

$ command -v foo >/dev/null 2>&1 || { echo >&2 "I require foo but it's not installed.  Aborting."; exit 1; }
$ type foo >/dev/null 2>&1 || { echo >&2 "I require foo but it's not installed.  Aborting."; exit 1; }
$ hash foo 2>/dev/null || { echo >&2 "I require foo but it's not installed.  Aborting."; exit 1; }

编写方法时,可以这么编写:

gnudate() {
    if hash gdate 2>/dev/null; then
        gdate "$@"
    else
        date "$@"
    fi
}

参考资料


Docker run命令

Docker会在隔离的容器中运行进程。当运行 docker run 命令时,Docker会启动一个进程,并为这个进程分配其独占的文件系统、网络资源和以此进程为根进程的进程组。

docker run可以控制一个容器运行时的行为,它可以覆盖docker build在构建镜像时的一些默认配置,这也是为什么run命令相比于其它命令有如此多的参数的原因。

命令格式

最基本的docker run命令的格式如下:

$ sudo docker run [OPTIONS] IMAGE[:TAG] [COMMAND] [ARG...]

docker run [OPTIONS]可以让用户完全控制容器的生命周期,并允许用户覆盖执行docker build时所设定的参数,甚至也可以修改本身由Docker所控制的内核级参数。

OPTIONS总起来说可以分为两类:

  1. 设置运行方式:

    • 决定容器的运行方式,前台执行还是后台执行 -d -a -t -i
    • 设置containerID –name –cidfile
    • IPC(命名空间) –ipc
    • 设置网络参数
    • 设置容器的CPU和内存参数;
      • 设置权限和LXC参数;
  2. 设置镜像的默认资源,也就是说用户可以使用该命令来覆盖在镜像构建时的一些默认配置。

先对照几个例子:

$ docker run -d -p 54285:54285 oddrationale/docker-shadowsocks -s 0.0.0.0 -p 54285 -k yourpasswd -m aes-256-cfb
$ docker run -d --name web -p 8080:80 joshhu/webdemo

前台vs后台 -d -a -t -i

当我们启动一个容器时,首先需要确定这个容器是运行在前台还是运行在后台。

如果在docker run后面追加-d=true或者-d,那么容器将会运行在后台模式。此时所有I/O数据只能通过网络资源或者共享卷组来进行交互。因为容器不再监听你执行docker run的这个终端命令行窗口。但你可以通过执行docker attach来重新附着到该容器的回话中。

在前台模式下(不指定-d参数即可),Docker会在容器中启动进程,同时将当前的命令行窗口附着到容器的标准输入、标准输出和标准错误中:

-a=[]               : Attach to `STDIN`, `STDOUT` and/or `STDERR`
-t=false            : Allocate a pseudo-tty
--sig-proxy=true : Proxify all received signal to the process (non-TTY mode only)
-i=false            : Keep STDIN open even if not attached

如果在执行run命令时没有指定-a参数,那么Docker默认会挂载所有标准数据流,包括输入输出和错误,你可以单独指定挂载哪个标准流。

$ sudo docker run -a stdin -a stdout -i -t ubuntu /bin/bash

如果要进行交互式操作(例如Shell脚本),那我们必须使用-i -t参数同容器进行数据交互。但是当通过管道同容器进行交互时,就不需要使用-t参数,例如下面的命令:

echo test | docker run -i busybox cat

容器识别 –name –cidfile

  1. Name –name

    可以通过三种方式为容器命名:

    1. 使用UUID长命名(”f78375b1c487e03c9438c729345e54db9d20cfa2ac1fc3494b6eb60872e74778”)
    2. 使用UUID短命令(”f78375b1c487”)
    3. 使用Name(“evil_ptolemy”)

    这个UUID标示是由Docker deamon生成的。如果你在执行docker run时没有指定–name,那么deamon会自动生成一个随机字符串UUID。但是对于一个容器来说有个name会非常方便,当你需要连接其它容器时或者类似需要区分其它容器时,使用容器名称可以简化操作。

  2. PID –cidfile

    如果在使用Docker时有自动化的需求,你可以将containerID输出到指定的文件中(PIDfile),类似于某些应用程序将自身ID输出到文件中,方便后续脚本操作。 –cidfile=””: Write the container ID to the file

Image[:tag]

当一个镜像的名称不足以分辨这个镜像所代表的含义时,你可以通过tag将版本信息添加到run命令中,以执行特定版本的镜像。例如: docker run ubuntu:14.04

命名空间 –ipc

默认情况下,所有容器都开启了IPC命名空间。

--ipc=""  : Set the IPC mode for the container,
        'container:<name|id>': reuses another container's IPC namespace
        'host': use the host's IPC namespace inside the container

IPC(POSIX/SysV IPC)命名空间提供了相互隔离的命名共享内存、信号灯变量和消息队列。

共享内存可以提高进程数据的交互速度。共享内存一般用在数据库和高性能应用(C/OpenMPI、C++/using boost libraries)上或者金融服务上。如果需要容器中部署上述类型的应用,那么就应该在多个容器直接使用共享内存了。

网络设置

默认情况下,所有的容器都开启了网络接口,同时可以接受任何外部的数据请求。

-h HOSTNAME or --hostname=HOSTNAME --配置容器主机名
--link=CONTAINER_NAME:ALIAS --添加到另一个容器的连接
--net=bridge|none|container:NAME_or_ID|host --配置容器的桥接模式
-p SPEC or --publish=SPEC --映射容器端口到宿主主机
-P or --publish-all=true|false --映射容器所有端口到宿主主机
--dns=[]         : Set custom dns servers for the container
--add-host=""    : Add a line to /etc/hosts (host:IP)
--mac-address="" : Sets the container's Ethernet device's MAC address

例如开篇的例子:

$ docker run -d --name web -p 8080:80 joshhu/webdemo

-p 8080:80 把 host 的 8080端口流量转发到 web 的80端口。

Clean up (–rm)

默认情况下,每个容器在退出时,它的文件系统也会保存下来,这样一方面调试会方便些,因为你可以通过查看日志等方式来确定最终状态。另外一方面,你也可以保存容器所产生的数据。但是当你仅仅需要短暂的运行一个容器,并且这些数据不需要保存,你可能就希望Docker能在容器结束时自动清理其所产生的数据。

注意:–rm 和 -d不能共用!

--rm=false: Automatically remove the container when it exits (incompatible with -d)

安全设置 –security-opt

--security-opt="label:user:USER"   : Set the label user for the container
--security-opt="label:role:ROLE"   : Set the label role for the container
--security-opt="label:type:TYPE"   : Set the label type for the container
--security-opt="label:level:LEVEL" : Set the label level for the container
--security-opt="label:disable"     : Turn off label confinement for the container
--secutity-opt="apparmor:PROFILE"  : Set the apparmor profile to be applied  to the container

性能设置 -m -c

-m="": Memory limit (format: <number><optional unit>, where unit = b, k, m or g)
-c=0 : CPU shares (relative weight)

运行时特权 LXC设置

  --cap-add: Add Linux capabilities
  --cap-drop: Drop Linux capabilities
  --privileged=false: Give extended privileges to this container
  --device=[]: Allows you to run devices inside the container without the --privileged flag.
  --lxc-conf=[]: (lxc exec-driver only) Add custom lxc options --lxc-conf="lxc.cgroup.cpuset.cpus = 0,1"

重写Dockerfile

这些参数中,有四个是无法被覆盖的:FROM、MAINTAINER、RUN和ADD,其余参数都可以通过docker run进行覆盖。

  1. CMD (Default Command or Options)
  2. ENTRYPOINT (Default Command to Execute at Runtime)
  3. EXPOSE (Incoming Ports)
  4. ENV (Environment Variables)
  5. VOLUME (Shared Filesystems)
  6. USER
  7. WORKDIR   

参考资料


更新Linux内核至4.9

aptitude install initramfs-tools
apt-get install --reinstall grub

mkdir /boot/grub

Searching for GRUB installation directory ... found: /boot/grub
Probing devices to guess BIOS drives. This may take a long time.
Unknown partition table signature
Unknown partition table signature
Searching for default file ... Generating /boot/grub/default file and setting the default boot entry to 0
Searching for GRUB installation directory ... found: /boot/grub
Testing for an existing GRUB menu.lst file ...


Generating /boot/grub/menu.lst
Searching for splash image ... none found, skipping ...
Found kernel: /boot/vmlinuz-4.10.0-041000-generic
Found kernel: /boot/vmlinuz-3.16.0-4-amd64
Updating /boot/grub/menu.lst ... done

参考资料