实验五 消息中间件

实验目的

模拟在道路上汽车行驶的场景:
1,订单可以根据订单生成器(生成器可参考附件的文件,但可自行修改;比如根据车辆数,修改订单生成的速率)生成起点和终点。车辆以概率p(比如p=0.8)车根据订单沿着道路行走,行驶速度根据路段给定;车辆以1-p的概率随机移动(当没有订单时);(路网为DIMACS格式的文件。)
2,有些车发布消息(生产者,比如内容是一个图像),有些车接收和消费消息(消费者);当车与车之间的距离小于R时(比如R=100m),可以进行通信:生产者把消息发送给在通信范围内的消费者。当大于R时,通信停止;【不断变动消息的订阅关系】

把厦门市的道路路网进行可视化展现(基于前端html页面或者java窗体);并能展现汽车移动。
基于Spring 的 JMS编程模型,完成以上消息发布、消息接收等模拟器编程。

实验过程

  • springboot +JMS开发环境搭建
  • 路网搭建
  • 搭建订单生成服务器
  • 搭建车辆模拟服务器
  • 显示车辆移动

SpringBoot +JMS开发环境搭建

参考博文https://www.cnblogs.com/niit-soft-518/p/6957384.html

路网搭建

这里采用JGraphT搭建厦门的全联通的时间依赖的速度路网,具体过程略。

搭建订单生成服务器

订单生成器读取真实订单txt文件,将其转化成消息传递到request队列中,供车辆模拟服务器异步获取进行处理。
模拟开始时,需要同步两个服务器的时间,具体做法如下:订单生成服务器启动时会监听simulatorCommand队列,车辆模拟服务器开始模拟时会将start命令传入此队列,告诉订单生成器现在的时间,并通知其开始工作。关键代码如下:

   @JmsListener(destination = "simulatorCommand",containerFactory = "queueListenerContainer")
    public void recieve(String msg) throws Exception {
        String[] info=msg.split("#");
        //从消息中获取车辆模拟服务器传达的命令,如果是start则开始工作
        String command=info[0];
        if(command.equals("start")){
            if(thread!=null&&thread.isAlive()){
                return;
            }
            this.startTime=Integer.valueOf(info[1]);
            this.time=startTime;
            this.unitTime=Integer.valueOf(info[2]);
            this.isInterupt=false;
            this.thread=new Thread(this,"simulator");
            thread.start();
        }else if(command.equals("stop")){
            isInterupt=true;
        }else if(command.equals("terminate")){
            isInterupt=true;
            bufferedReader.close();
            bufferedReader=null;
        }
    }

在真实场景中,用户通过rest形式的http请求发出乘车请求,对应的controllor将用户的乘车信息转化为能够处理的消息格式,传入request队列中:

@RequestMapping(value = "/request",method = RequestMethod.POST)
    public void getRequest(@RequestBody Map<String,String> request){
        jmsTemplate.convertAndSend("request",request.get("request"));
    }

订单生成器会读取真实订单txt文件,并模拟http请求,根据时间调用此controller,达到模拟真实场景的效果。

搭建车辆模拟服务器

服务器的每次调度过程如下:
1.向request队列中取有限个请求加到原有的请求队列中
2.获取当前的请求队列和空载车辆,选择匹配算法进行匹配(这里使用最近优先匹配)
3.根据匹配结果更新被匹配车辆状态
4.模拟车辆发布接收消息
5.随机移动空载车辆

如果将每一辆车都配置一个独立的topic,则要为每辆车配置总车辆数个监听器来监听其他车辆的topic,太麻烦。我们将所有车辆发出的信息保存的一个topic中,交给第三方——消息处理器分发信息。
每次调度,选择1辆车发布消息,选择与它最近的5辆车订阅此消息。
关键代码如下:

public void sendMessage(){
        List<SimulatorCar> allCars=carExcutor.getAllCars();
        int selectId=(int)(new Random().nextDouble()*allCars.size())+1;
        for(Car car:allCars){
            selectId--;
            if(selectId==0){
                jmsTemplate.convertAndSend("carMessage",car.getId()+"#car "+car.getId()+" message");
                break;
            }
        }
    }

    @JmsListener(destination = "carMessage",containerFactory = "topicListenerContainer")
    public void getMessage(String msg){
        String[] info=msg.split("#");
        int carId=Integer.valueOf(info[0]);
        String message=info[1];
        List<SimulatorCar> allCars=carExcutor.getAllCars();
        Car messageCar=allCars.get(carId-1);
        List<Car> nearCars=getNearCars(5,messageCar);

        for(Car car:nearCars){
            System.out.println("car "+car.getId()+" receive message: "+message);
        }
    }

    private List<Car> getNearCars(int num,Car center){
        List<Car> nearCars=new LinkedList<>();
        List<Double> distances=new LinkedList<>();
        for(Car car:carExcutor.getAllCars()){
            if(center==car){
                continue;
            }
            RoadNode carL=((SimulatorCar)car).getLocation();
            RoadNode centerL=((SimulatorCar)center).getLocation();
            double distance=(carL.getLat()-centerL.getLat())*(carL.getLat()-centerL.getLat())+(carL.getLon()-centerL.getLon())*(carL.getLon()-centerL.getLon());
            for(int i=0;i<nearCars.size();i++){
                if (distance<distances.get(i)){
                    nearCars.add(i,car);
                    distances.add(i,distance);
                    break;
                }
            }
            if(nearCars.size()<num){
                nearCars.add(car);
                distances.add(distance);
            }
            if(nearCars.size()>num){
                ((LinkedList<Car>) nearCars).removeLast();
                ((LinkedList<Double>) distances).removeLast();
            }
        }
        return nearCars;
    }

前4步做完计算服务器花费的时间,并转化为模拟时间,将空载车辆随机移动这么多的时间。

显示车辆移动

我们调用高德地图的JS API进行可视化,模拟器缓存了当前空载车辆的位置信息,我们通过提供的接口调用获取,并在图中标出相应的位置。每隔1s轮询刷新一次。

实验结果

先启动订单生成服务器,再启动车辆模拟服务器,调用/start接口开始模拟
订单生成器输出订单信息(只输出了请求的t0信息):


image.png

消息处理器输出车辆之间的消息接收信息:


image.png

显示车辆位置信息:
image.png
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,651评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,468评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,931评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,218评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,234评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,198评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,084评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,926评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,341评论 1 311
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,563评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,731评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,430评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,036评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,676评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,829评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,743评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,629评论 2 354

推荐阅读更多精彩内容