docker实现了更便捷的单机容器虚拟化的管理, docker的位置处于操作系统层与应用层之间;

  • 相对传统虚拟化(KVM,XEN):

    docker可以更加灵活的去实现一些应用层功能, 同时对资源的利用率也更高

  • 相对应用:

    docker可以把应用更操作系统(镜像)做更好的结合, 降低部署与维护的的成本

    处于这样一个位置在单机使用docker进行业务部署是可以感觉到质的提升; 但是针对跨机器, 大规模, 需要对业务质量进行保证的时候, docker本身又有些不足, 而传统的运维自动化工具无论是在docker内部部署还是用来管理docker都显得有些不伦不类.

Kubernetes则实现了大规模,分布式, 并且确保高可用的docker集群的管理.

1: 理解Kubernets

理念:

可以把kuberntes理解为容器级别的自动化运维工具, 之前的针对操作系统(linux, windows)的自动化运维工具比如puppet, saltstack, chef所做的工作是确保代码状态的正确, 配置文件状态的正确, 进程状态的正确, 本质是状态本身的维护; 而kubernetes实际上也是状态的维护, 只不过是容器级别的状态维护; 不过kubernetes在容器级别要做到不仅仅状态的维护, 还需要docker跨机器之间通信的问题.

相关概念

  • 1: pod

    • pod是容器的集合, 每个pod可以包含一个或者多个容器; 为了便于管理一般情况下同一个pod里运行相同业务的容器
    • 同一个pod的容器共享相同的系统栈(网络,存储)
    • 同一个pod只能运行在同一个机器上
  • 2: Replicateion controller

    • 由于这个名字实在是太长了, 以下均用rc代替(kubernetes也知道这个名字比较长, 也是用rc代替)
    • rc是管理pod的, rc负责集群中在任何时候都有一定数量的pod在运行, 多了自动杀, 少了自动加;
    • rc会用预先定义好的pod模版来创建pod; 创建成功后正在运行的pod实例不会随着模版的改变而改变;
    • rc通过SELECTOR(一种系统label)与pod对应起来
    • 当rc中定义的pod数量改变是, rc会自动是运行中的pod数量与定义的数量一致
    • rc还有一种神奇的机制:
      • rolling updates; 比如现在某个服务有5个正在运行的pod, 现在pod本身的业务要更新了, 可以以逐个替换的机制来实现整个rc的更新
  • 3: service

    • services即服务, 真正提供服务的接口,将pod提供的服务暴力到外网, 每个服务后端可以有一个或者多个pod
  • 4: lable
  • label就是标签, kubernetes在pod, service, rc上打了很多个标签(K/V形式的键值对); lable的存储在etcd(一个分布式的高性能,持久化缓存)中; kubernetes用etcd一下子解决了传统服务中的服务之间通信(消息服务)与数据存储(数据库)的问题
架构实现

整个架构大体分为控制节点和计算节点; 控制节点发命令, 计算节点干活.

架构图

首先试图从图本身试图对架构做一些理解

  • 1: 真正提供服务的是node(计算节点), 计算节点的服务通过proxy,在通过防火墙后出去
  • 2: 控制节点和计算节点通过REST的API通信
  • 3: 用户的命令需要授权后调用服务端的API发送到系统
  • 4: 计算节点主要进程为kubelet与proxy
  • 5: 控制节点负责调度, 状态维护

2: Kubernetes部署

主机环境

  • 192.168.56.110

    • etcd
    • kubernetes master
  • 192.168.56.111
    • etcd
    • kubernetes master
  • 192.168.56.112
    • kubernetes master
      操作系统: centos7

110和111部署etcd, 110作为kubenetes的控制节点, 111和112作为计算节点

环境准备:

  • 安装epel源:

       yum install epel-release
  • 关闭防火墙
      systemctl stop firewalld
    systemctl disable firewalld
1: etcd

etcd是一个分布式, 高性能, 高可用的键值存储系统,由CoreOS开发并维护的,灵感来自于 ZooKeeper 和 Doozer,它使用Go语言编写,并通过Raft一致性算法处理日志复制以保证强一致性。

  • 简单: curl可访问的用户的API(HTTP+JSON)
  • 安全: 可选的SSL客户端证书认证
  • 快速: 单实例每秒 1000 次写操作
  • 可靠: 使用Raft保证一致性

  • 1: 安装包:

      yum install etcd -y
  • 2: 编辑配置: /etc/etcd/etcd.conf

      # [member]
    ETCD_NAME=192.168.56.110 #member节点名字 要与后面的ETCD_INITIAL_CLUSTER对应
    ETCD_DATA_DIR="/var/lib/etcd/default.etcd" #数据存储目录
    #ETCD_SNAPSHOT_COUNTER="10000"
    #ETCD_HEARTBEAT_INTERVAL="100"
    #ETCD_ELECTION_TIMEOUT="1000"
    ETCD_LISTEN_PEER_URLS="http://192.168.56.110:2380" #集群同步地址与端口
    ETCD_LISTEN_CLIENT_URLS="http://192.168.56.110:4001" #client通信端口
    #ETCD_MAX_SNAPSHOTS="5"
    #ETCD_MAX_WALS="5"
    #ETCD_CORS=""
    #
    #[cluster]
    ETCD_INITIAL_ADVERTISE_PEER_URLS="http://192.168.56.110:2380" #peer初始化广播端口
    ETCD_INITIAL_CLUSTER="192.168.56.110=http://192.168.56.110:2380,192.168.56.111=http:// 192.168.56.111:2380" #集群成员, 格式: $节点名字=$节点同步端口 节点之前用","隔开
    ETCD_INITIAL_CLUSTER_STATE="new" #初始化状态, 初始化之后会变为existing
    ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster" #集群名字
    ETCD_ADVERTISE_CLIENT_URLS="http://192.168.56.110:4001" #client广播端口
    #ETCD_DISCOVERY=""
    #ETCD_DISCOVERY_SRV=""
    #ETCD_DISCOVERY_FALLBACK="proxy"
    #ETCD_DISCOVERY_PROXY=""
    #
    #[proxy]
    #ETCD_PROXY="off"
    #
    #[security]
    #ETCD_CA_FILE=""
    #ETCD_CERT_FILE=""
    #ETCD_KEY_FILE=""
    #ETCD_PEER_CA_FILE=""
    #ETCD_PEER_CERT_FILE=""
    #ETCD_PEER_KEY_FILE=""

    除ETCD_INITIAL_CLUSTER项目所有节点保持一致外, 其他配置中的IP均为本机IP
    etcd的配置文件不支持每行后面加注释 哈哈, 所以在实际配置过程中需要把每行#后面的注释删掉

  • 3: 启动服务
      systemctl enable etcd
    systemctl start etcd
  • 4: 验证
      #etcdctl member list
    dial tcp 127.0.0.1:2379: connection refused
    #etcd默认连接127.0.0.1的2379端口, 而咱们配置的是192.168.56.110的4001端口
    # etcdctl -C 192.168.56.110:4001 member list
    no endpoints available
    #如果依然出现了上面的问题, 查看服务是否启动
    # netstat -lnp | grep etcd
    tcp 0 0 192.168.56.110:4001 0.0.0.0: LISTEN 18869/etcd
    tcp 0 0 192.168.56.110:2380 0.0.0.0:
    LISTEN 18869/etcd #然后查看端口是否畅通
    telnet 192.168.56.111 4001
    Trying 192.168.56.111...
    Connected to 192.168.56.111.
    Escape character is '^]'.
    ^C
    # etcdctl -C 192.168.56.110:4001 member list
    10f1c239a15ba875: name=192.168.56.110 peerURLs=http://192.168.56.110:2380 clientURLs=http://192.168.56.110:4001
    f7132cc88f7a39fa: name=192.168.56.111 peerURLs=http://192.168.56.111:2380 clientURLs=http://192.168.56.111:4001
  • 5: 准备
      #etcdctl -C 192.168.56.110:4001 mk /coreos.com/network/config '{"Network":"10.0.0.0/16"}'
    {"Network":"10.0.0.0/16"}
    # etcdctl -C 192.168.56.110:4001 get /coreos.com/network/config
    {"Network":"10.0.0.0/16"}

    该配置后面的kubenetes会用到

2: kubenetes
  • 1: 控制节点安装

    • 1: 包安装

      yum -y install kubernetes
    • 2: 配置文件: /etc/kubernetes/apiserver

        ###
      # kubernetes system config
      #
      # The following values are used to configure the kube-apiserver
      #

      # The address on the local server to listen to.
      KUBE_API_ADDRESS="--address=0.0.0.0"

      # The port on the local server to listen on.
      KUBE_API_PORT="--port=8080"

      # Port minions listen on
      KUBELET_PORT="--kubelet_port=10250"

      # Comma separated list of nodes in the etcd cluster
      #KUBE_ETCD_SERVERS="--etcd_servers=http://127.0.0.1:4001"
      KUBE_ETCD_SERVERS="--etcd_servers=http://192.168.56.110:4001,http://192.168.56.111:4001"
      # 修改为咱们配置的etcd服务

      # Address range to use for services
      KUBE_SERVICE_ADDRESSES="--portal_net=192.168.56.150/28"
      # 外网网段, kubenetes通过改网络把服务暴露出去

      # default admission control policies
      KUBE_ADMISSION_CONTROL="--admission_control=NamespaceAutoProvision,LimitRanger,ResourceQuota"
      # Add your own!
      KUBE_API_ARGS=""

      kubenetse的配置文件不支持每行后面加注释, 实际生产中需要将每行后面的解释删掉

    • 3: 启动服务

      API的启动脚本有问题
      /usr/lib/systemd/system/kube-apiserver.service

        [Unit]
      Description=Kubernetes API Server
      Documentation=https://github.com/GoogleCloudPlatform/kubernetes
      [Service]
      PermissionsStartOnly=true
      ExecStartPre=-/usr/bin/mkdir /var/run/kubernetes
      ExecStartPre=-/usr/bin/chown -R kube:kube /var/run/kubernetes/
      EnvironmentFile=-/etc/kubernetes/config
      EnvironmentFile=-/etc/kubernetes/apiserver
      User=kube
      ExecStart=/usr/bin/kube-apiserver \
      $KUBE_LOGTOSTDERR \
      $KUBE_LOG_LEVEL \
      $KUBE_ETCD_SERVERS \
      $KUBE_API_ADDRESS \
      $KUBE_API_PORT \
      $KUBELET_PORT \
      $KUBE_ALLOW_PRIV \
      $KUBE_SERVICE_ADDRESSES \
      $KUBE_ADMISSION_CONTROL \
      $KUBE_API_ARGS
      Restart=on-failure
      LimitNOFILE=65536
      [Install]
      WantedBy=multi-user.target

      启动服务

        systemctl enable kube-apiserver kube-controller-manager kube-scheduler
      systemctl restart kube-apiserver kube-controller-manager kube-scheduler
    • 4: 验证
        # ps aux | grep kube
      kube 20505 5.4 1.6 45812 30808 ? Ssl 22:05 0:07 /usr/bin/kube-apiserver --logtostderr=true --v=0 --etcd_servers=http://192.168.56.110:2380,http://192.168.56.110:2380 --address=0.0.0.0 --allow_privileged=false --portal_net=192.168.56.0/24 --admission_control=NamespaceAutoProvision,LimitRanger,ResourceQuota
      kube 20522 1.8 0.6 24036 12064 ? Ssl 22:05 0:02 /usr/bin/kube-controller-manager --logtostderr=true --v=0 --machines=127.0.0.1 --master=http://127.0.0.1:8080
      kube 20539 1.3 0.4 17420 8760 ? Ssl 22:05 0:01 /usr/bin/kube-scheduler --logtostderr=true --v=0 --master=http://127.0.0.1:8080
      # kubectl cluster-info
      Kubernetes master is running at http://localhost:8080
  • 2: 计算节点安装

    • 1: 包安装

      yum -y install kubernetes docker flannel bridge-utils net-tools
    • 2: 配置文件
      • /etc/kubernetes/config

        ###
        # kubernetes system config
        #
        # The following values are used to configure various aspects of all
        # kubernetes services, including
        #
        # kube-apiserver.service
        # kube-controller-manager.service
        # kube-scheduler.service
        # kubelet.service
        # kube-proxy.service
        # logging to stderr means we get it in the systemd journal
        KUBE_LOGTOSTDERR="--logtostderr=true"
        # journal message level, 0 is debug
        KUBE_LOG_LEVEL="--v=0"
        # Should this cluster be allowed to run privileged docker containers
        KUBE_ALLOW_PRIV="--allow_privileged=false"
        # How the controller-manager, scheduler, and proxy find the apiserver
        KUBE_MASTER="--master=http://192.168.56.110:8080" #将改IP改为控制节点IP
      • /etc/kubernetes/kubelet
        ###
        # kubernetes kubelet (minion) config
        # The address for the info server to serve on (set to 0.0.0.0 or "" for all interfaces)
        KUBELET_ADDRESS="--address=192.168.56.111" #本机地址
        # The port for the info server to serve on
        KUBELET_PORT="--port=10250"
        # You may leave this blank to use the actual hostname
        KUBELET_HOSTNAME="--hostname_override=192.168.56.111" #本机地址
        # location of the api-server
        KUBELET_API_SERVER="--api_servers=http://192.168.56.110:8080" #控制节点地址
        # Add your own!
        KUBELET_ARGS="--pod-infra-container-image=docker.io/kubernetes/pause:latest"
        #kubenet服务的启动需要依赖以pause这个镜像, 默认kubenet会从google镜像服务下载, 而由于*原因, 下载不成功, 这里我们指定为的docker的镜像
        #镜像下载: docker pull docker.io/kubernetes/pause
      • /etc/sysconfig/flanneld
        # Flanneld configuration options
        # etcd url location. Point this to the server where etcd runs
        FLANNEL_ETCD="http://192.168.56.110:4001,http://192.168.56.111:4001" #修改为etcd服务地址
        # etcd config key. This is the configuration key that flannel queries
        # For address range assignment
        FLANNEL_ETCD_KEY="/coreos.com/network"
        # Any additional options that you want to pass
        #FLANNEL_OPTIONS=""
    • 3: 服务修改

      kubernetes的默认服务启动有问题, 需要做写调整

      cat /usr/lib/systemd/system/kubelet.service

        [Unit]
      Description=Kubernetes Kubelet Server
      Documentation=https://github.com/GoogleCloudPlatform/kubernetes
      After=docker.service
      Requires=docker.service
      [Service]
      WorkingDirectory=/var/lib/kubelet
      EnvironmentFile=-/etc/kubernetes/config
      EnvironmentFile=-/etc/kubernetes/kubelet
      ExecStart=/usr/bin/kubelet \
      $KUBE_LOGTOSTDERR \
      $KUBE_LOG_LEVEL \
      $KUBELET_API_SERVER \
      $KUBELET_ADDRESS \
      $KUBELET_PORT \
      $KUBELET_HOSTNAME \
      $KUBE_ALLOW_PRIV \
      $KUBELET_ARGS
      LimitNOFILE=65535
      LimitNPROC=10240
      Restart=on-failure
      [Install]
      WantedBy=multi-user.target

      调整docker网络

        systemctl start docker
      systemctl stop docker
      ifconfig docker0 down
      brctl delbr docker0

      启动服务

        systemctl enable kube-proxy kubelet flanneld docker
      systemctl restart kube-proxy kubelet flanneld docker
    • 验证
        # kubectl get nodes
      NAME LABELS STATUS
      192.168.56.111 kubernetes.io/hostname=192.168.56.111 Ready
      192.168.56.112 kubernetes.io/hostname=192.168.56.112 Ready

3: Kubernetes使用

3.1 基本应用

kubenetes的管理实际上就是针对pod, rc, services的管理, 命令行针对kubenetes的管理建议基于配置文件进行, 这样更便于管理, 也更规范

    kubectl create -h
Create a resource by filename or stdin.
JSON and YAML formats are accepted.
Usage:
kubectl create -f FILENAME [flags]
Examples:
// Create a pod using the data in pod.json.
$ kubectl create -f pod.json
// Create a pod based on the JSON passed into stdin.
$ cat pod.json | kubectl create -f -
  • 格式规范:

      apiVersion: v1beta3 #API版本, 要在 kubectl api-versions
    kind: ReplicationController #Pod, ReplicationController, Service
    metadata: #元数据, 主要是name与label
    name: test
    spec: #配置, 根据不同的kind, 具体配置项会有所不同
    ***

    kubenetes支持yaml或者json的文件输入, json的用API来处理的时候比较方便, yaml对人更友好一些, 以下用yaml格式.
    一个典型的业务大概架构类似这样:

        +-----------+
    | |
    | logic | #逻辑处理服务
    | |
    +---+--+----+
    | |
    +----+ +----+
    | |
    | |
    +----v-----+ +----v----+
    | | | |
    | DB | | redis | #调用其他服务
    | | | |
    +----------+ +---------+

思路: 每个pod内提供一组完整的服务

  • 1: 准备镜像

    • postgres: 数据库镜像
    • redis: 缓存服务镜像
    • wechat: 微信服务镜像
  • 2: rc配置wechat-rc.yaml:

      apiVersion: v1beta3
    kind: ReplicationController
    metadata:
    name: wechatv4
    labels:
    name: wechatv4
    spec:
    replicas: 1
    selector:
    name: wechatv4
    template:
    metadata:
    labels:
    name: wechatv4
    spec:
    containers:
    - name: redis
    image: redis
    ports:
    - containerPort: 6379
    - name: postgres
    image: opslib/wechat_db
    ports:
    - containerPort: 5432
    - name: wechat
    image: opslib/wechat1
    ports:
    - containerPort: 80

    导入rc

      # kubectl create -f wechat-rc.yaml
    replicationcontrollers/wechat

    确认
    <img src="./getpods.png" width=800>
    :
    在docker中可以利用link功能将容器之间连接起来, 而在kubenetes中是没有这样的系统的, 但是由于同一个pod内是共享网络存储相关空间的,在wechat的镜像中的配置文件中, 连接数据库和redis的配置项中的IP可以直接写'127.0.0.1', 类似这样:

      sql_connection='postgresql://wechat:wechatpassword@127.0.0.1/wechat'
    cached_backend='redis://127.0.0.1:6379/0'
  • 3: 服务配置wechat-service.yaml
      apiVersion: v1beta3
    kind: Service
    metadata:
    name: wechat
    labels:
    name: wechat
    spec:
    ports:
    - port: 80
    selector:
    name: wechatv4

    导入

      # kubectl create -f wechat-service.yaml
    services/wechat

    查看

      kubectl get service wechat
    NAME LABELS SELECTOR IP(S) PORT(S)
    wechat name=wechat name=wechatv4 192.168.56.156 80/TCP

    确认

      # curl -i http://192.168.56.156
    HTTP/1.1 200 OK
    Content-Length: 0
    Access-Control-Allow-Headers: X-Auth-Token, Content-type
    Server: TornadoServer/4.2
    Etag: "da39a3ee5e6b4b0d3255bfef95601890afd80709"
    Date: Mon, 06 Jul 2015 09:04:49 GMT
    Access-Control-Allow-Origin: *
    Access-Control-Allow-Methods: GET, POST, PUT, DELETE
    Content-Type: application/json

3.2 业务更新

基本的业务部署完成后, 在服务要更新的时候, kubenetes可以利用滚动更新,基本上实现了业务的热更新.

#kubectl rolling-update wechatv3 -f wechatv3.yaml
Creating wechatv4
At beginning of loop: wechatv3 replicas: 0, wechatv4 replicas: 1
Updating wechatv3 replicas: 0, wechatv4 replicas: 1
At end of loop: wechatv3 replicas: 0, wechatv4 replicas: 1
Update succeeded. Deleting wechatv3
wechatv4

3.3 应用管理

当需要同一服务需要启动多个实例, 服务本身一样, 但是启动服务的配置不一样时候
一般我们可能会有3种需求:

  • 1: 不同的container设置不同的资源权限
  • 2: 不同的container挂载不同的目录
  • 3: 不同的container执行不同的启动命令

可以在配置文件中针对不同的container设置不同的设置.

apiVersion: v1beta3
kind: ReplicationController
metadata:
name: new
labels:
name: new
spec:
replicas: 1
selector:
name: new
template:
metadata:
labels:
name: new
spec:
containers:
- name: redis
image: redis
ports:
- containerPort: 6379
- name: postgres
image: opslib/wechat_db
ports:
- containerPort: 5432
- name: wechat
image: opslib/wechat1
command: #container的启动命令有外部定义
- '/bin/bash'
- '-c'
- '/usr/bin/wechat_api'
- '--config=/etc/wechat/wechat.conf'
resources: #限制container的资源
request: #请求的资源
cpu: "0.5"
memory: "512Mi"
limits: #最大可以使用的资源
cpu: "1"
memory: "1024Mi"
ports:
- containerPort: 80
volumeMounts: #挂载目录
- name: data
mountPath: /data
volumes:
- name: data
参考文章:
文/Harvey_L(简书作者)
原文链接:http://www.jianshu.com/p/40d171c3b950
著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。

kubernetes学习笔记的更多相关文章

  1. Kubernetes 学习笔记(一):基础概念

    个人笔记,仅本人查阅使用,不保证正确. 零.微服务 微服务架构专注于应用解耦合,通过将应用彻底地组件化和服务化,每个微服务只包含一个非常小的功能,比如权限管理.日志收集等等.由这一组微服务组合起来,提 ...

  2. Kubernetes学习笔记(八):Deployment--声明式的升级应用

    概述 本文核心问题是:如何升级应用. 对于Pod的更新有两种策略: 一是删除全部旧Pod之后再创建新Pod.好处是,同一时间只会有一个版本的应用存在:缺点是,应用有一段时间不可用. 二是先创建新Pod ...

  3. Kubernetes学习笔记(四):服务

    服务介绍 服务是一种为一组相同功能的pod提供单一不变接入点的资源.当服务存在时,他的IP和端口不会改变.客户端通过IP和端口建立连接,这些连接会被路由到任何一个pod上.如此,客户端不需要知道每个单 ...

  4. Kubernetes学习笔记之认识Kubernetes组件

    前言:笔记知识点来源于Kubernetes官方文档说明,链接:https://kubernetes.io/docs/concepts/overview/components/ ,本记录仅仅是学习笔记记 ...

  5. 深入剖析Kubernetes学习笔记:开篇词(00)

    一.关于Kubernetes初学的疑惑 就在这场因"容器"而起的技术变革中,kubernetes项目已经成为容器技术的事实标准,重新定义了基础设置领域对应用编排与管理的种种可能 1 ...

  6. kubernetes学习笔记(二)——部署服务

    文章目录 (1)创建app (2)创建app的docker镜像 (3)部署app到k8s (4)参考资料 前面一篇文章部署好了minikube环境,这次学习下怎么部署app到kubernetes环境当 ...

  7. kubernetes学习笔记(一)——minikube安装记录

    想学习一下kubernetes,于是先安装一个单机版来学习一下.但是就是这个最简单的单机版安装方式都倒腾了我好久,记录下自己的安装过程.博主是在windows利用vmware workstation安 ...

  8. Kubernetes 学习笔记(二):本地部署一个 kubernetes 集群

    前言 前面用到过的 minikube 只是一个单节点的 k8s 集群,这对于学习而言是不够的.我们需要有一个多节点集群,才能用到各种调度/监控功能.而且单节点只能是一个加引号的"集群&quo ...

  9. 【Kubernetes学习笔记】-使用Minikube快速部署K8S单机学习环境

    介绍 https://minikube.sigs.k8s.io/docs/ Minikube 用于快速在本地搭建 Kubernetes 单节点集群环境,它对硬件资源没有太高的要求,方便开发人员学习试用 ...

  10. 【Kubernetes学习笔记】-服务访问之 IP & Port & Endpoint 辨析

    目录 不同类型的IP Pod IP Cluster IP 不同类型的Port port nodePort TargetPort containerPort hostPort Endpoint Endp ...

随机推荐

  1. eclipse 引用自己开发的模块

    这样就可以 生成的是LIB 工程需要设置“Is Library”

  2. java 调用微信截图工具

  3. mybatis热加载的实现

    最近在使用mybatis,由于是刚刚开始用,用的并不顺手,目前是感觉有2个地方非常的不好用: 1.mybatis调试不方便 由于dao层只有接口,实现只是一个map的xml文件,想加断点都没有地方加, ...

  4. "无法启动应用程序,工作组信息文件丢失,或是已被其他用户已独占方式打开"解决办法

    当程序用ado的jet4.0方式连接mdb数据库的时候,对于设有access数据库密码的mdb的访问居然报错“无法启动应用程序,工作组信息文件丢失,或是已被其他用户已独占方式打开”. ADOConne ...

  5. WPF调用图片路径,或资源图片

    一.加载本项目的图片WPF引入了统一资源标识Uri(Unified Resource Identifier)来标识和访问资源.其中较为常见的情况是用Uri加载图像.Uri表达式的一般形式为:协议+授权 ...

  6. 深入剖析 redis 事件驱动

    概述 redis 内部有一个小型的事件驱动,它和 libevent 网络库的事件驱动一样,都是依托 I/O 多路复用技术支撑起来的. 利用 I/O 多路复用技术,监听感兴趣的文件 I/O 事件,例如读 ...

  7. ECshop导入淘宝数据包乱码问题解决方法

    ECshop在导入淘宝数据包的时候出现数据乱码. 测试版本 ecshop2.73 利用淘宝助手导出一个数据包(.csv),不要一次全部商品导出,最好是将数据包控制在1M左右,因为ecshop对上传文件 ...

  8. Photoshop CS6 for Mac简体中文正式 完美破解版 支持Retina屏

    Photoshop CS6 MAC 中文版破解版 支持Retina屏 目前世界上“最好的化妆品”是一款叫做PhotoShop的产品,它可以帮你去除所有你不满意的地方.上周末,这款最好的化妆品推出了第十 ...

  9. R语言之中文分词:实例

    一.说明 网上提供的一个例子,做了修改与订正. 二.程序 #调入分词的库 library("rJava") library("Rwordseg") #调入绘制词 ...

  10. SVN: bdb: BDB1538 Program version 5.3 doesn't match environment version 4.7

    Q:bdb: BDB1538 Program version 5.3 doesn't match environment version 4.7 A: svnadmin recover /var/wh ...