澳门新葡亰平台9411网络基础

澳门新葡亰平台9411 2

分布式系统是一种通过网络进行通信使用多台服务器来协同完成计算任务的系统,是一种提高业务承载量的基本手段,通过利用更多的服务器,来解决单个服务器无法同时承载大量的用户使用的问题。

前述:

基本概念

在网络编程中,有几个必须掌握的基本概念:

客户端(Client):移动应用(iOS、android 等应用);

服务器(Server):为客户端提供服务、提供数据、提供资源的机器;

请求(Request):客户端向服务器索取数据的一种行为;

响应(Response):服务器对客户端的请求做出的反应,一般指返回数据给客户端;

澳门新葡亰平台9411 1

基本概念

  在学习单例模式后,对老师课上布置的课后作业,自然要使用单例模式,但是不是一般的单例,要求引起我的兴趣,案例是用服务器。

服务器

按照软件开发阶段来分,服务器可以大致分为 2 种;

  • 远程服务器

别名:外网服务器、正式服务器;

使用阶段:应用上线后使用的服务器;

使用人群:供全体用户使用;

速度:取决于服务器的性能、用户的网速;

  • 本地服务器

别名:内网服务器、测试服务器;

使用阶段:应用处于开发、测试阶段使用的服务器;

使用人群:仅供公司内部的开发人员、测试人员使用;

速度:由于是局域网,所以速度飞快,有助于提高开发测试效率;

  老师布置的要求是:服务器只有一个,但是使用这个服务器时候可以有多个对象(原版的)和备份数据库,也就是至少要两个对象,因为有可能服务器对象会垮掉,所以要用备份的,所以这里要考虑调用时候,应该返回哪个服务器对象,还有当服务器对象垮掉后,应该怎么处理,保证用户的使用。老师说,两个对象是基本要求,如果能够控制多个对象,分数更高哦。

  我觉得蛮有意思的题目,如果只考虑两个对象,无非在单例模式下原来是建立一个,现在改为建立两个,然后在使用前作检查,如果服务器垮掉,那备份服务器拿起来用,并且要给原版(原来垮掉的那个重新赋值)这样,有些简单。所以,我自己在琢磨后,写出了能够控制多个服务器的多例模式,并且保证只实例一次,后面的服务器对象都是备份原来的,并且返回的服务器对象都是可用。

 

首先,看下画类图

澳门新葡亰平台9411 2

先看里面的字段:list就是多例保存的服务器实例;COUNT是常量,用于保存设置服务器的最大数量;使用时候是按队列取,因此top自然放的是list的顶部;name是服务器名,state来模拟服务器是否垮掉(true代表能用,false代表垮掉);CTIME是来计数器,来定时清理队列中不可用的服务器;time就是配合CTIME使用。

 

分析下设计的思路:其实最难的就是怎么获取服务器,还有怎么创建,获取,及删除无用的服务器,就是在静态方法getInstance方法里。

首先,调用cleanServer()方法,里面会检查有没有到计数值,如果有到,就执行将所有的遍历一遍,将不能用的服务器从队列里删除掉,这个是为了队列里面在top之前可能有获取不到的无用服务器,但是这些又不影响当前使用,所以可以用个计数器来进行清理。

 

第二步,用户获取服务器时候,先要使用一个循环,只要直到队列top到底了或者里某个服务器对象的state为true就跳出循环。这里只是为了找到可用的服务器,不需要遍历所有,可以节省了时间。

 

第三步,当跳出循环后,就判断队列有没有超过COUNT的值,

  当没有等于COUNT值,那就执行createServer()方法,这里面存放创建或者是复制服务器;

    当队列为空时候,就创建服务器,将当前服务器添加到队列里,并返回给用户;

    如果不为空,就克隆上个能使用的服务器,并将当前复制的服务器添加到队列里,并返回给用户;

  当等于COUNT值了,就把服务器直接返回。

 

好了思路分析完了,这样子多例是不是很好,可以对多个实例进行控制,为了测试,里面设置了Dispose()用来修改state值,模拟服务器不能使用了。

 

接下来贴代码,是使用java写的,其实我觉得算法的话,与实际的语言无关,只不过老师只认java,所以用java来写,其中使用了java的克隆模式,如果不了解,先去了解下,也是简单的。

import java.awt.List;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.ArrayList;


public class ServerStation implements Serializable {
    //服务器多例list
    static ArrayList<ServerStation> list = new ArrayList<ServerStation>();
    //控制数量
    static final int COUNT = 2;
    //指向列表头服务器
    static int top = -1;
    //服务器名
    String name;
    //服务器状态
    boolean state;
    //计数器最大值
    static final int CTIME = 5;
    //计数器
    static int time = 0;
    //私有构造函数
    private ServerStation(String name){
        this.name = name;
        this.state = true;
    }
    //设置服务器名
    private void setName(String name){
        this.name = name;
    }
    //获取服务器名
    public String getName(){
        return this.name;
    }
    //获取服务器状态
    public boolean getState(){
        return this.state;
    }

    //显示服务器信息
    public void showInfo(){
        System.out.println("服务器名:"+this.name);
        System.out.println("服务运行状态:"+this.state);
    }
    //释放服务器
    public void Dispose(){
        this.list.get(top).state = false;
    }
    //获取服务器
    public static ServerStation getInstance(){
        clearServer();
        ServerStation server = null;

        while(top >= 0 && list.get(top).state == false)
            removeServer();

        if(top < COUNT - 1)
            server = createServer();
        else
            server = getServer();

        return server;
    }

    //创建服务器或者克隆服务器
    private static ServerStation createServer(){
        ServerStation server = null;
        if(top == -1){
            top++;
            server = new ServerStation("新服务器");
            list.add(server);
        }else{
            server = cloneServer();
        }
        return server;
    }
    //获取服务器
    private static ServerStation getServer(){
        ServerStation server = list.get(top);
        String name = server.getName();
        if(name.contains("新"))
            name = name.replace("新", "旧");
        server.setName(name);
        return server;
    }
    //清除无用服务器
    private static void clearServer(){
        if(time < CTIME){
            time++;
            return;
        }
        time = 0;
        for(int i = 0;i<list.size()-1;i++){
            if(list.get(i).getState() == false){
                list.remove(i);
                top--;
            }
        }
    }

    //移除服务器
    private static void removeServer(){
        list.remove(top);
        top--;
    }

    //克隆服务器
    private static ServerStation cloneServer(){
        ServerStation server = null;
        try{
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(out);
            oos.writeObject(list.get(top));
            top++;
            ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
            ObjectInputStream ois = new ObjectInputStream(in);
            server = (ServerStation)ois.readObject();
            String name = server.getName();
            if(!name.contains("备份")){
                name = "备份"+name;
            }
            server.setName(name);
            list.add(server);
            oos.close();
            ois.close();
        }catch(Exception e){
            e.printStackTrace();
            System.out.print("错误");
        }

        return server;
    }
}

 

测试代码:

public class Main {
    public static void main(String[] args) {
        ServerStation s1 = ServerStation.getInstance();
        s1.showInfo();
        ServerStation s2 = ServerStation.getInstance();
        s2.showInfo();
        s2.Dispose();
        ServerStation s3 = ServerStation.getInstance();
        s3.showInfo();
        s2.Dispose();
        ServerStation s4 = ServerStation.getInstance();
        s4.showInfo();
        ServerStation s5 = ServerStation.getInstance();
        s4.showInfo();
    }
}

上边就是为了模拟,运行后验证,返回服务器都是可用的,蛮不错。

运行结果:

 

服务器名:新服务器
服务运行状态:true
服务器名:备份新服务器
服务运行状态:true
服务器名:备份新服务器
服务运行状态:true
服务器名:备份新服务器
服务运行状态:true
服务器名:备份旧服务器
服务运行状态:true