凤凰花开芙蓉畔


  • 首页

  • 分类

  • 归档

  • 标签

从操作系统的角度聊聊CPU和IO设备

发表于 2016-06-20   |   分类于 IO   |  

操作系统的发展过程

无操作系统时代

1945年到上世纪50年代中期,这时还未出现OS,需要程序员使用人工方式直接使用计算机硬件系统,将穿孔的纸带装入纸带输入机,将程序和数据输入到计算机中,然后启动计算机运行;运行完毕后取走计算结果。

  1. 用户独占全机的全部资源,每个用户需要等待上一个用户操作完全完成。
  2. CPU等待人工操作。

为了解决人机矛盾,出现了脱机输入/输出(Off-Line I/O),输入数据量大,CPU等待时间长,引入外围机作中转,将数据通过外围机输入到磁带上,主机在需要的时候直接读取磁带,解决CPU在等待时,资源的浪费为。

单道批处理系统

由监控程序,每次保着将磁带上的一个作业装入内存,旨在提高资源的利用率和系统的吞吐量。系统中始终只保持一道程序。具备:自动性、顺序性、单道性。

多道批处理系统

CPU等待IO设备结果时,可以被系统调度出去,暂时中断其对CPU的占用,是其他程序可以使用CPU,待IO处理完成后再由系统调度回来。具备:多道性、无序性(先进入内存的作业可能较后完成)、调度性。

内存中驻留躲到程序,可保持资源处于忙碌状态,资源充分利用。CPU和其他资源保持“忙碌”状态,挡作业运行完成或运行不下去的时候才进行切换,开销小。

批处理系统推动了多任务操作系统的发展。

分时系统

多用户样子的系统,一台主机上,连接了多个带有显示器和键盘的终端,允许同时多个用户通过自己的终端,以交互的方式使用计算机,共享主机中的资源。

及时接收:多路卡连接终端,缓冲区暂存键入的命令或数据。

及时处理:作业不能先存于磁盘再调入内容,因为磁盘中的作业不能运行,也不能进行交互;不允许一个作业长期占用cpu,只在运行完毕或出现IO请求才被调度是不合适的。采用时间片轮转的方式,让每个作业都能运行一小段时间,这样,在一个不长的时间内会感觉所有用户所有作业都在得到响应。

实时系统

及时响应外部事件的请求。

操作系统的特性

并发、共享、虚拟、异步。其中并发是其他三个的前提。
并发和并行的差别。并行指同一时刻发生;并发指同一时间间隔内发生。

好文章列表(不断更新)

发表于 2016-06-20   |   分类于 article   |  

并发

http://ifeve.com/java-synchronized/ 方腾飞老师的聊聊并发系列

CountDownLatch

发表于 2016-06-15   |   分类于 juc   |  
package juc.test;
/**
 * 可以在闭锁上等待,每次执行countdown后,count-1,当count=0时,等待的线程被唤醒
 */
public class CountDownLatch {
    /**
     * 内部类,使用AQS同步,利用AQS的state做计数count
     */
    private static final class Sync extends AbstractQueuedSynchronizer {
        private static final long serialVersionUID = 4982264981922014374L;

        Sync(int count) {
            setState(count);
        }

        int getCount() {
            return getState();
        }

        /*
         * count=0请求成功;否则,请求失败,请求线程将被阻塞
         * 闭锁只有共享模式
         */
        protected int tryAcquireShared(int acquires) {
            return (getState() == 0) ? 1 : -1;
        }
        /*
         * 释放
         */
        protected boolean tryReleaseShared(int releases) {
            // Decrement count; signal when transition to zero
            for (;;) {
                int c = getState();
                if (c == 0) // 闭锁已经是0,无需释放
                    return false;
                int nextc = c-1;
                if (compareAndSetState(c, nextc)) // CAS修改count=count-1
                    // 如果修改后为0表示闭锁已经打开,返回true;否则,说明还有等待的,闭锁处于关闭状态,返回false
                    return nextc == 0;
            }
        }
    }

    private final Sync sync;

    /*
     * 根据给定count值构造闭锁
     */
    public CountDownLatch(int count) {
        if (count < 0) throw new IllegalArgumentException("count < 0");
        this.sync = new Sync(count);
    }

     /* 
      * 如果当前count为0,那么方法立即返回。 
      * 如果当前count不为0,那么当前线程会一直等待,直到count被(其他线程)减到0或者当前线程被中断。 
      */  
    public void await() throws InterruptedException {
        sync.acquireSharedInterruptibly(1); // AQS中的实现
    }

    /*
     * 超时版await
     */
    public boolean await(long timeout, TimeUnit unit)
        throws InterruptedException {
        return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
    }

    /*
     * 递减count,当减到0时,唤醒所有等待的线程去调度。如果当前count是0,则什么都不会发生
     */
    public void countDown() {
        sync.releaseShared(1);
    }

    public long getCount() {
        return sync.getCount();
    }

    public String toString() {
        return super.toString() + "[Count = " + sync.getCount() + "]";
    }
}

ReentrantLock

发表于 2016-06-14   |   分类于 juc   |  

和Synchronized一样,ReentrantLock也是可重入的,可作为内置锁的替代物。

与Synchronized相比较而言,ReentrantLock有以下优势:支持公平/非公平锁、支持可中断的锁、支持非阻塞的tryLock(可超时)、支持锁条件、可跨代码块使用(一个地方加锁,另一个地方解锁),总之比Synchronized更加灵活。但也有缺点,比如锁需要显示解锁、无法充分享用JVM内部性能提升带来的好处等等。

public interface Lock {
    /**
     * 获取锁,若无法获取到,则当前线程被阻塞。直到获取成功为止。
     */
    void lock();
    /**
     * 获取锁,若无法获取到,则当前线程被阻塞。直到发生以下两种情况:
     * 获取成功;或者
     * 其他线程中断当前线程 
     */
    void lockInterruptibly() throws InterruptedException;
    /**
     * 如果当前锁可用,获取成功返回true;否则返回false
     */
    boolean tryLock();
    /**
     * 与lockInterruptibly相似,还有第三种情况,即达到超时时间。
     * 如果当前锁可用,获取成功返回true;否则返回false
     */
    boolean tryLock(long time, TimeUnit unit) throws InterruptedException;
    /**
     * 释放锁
     */
    void unlock();
    /**
     * 返回当前锁相关的条件。在条件等待之前,锁必须被当前线程占有,await方法会在等待前释放锁,在结束等待前重新获取锁
     */
    Condition newCondition();
}

基于AQS机制构建的同步类,内部都会使用相关类继承AQS。ReentrantLock也不例外。

// 内部协调机制对象
private final Sync sync;
// 抽象类继承AQS,具有公平和非公平版本的子类。利用AQS的state来表示锁持有(重入)的次数。. 
abstract static class Sync extends AbstractQueuedSynchronizer 

非公平锁子类,新来的类之间尝试获取锁,无论等待队列中是否有线程阻塞等待。

final static class NonfairSync extends Sync

公平锁子类,只有在递归(重入)或者同步队列中没有其他线程或者当前线程是等待队列中的第一个线程时才准许访问

final static class FairSync extends Sync 

非公平版的锁-加锁操作

  1. 当前线程首先会无条件的执行一个CAS操作来获取锁,如果CAS操作成功,获取锁成功。
  2. 如果第1步没成功,当前会检查锁是否被其他线程持有,也就是锁是否可用。
  3. 如果没有其他线程持有锁,会以CAS的方式尝试获取锁,如果CAS操作成功,获取锁成功。
  4. 如果有其他线程持有锁,会判断一下持有锁的线程是否为当前线程,如果是当前线程,重入次数+1,获取锁成功。
  5. 根据AQS的分析,上述2、3、4步会执行多次,如果最终获取锁失败,当前线程会被阻塞,等待其他线程执行解锁操作将其唤醒。

公平版的锁-加锁操作

  1. 当前线程首先会检查锁是否被其他线程持有,并且当前同步等待队列里有没有其他线程在等待。
  2. 如果没有其他线程持有锁,且同步等待队列里没有其他线程,会以CAS的方式尝试获取锁,如果CAS操作成功,获取锁成功。
  3. 如果有其他线程持有锁,会判断一下持有锁的线程是否为当前线程,如果是当前线程,重入次数+1,获取锁成功。nonfairTryAcquire方法
  4. 根据AQS的分析,上述1、2、3步会执行多次,如果最终获取锁失败,当前线程会被阻塞,等待其他线程执行解锁操作将其唤醒。

非公平版和公平版锁的解锁操作一样

  1. 当前线程首先将锁重入次数减1(AQS的state),如果减1后结果为0,将当前同步器的线程信息置空,并唤醒同步等待队列中队头的等待线程。
  2. 如果第1步中,重入次数减1后结果不为0(说明当前线程还持有当前锁),方法结束。

ReentrantLock实现,整体就是sync的一个代理。

public ReentrantLock() {
    sync = new NonfairSync();
}
public ReentrantLock(boolean fair) {
    sync = (fair)? new FairSync() : new NonfairSync();
}

public void lock() {
    sync.lock();
}

public void lockInterruptibly() throws InterruptedException {
    sync.acquireInterruptibly(1);
}

public boolean tryLock() {
    return sync.nonfairTryAcquire(1);
}

public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException {
    return sync.tryAcquireNanos(1, unit.toNanos(timeout));
}

public void unlock() {
    sync.release(1);
}
public Condition newCondition() {
    return sync.newCondition();
}

所有try方法,相当于非阻塞的方式获取锁。

synchronized获得的内部锁存在一定的局限

  1. 不能中断一个正在试图获得锁的线程

  2. 试图获得锁时不能像trylock那样设定超时时间

  3. 每个锁只有单一的条件,不像condition那样可以设置多个

Semaphore

发表于 2016-06-05   |   分类于 juc   |  
  1. 建立一个包含n个许可的信号量(内部的计数为n),当一个线程从信号量中请求一个许可(调用acquire()),如果信号量中有许可的话(n大于0),那么线程成功获取许可,信号量内部许可数量减1(n减1);如果信号量中没有许可(n等于0),那么当前线程阻塞。
  2. 当一个线程归还许可(调用release(),内部计数加1),其他在acquire()方法处等待的线程便有可能被唤醒来竞争许可。
  3. 公平模式下,如果有线程在acquire()处等待,新来的请求线程会排在这些等待线程后面;非公平模式下,新来的请求线程可能会插队,比在acquire()处等待的线程提前申请到许可。

代码分析

/*
 * 基于计数信号量,可用来管理一组许可
 */
public class Semaphore implements java.io.Serializable {
    private static final long serialVersionUID = -3222578661600680210L;
    /** All mechanics via AbstractQueuedSynchronizer subclass */
    private final Sync sync;

    /**
     * 通过AQS的state表示许可的数量,包含公平和非公平的实现
     */
    abstract static class Sync extends AbstractQueuedSynchronizer {
        private static final long serialVersionUID = 1192457210091910933L;

        Sync(int permits) {
            setState(permits);
        }

        final int getPermits() {
            return getState();
        }
        // 共享模式非公平的请求
        final int nonfairTryAcquireShared(int acquires) {
            for (;;) {
                // 获取当前许可数量
                int available = getState();
                // 计算申请后剩余数量
                int remaining = available - acquires;
                /*
                 * 如果申请后剩余>=0,则通过CAS修改,修改成功后返回剩余数量;
                 * 如果申请后剩余<0,则直接返回数量
                 */
                if (remaining < 0 ||
                    compareAndSetState(available, remaining))
                    return remaining;
            }
        }
        /*
         * 释放所,CAS,有int越界判断
         */
        protected final boolean tryReleaseShared(int releases) {
            for (;;) {
                int current = getState();
                int next = current + releases;
                if (next < current) // overflow
                    throw new Error("Maximum permit count exceeded");
                if (compareAndSetState(current, next))
                    return true;
            }
        }
        /*
         * 相当于release的逆操作
         */
        final void reducePermits(int reductions) {
            for (;;) {
                int current = getState();
                int next = current - reductions;
                if (next > current) // underflow
                    throw new Error("Permit count underflow");
                if (compareAndSetState(current, next))
                    return;
            }
        }

        /*
         * 将count置为0并返回
         */
        final int drainPermits() {
            for (;;) {
                int current = getState();
                if (current == 0 || compareAndSetState(current, 0))
                    return current;
            }
        }
    }

    /**
     * 非公平
     */
    static final class NonfairSync extends Sync {
        private static final long serialVersionUID = -2694183684443567898L;

        NonfairSync(int permits) {
            super(permits);
        }

        protected int tryAcquireShared(int acquires) {
            return nonfairTryAcquireShared(acquires);
        }
    }

    /**
     * 公平
     */
    static final class FairSync extends Sync {
        private static final long serialVersionUID = 2014338818796000944L;

        FairSync(int permits) {
            super(permits);
        }

        protected int tryAcquireShared(int acquires) {
            for (;;) {
                // 公平版的请求,需要先检查同步队列里有没有比当前线程更早的线程在等待。  
                if (hasQueuedPredecessors())
                    return -1;
                int available = getState();
                int remaining = available - acquires;
                if (remaining < 0 ||
                    compareAndSetState(available, remaining))
                    return remaining;
            }
        }
    }

    public Semaphore(int permits) {
        sync = new NonfairSync(permits);
    }

    public Semaphore(int permits, boolean fair) {
        sync = fair ? new FairSync(permits) : new NonfairSync(permits);
    }

    /**
     * Acquires a permit from this semaphore, blocking until one is
     * available, or the thread is {@linkplain Thread#interrupt interrupted}.
     *
     * <p>Acquires a permit, if one is available and returns immediately,
     * reducing the number of available permits by one.
     *
     * <p>If no permit is available then the current thread becomes
     * disabled for thread scheduling purposes and lies dormant until
     * one of two things happens:
     * <ul>
     * <li>Some other thread invokes the {@link #release} method for this
     * semaphore and the current thread is next to be assigned a permit; or
     * <li>Some other thread {@linkplain Thread#interrupt interrupts}
     * the current thread.
     * </ul>
     *
     * <p>If the current thread:
     * <ul>
     * <li>has its interrupted status set on entry to this method; or
     * <li>is {@linkplain Thread#interrupt interrupted} while waiting
     * for a permit,
     * </ul>
     * then {@link InterruptedException} is thrown and the current thread's
     * interrupted status is cleared.
     *
     * @throws InterruptedException if the current thread is interrupted
     */
    public void acquire() throws InterruptedException {
        sync.acquireSharedInterruptibly(1);
    }

    /**
     * Acquires a permit from this semaphore, blocking until one is
     * available.
     *
     * <p>Acquires a permit, if one is available and returns immediately,
     * reducing the number of available permits by one.
     *
     * <p>If no permit is available then the current thread becomes
     * disabled for thread scheduling purposes and lies dormant until
     * some other thread invokes the {@link #release} method for this
     * semaphore and the current thread is next to be assigned a permit.
     *
     * <p>If the current thread is {@linkplain Thread#interrupt interrupted}
     * while waiting for a permit then it will continue to wait, but the
     * time at which the thread is assigned a permit may change compared to
     * the time it would have received the permit had no interruption
     * occurred.  When the thread does return from this method its interrupt
     * status will be set.
     */
    public void acquireUninterruptibly() {
        sync.acquireShared(1);
    }

    /**
     * Acquires a permit from this semaphore, only if one is available at the
     * time of invocation.
     *
     * <p>Acquires a permit, if one is available and returns immediately,
     * with the value {@code true},
     * reducing the number of available permits by one.
     *
     * <p>If no permit is available then this method will return
     * immediately with the value {@code false}.
     *
     * <p>Even when this semaphore has been set to use a
     * fair ordering policy, a call to {@code tryAcquire()} <em>will</em>
     * immediately acquire a permit if one is available, whether or not
     * other threads are currently waiting.
     * This &quot;barging&quot; behavior can be useful in certain
     * circumstances, even though it breaks fairness. If you want to honor
     * the fairness setting, then use
     * {@link #tryAcquire(long, TimeUnit) tryAcquire(0, TimeUnit.SECONDS) }
     * which is almost equivalent (it also detects interruption).
     *
     * @return {@code true} if a permit was acquired and {@code false}
     *         otherwise
     */
    public boolean tryAcquire() {
        return sync.nonfairTryAcquireShared(1) >= 0;
    }

    /**
     * Acquires a permit from this semaphore, if one becomes available
     * within the given waiting time and the current thread has not
     * been {@linkplain Thread#interrupt interrupted}.
     *
     * <p>Acquires a permit, if one is available and returns immediately,
     * with the value {@code true},
     * reducing the number of available permits by one.
     *
     * <p>If no permit is available then the current thread becomes
     * disabled for thread scheduling purposes and lies dormant until
     * one of three things happens:
     * <ul>
     * <li>Some other thread invokes the {@link #release} method for this
     * semaphore and the current thread is next to be assigned a permit; or
     * <li>Some other thread {@linkplain Thread#interrupt interrupts}
     * the current thread; or
     * <li>The specified waiting time elapses.
     * </ul>
     *
     * <p>If a permit is acquired then the value {@code true} is returned.
     *
     * <p>If the current thread:
     * <ul>
     * <li>has its interrupted status set on entry to this method; or
     * <li>is {@linkplain Thread#interrupt interrupted} while waiting
     * to acquire a permit,
     * </ul>
     * then {@link InterruptedException} is thrown and the current thread's
     * interrupted status is cleared.
     *
     * <p>If the specified waiting time elapses then the value {@code false}
     * is returned.  If the time is less than or equal to zero, the method
     * will not wait at all.
     *
     * @param timeout the maximum time to wait for a permit
     * @param unit the time unit of the {@code timeout} argument
     * @return {@code true} if a permit was acquired and {@code false}
     *         if the waiting time elapsed before a permit was acquired
     * @throws InterruptedException if the current thread is interrupted
     */
    public boolean tryAcquire(long timeout, TimeUnit unit)
        throws InterruptedException {
        return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
    }

    /**
     * Releases a permit, returning it to the semaphore.
     *
     * <p>Releases a permit, increasing the number of available permits by
     * one.  If any threads are trying to acquire a permit, then one is
     * selected and given the permit that was just released.  That thread
     * is (re)enabled for thread scheduling purposes.
     *
     * <p>There is no requirement that a thread that releases a permit must
     * have acquired that permit by calling {@link #acquire}.
     * Correct usage of a semaphore is established by programming convention
     * in the application.
     */
    public void release() {
        sync.releaseShared(1);
    }

    /**
     * Acquires the given number of permits from this semaphore,
     * blocking until all are available,
     * or the thread is {@linkplain Thread#interrupt interrupted}.
     */
    public void acquire(int permits) throws InterruptedException {
        if (permits < 0) throw new IllegalArgumentException();
        sync.acquireSharedInterruptibly(permits);
    }

    public void acquireUninterruptibly(int permits) {
        if (permits < 0) throw new IllegalArgumentException();
        sync.acquireShared(permits);
    }

    public boolean tryAcquire(int permits) {
        if (permits < 0) throw new IllegalArgumentException();
        return sync.nonfairTryAcquireShared(permits) >= 0;
    }

    public boolean tryAcquire(int permits, long timeout, TimeUnit unit)
        throws InterruptedException {
        if (permits < 0) throw new IllegalArgumentException();
        return sync.tryAcquireSharedNanos(permits, unit.toNanos(timeout));
    }

    public void release(int permits) {
        if (permits < 0) throw new IllegalArgumentException();
        sync.releaseShared(permits);
    }

    public int availablePermits() {
        return sync.getPermits();
    }

    public int drainPermits() {
        return sync.drainPermits();
    }

    protected void reducePermits(int reduction) {
        if (reduction < 0) throw new IllegalArgumentException();
        sync.reducePermits(reduction);
    }

    public boolean isFair() {
        return sync instanceof FairSync;
    }

    /**
     * Queries whether any threads are waiting to acquire. Note that
     * because cancellations may occur at any time, a {@code true}
     * return does not guarantee that any other thread will ever
     * acquire.  This method is designed primarily for use in
     * monitoring of the system state.
     *
     * @return {@code true} if there may be other threads waiting to
     *         acquire the lock
     */
    public final boolean hasQueuedThreads() {
        return sync.hasQueuedThreads();
    }

    public final int getQueueLength() {
        return sync.getQueueLength();
    }

    protected Collection<Thread> getQueuedThreads() {
        return sync.getQueuedThreads();
    }

    public String toString() {
        return super.toString() + "[Permits = " + sync.getPermits() + "]";
    }
}

xinetd

发表于 2016-05-30   |   分类于 linux   |  

抄一篇关于xinetd的,mark下。

http://www.cnblogs.com/itech/archive/2010/12/27/1914846.html

守护进程分类

独立启动(stand_alone):该类进程启动后就常驻内存,所以会一直占用系统资源。其最大的优点就是它会一直启动,当外界有要求时相应速度较快,像httpd等进程;

超级守护进程:系统启动时由一个统一的守护进程xinet来负责管理一些进程,当相应请求到来时需要通过xinet的转接才可以唤醒被xinet管理的进程。这种进程的优点时最初只有xinet这一守护进程占有系统资源,其他的内部服务并不一直占有系统资源,只有数据包到来时才会被xinet管理员来唤醒。并且我们还可以通过xinet来对它所管理的进程设置一些访问权限,相当于多了一层管理机制。

守护进程管理工具

redhat-config-services、ntsysv、chkconfig

service iptables status #查看相应服务的状态,用service需要服务在/etc/init.d/目录中存在

netstat -tulp #会列出相应的服务及其监听的端口号等,若加n参数会列出端口号

chkconfig –list |grep 服务名 #会列出现在当前服务的各种状态,包括在不同运行级别下的启情况,分为上线两部分,上部分是独立启动的服务,你会看到xinetd也在,下面部分是有inet管理的超级守护进程,没有运行级别可分的。

xinetd

从守护进程的概念可以看出,对于系统所要通过的每一种服务,都必须运行一个监听某个端口连接所发生的守护进程,这通常意味着资源浪费。为了解决这个问题,Linux引进了”网络守护进程服务程序”的概念。Red Hat Linux 9.0使用的网络守护进程是xinted(eXtended InterNET daemon)。xinetd能够同时监听多个指定的端口,在接受用户请求时,它能够根据用户请求的端口的不同,启动不同的网络服务进程来处理这些用户请求。可以把xinetd看做一个管理启动服务的管理服务器,它决定把一个客户请求交给哪个程序处理,然后启动相应的守护进程。xinetd无时不在运行并监听它所管理的所有端口上的服务。当某个要连接它管理的某项服务的请求到达时,xinetd就会为该服务启动合适的服务器。

xinetd和stand-alone工作模式相比,系统不想要每一个网络服务进程都监听其服务端口,运行单个xinetd就可以同时监听所有服务端口,这样就降低了系统开销,保护系统资源。但是对于访问量大、经常出现并发访问的情况,xinetd则要频繁启动相应的网络服务进程,反而会导致系统性能下降。查看系统为Linux服务提供哪种工作模式,可以在Linux命令行中使用pstree命令,就能看到两种不同模式启动的网络服务。一般来说系统中一些负载高的服务,Sendmail、Apache服务是单独启动的;而其他服务类型都可以使用xinetd超级服务器管理。

什么是xinetd

xinetd即extended internet daemon,xinetd是新一代的网络守护进程服务程序,又叫超级Internet服务器。经常用来管理多种轻量级Internet服务。xinetd提供类似于inetd+tcp_wrapper的功能,但是更加强大和安全。

xinetd的特色

强大的存取控制功能

  • 内置对恶意用户和善意用户的差别待遇设定。
  • 使用libwrap支持,其效能更甚于tcpd。
  • 可以限制连接的等级,基于主机的连接数和基于服务的连接数。
  • 设置特定的连接时间。
  • 将某个服务设置到特定的主机以提供服务。

有效防止DoS攻击

  • 可以限制连接的等级。
  • 可以限制一个主机的最大连接数,从而防止某个主机独占某个服务。
  • 可以限制日志文件的大小,防止磁盘空间被填满。

强大的日志功能

  • 可以为每一个服务就syslog设定日志等级。
  • 如果不使用syslog,也可以为每个服务建立日志文件。
  • 可以记录请求的起止时间以决定对方的访问时间。
  • 可以记录试图非法访问的请求。

转向功能

可以将客户端的请求转发到另一台主机去处理。

支持IPv6

xinetd自xinetd 2.1.8.8pre*起的版本就支持IPv6,可以通过在./configure脚本中使用with-inet6 capability选项来完成。注意,要使这个生效,核心和网络必须支持IPv6。当然IPv4仍然被支持。

与客户端的交互功能

无论客户端请求是否成功,xinetd都会有提示告知连接状态。

Xinetd的缺点

当前,它最大的缺点是对RPC支持的不稳定性,但是可以启动protmap,使它与xinetd共存来解决这个问题。

使用xinetd启动守护进程

原则上任何系统服务都可以使用xinetd,然而最适合的应该是那些常用的网络服务,同时,这个服务的请求数目和频繁程度不会太高。像DNS和Apache就不适合采用这种方式,而像FTP、Telnet、SSH等就适合使用xinetd模式,系统默认使用xinetd的服务可以分为如下几类。
① 标准Internet服务:telnet、ftp。
② 信息服务:finger、netstat、systat。
③ 邮件服务:imap、imaps、pop2、pop3、pops。
④ RPC服务:rquotad、rstatd、rusersd、sprayd、walld。
⑤ BSD服务:comsat、exec、login、ntalk、shell、talk。
⑥ 内部服务:chargen、daytime、echo、servers、services、time。
⑦ 安全服务:irc。
⑧ 其他服务:name、tftp、uucp。

解读xinet的配置文件/etc/services, /etc/xinetd.conf和/etc/xinetd.d/*

0)/etc/services

在/etc/services 中设置了xinetd下的service对应的端口,例如:

$ cat /etc/services | grep rsync
rsync 873/tcp # rsync
rsync 873/udp # rsync

1) /etc/xinetd.conf
xinetd的配置文件是/etc/xinetd.conf,但是它只包括几个默认值及/etc/xinetd.d目录中的配置文件。如果要启用或禁用某项xinetd服务,编辑位于/etc/xinetd.d目录中的配置文件。例如,disable属性被设为yes,表示该项服务已禁用;disable属性被设为no,表示该项服务已启用。/etc/xinetd.conf有许多选项,下面是RHEL 4.0的/etc/xinetd.conf。

Simple configuration file for xinetd
Some defaults, and include /etc/xinetd.d/
defaults
{
    instances            = 60
        log_type             = SYSLOG authpriv
       log_on_success       = HOST PID
    log_on_failure       = HOST
    cps                  = 25 30
}
includedir /etc/xinetd.d
  • instances = 60:表示最大连接进程数为60个。
  • log_type = SYSLOG authpriv:表示使用syslog进行服务登记。
  • log_on_success= HOST PID:表示设置成功后记录客户机的IP地址的进程ID。
  • log_on_failure = HOST:表示设置失败后记录客户机的IP地址。
  • cps = 25 30:表示每秒25个入站连接,如果超过限制,则等待30秒。主要用于对付拒绝服务攻击。
  • includedir /etc/xinetd.d:表示告诉xinetd要包含的文件或目录是/etc/xinetd.d。

2) /etc/xinetd.d/*

下面以/etc/xinetd.d/中的一个文件(rsync)为例。
service rsync
{
disable = yes
socket_type = stream
wait = no
user = root
server = /usr/bin/rsync
log_on_failure += USERID
}

下面说明每一行选项的含义。

  • disable = yes:表示禁用这个服务。
  • socket_type = stream:表示服务的数据包类型为stream。
  • wait = no:表示不需等待,即服务将以多线程的方式运行。
  • user = root:表示执行此服务进程的用户是root。
  • server = /usr/bin/rsync:启动脚本的位置。
  • log_on_failure += USERID:表示设置失败时,UID添加到系统登记表。

配置xinetd

1) 格式
/etc/xinetd.conf中的每一项具有下列形式:
service service-name
{
……
}

其中service是必需的关键字,且属性表必须用大括号括起来。每一项都定义了由service-name定义的服务。

service-name是任意的,但通常是标准网络服务名,也可增加其他非标准的服务,只要它们能通过网络请求激活,包括localhost自身发出的网络请求。有很多可以使用的属性,稍后将描述必需的属性和属性的使用规则。

操作符可以是=、+=或-=。所有属性可以使用=,其作用是分配一个或多个值,某些属性可以使用+=或-=,其作用分别是将其值增加到某个现存的值表中,或将其值从现存值表中删除。

2) 配置文件
相关的配置文件如下:
/etc/xinetd.conf
/etc/xinetd.d/* //该目录下的所有文件
/etc/hosts.allow
/etc/hosts.deny

3)/etc/xinetd.conf中的disabled与enabled
前者的参数是禁用的服务列表,后者的参数是启用的服务列表。他们的共同点是格式相同(属性名、服务名列表与服务中间用空格分开,例如disabled = in.tftpd in.rexecd),此外,它们都是作用于全局的。如果在disabled列表中被指定,那么无论包含在列表中的服务是否有配置文件和如何设置,都将被禁用;如果enabled列表被指定,那么只有列表中的服务才可启动,如果enabled没有被指定,那么disabled指定的服务之外的所有服务都可以启动。

4) 注意问题
① 在重新配置的时候,下列的属性不能被改变:socket_type、wait、protocol、type;
② 如果only_from和no_access属性没有被指定(无论在服务项中直接指定还是通过默认项指定),那么对该服务的访问IP将没有限制;
③ 地址校验是针对IP地址而不是针对域名地址。

6 xinetd防止拒绝服务攻击(Denial of Services)的原因
xinetd能有效地防止拒绝服务攻击(Denial of Services)的原因如下。

1) 限制同时运行的进程数
通过设置instances选项设定同时运行的并发进程数:
instances=20
当服务器被请求连接的进程数达到20个时,xinetd将停止接受多出部分的连接请求。直到请求连接数低于设定值为止。

2) 限制一个IP地址的最大连接数
通过限制一个主机的最大连接数,从而防止某个主机独占某个服务。
per_source=5
这里每个IP地址的连接数是5个。

3) 限制日志文件大小,防止磁盘空间被填满
许多攻击者知道大多数服务需要写入日志。入侵者可以构造大量的错误信息并发送出来,服务器记录这些错误,可能就造成日志文件非常庞大,甚至会塞满硬盘。同时会让管理员面对大量的日志,而不能发现入侵者真正的入侵途径。因此,限制日志文件大小是防范拒绝服务攻击的一个方法。
log_type FILE.1 /var/log/myservice.log 8388608 15728640
这里设置的日志文件FILE.1临界值为8MB,到达此值时,syslog文件会出现告警,到达15MB,系统会停止所有使用这个日志系统的服务。

4) 限制负载

xinetd还可以使用限制负载的方法防范拒绝服务攻击。用一个浮点数作为负载系数,当负载达到这个数目的时候,该服务将暂停处理后续的连接。
max_load = 2.8
上面的设定表示当一项系统负载达到2.8时,所有服务将暂时中止,直到系统负载下降到设定值以下。
说明 要使用这个选项,编译时应加入“–with-loadavg”,xinetd将处理max-load配置选项,从而在系统负载过重时关闭某些服务进程,来实现防范某些拒绝服务攻击。

5) 限制所有服务器数目(连接速率)
xinetd可以使用cps选项设定连接速率,下面的例子:
cps = 25 60
上面的设定表示服务器最多启动25个连接,如果达到这个数目将停止启动新服务60秒。在此期间不接受任何请求。

6) 限制对硬件资源的利用
通过rlimit_as和rlimit_cpu两个选项可以有效地限制一种服务对内存、中央处理器的资源占用:
rlimit_as = 8M
rlimit_cpu=20
上面的设定表示对服务器硬件资源占用的限制,最多可用内存为8MB,CPU每秒处理20个进程。

xinetd的一个重要功能是它能够控制从属服务可以利用的资源量,通过它的以上设置可以达到这个目的,有助于防止某个xinetd服务占用大量资源,从而导致“拒绝服务”情况的出现。

六 Service命令

Linux的service命令就是查看和控制所有的独立启动的守护进程。 这个命令不是在所有的linux发行版本中都有。主要是在redhat系linux中。service此命令位于/sbin/service,用file命令查看此命令会发现它是一个脚本命令。分析脚本可知此命令的作用是去/etc/init.d目录下寻找相应的服务,进行开启和关闭等操作。例如service mysqld stop等价于/etc/init.d/mysqld stop。

七 xinetd本身也是一个独立的守护进程,在/etc/init.d/xinetd。

linux管理维护命令

发表于 2016-05-30   |   分类于 linux   |  

nc

nc localhost 20000 与 telnet localhost 20000相同

激活一个20000端口来监听连接

nc -l localhost 20000 &
netstat -tlunp | grep nc
nc localhost 20000

这里localhost为只开启本机测试,如果想通过其他机器连接,可以使用ip或域名。

linux命令中的&,强制命令在后台执行。

ehcache是什么

发表于 2016-05-18   |   分类于 ehcache   |  

转自carlosfu大大的bigmemory系列文章: http://carlosfu.iteye.com/blog/2237511

duboo入门

发表于 2016-05-17   |   分类于 dubbo   |  

节点角色说明:

Provider: 暴露服务的服务提供方。
Consumer: 调用远程服务的服务消费方。
Registry: 服务注册与发现的注册中心。
Monitor: 统计服务的调用次调和调用时间的监控中心。
Container: 服务运行容器。

调用关系说明:

0. 服务容器负责启动,加载,运行服务提供者。
1. 服务提供者在启动时,向注册中心注册自己提供的服务。
2. 服务消费者在启动时,向注册中心订阅自己所需的服务。
3. 注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。
4. 服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。
5. 服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。

注册中心负责服务地址的注册与查找,相当于目录服务,服务提供者和消费者只在启动时与注册中心交互,注册中心不转发请求,压力较小。

dubbo官方入门文档 http://dubbo.io/Getting+Started-zh.htm

Schema

发表于 2016-05-11   |   分类于 mysql   |  

选择优化的数据类型

选择数据类型设计schema通常有以下几个简单的原则:

  1. 更小的通常更好。
    例如如果只需要存0~200,那么tinyint unsigned更好。因为更小的数据类型,占用的更少的磁盘、内存和cpu缓存,处理所需的cpu周期也更少。
  2. 简单就好。
    简单的数据类型操作通常需要更少的cpu周期。如,整形比字符操作代价更低,因为字符集和排序校对规则使字符比较比整形复杂。
    例子:日期应该使用date,time,datetime而不是字符串;IP地址应该使用整形。
  3. 尽量避免NULL。
    可为null的列使得索引、索引统计和值比较更复杂。这样的列需要占据额外的存储空间,每个索引记录需要一个额外的字节。因此如果打算在列上建索引,最好加上not null限制。

第一步需要确定大类型:数字、字符串、时间等;第二步,确定存储范围精度等。eg. TIMESTAMP(4B)比DATETIME(8B)少一半存储空间,可以根据时区变化,具有自动更新的能力;但同时允许的时间范围也小的多。

阅读全文 »
1234
Sunwind

Sunwind

含英咀华,凤凰于飞

35 日志
21 分类
41 标签
shiye dada
© 2017 Sunwind
由 Hexo 强力驱动
主题 - NexT.Muse