消息化服务自实现设计

背景

一直想自己试试设计一个只属于自己的小框架,于是就有了这个项目。

代码地址

https://coding.net/u/mich/p/MiniServer/git

项目说明

该项目主要将每个服务都配置一个消息队列,服务间通过消息进行传递,同时提供了控制台指令,进行服务的管理,实现一些后台的工作(主要web太麻烦了,所以控制台输入最省力),该项目只处理过一些小型后台任务,未在正式大型项目中实际使用过!

未来展望

1. 以后估计会将以往做过的微博用户数据抓取,tower对接,股票数据抓取及分析等已开发的项目在该框架的基础上实现(事实是原来以有一套类似小框架,但是后来被我嫌弃,现在重写了)

2.可能会将该项目分布式,通过zookeeper分布式管理所有的服务

3.加入实时热更新的功能,这也是服务消息化的主要原因

模块介绍

主要模块介绍就在上方的git地址看吧,此处省略

使用介绍

git上贴图不方便,说明什么的还是这里介绍吧。这里简单介绍一下example文件夹内容。

主要实现功能就是抽奖功能,在奖池中设置几个奖品,然后玩家多线程的去同时获取奖品

1. PrizeServer

该类就设置一个prize属性,作为奖品的数量,由于只有一个奖池,所以此服务设置为MiniServerType.SINGLETON,同时设置一下服务的名称name(其实不设置也可以默认为类名),然后设置一个初始化函数打上 @MiniServerInit注解,把奖品的数量设置为2。对外,我设置了一个抽奖的方法drawPrize()判断是不是有奖品,如果没有就返回-1

package example.server;
import com.basic.stableserver.MenuMethod;import com.basic.stableserver.MiniServerInfo;import com.basic.stableserver.MiniServerInit;import com.basic.stableserver.MiniServerType;import com.basic.utils.Utils;

/** * Created by Mich on 17/7/7. */@MiniServerInfo(value = MiniServerType.SINGLETON, name = "PrizeServer")public class PrizeServer {    private int prize;

@MenuMethod    public int drawPrize() {        if (prize == 0) {            return -1;        }        prize -= 1;        return Utils.getRandom();    }

@MenuMethod    public int getPrize() {        return prize;    }

@MiniServerInit    public void init() {        this.prize = 2;    }}

2. PlayerServer

玩家服务,由于玩家不同于奖池只有一个,玩家会有很多个,所以设置了@MiniServerInfo(value = MiniServerType.PROTOTYPE, name = "PlayerServer", id = "id"),同样为了区分每个玩家的信息,加入了id="id",除了id,同时设置了money.同样我对玩家做了些初始化的操作,设置了钱,同时输出了便于测试识别,退出时,我也输出了日志。对外,我也设置了几个方法,主要为draw()抽奖方法,通过获取奖池服务,call("drawPrize")来阻塞住消息,最后判断返回获得了什么奖品,同时输出奖品

package example.server;

import com.basic.stableserver.*;

/** * Created by Mich on 17/7/7. */@MiniServerInfo(value = MiniServerType.PROTOTYPE, name = "PlayerServer", id = "id")public class PlayerServer {    private int id;    private int money;

@MenuMethod    public int removeMoney(Integer money) {        this.money -= money;        System.out.println("id : " + id + " rest " + this.money);        return this.money;    }

@MenuMethod    public int draw() {        MiniServer prizeServer = MiniServerController.getInstance().getMiniServer(PrizeServer.class);        this.money -= 100;        int prize = (Integer) prizeServer.call("drawPrize");        if (prize == -1) {            this.money += 100;            System.out.println("id : " + id + " not get prize,rest money:" + this.money);        } else {            System.out.println("id : " + id + " get prize " + prize + ",rest money:" + this.money);        }        return prize;    }

@MenuMethod    public void logout() {        MiniServerController.getInstance().unregister(this.getClass(), this.id);    }

@MenuMethod    public int getMoney() {        return money;    }

public void setMoney(int money) {        this.money = money;    }

public void setId(int id) {        this.id = id;    }

public int getId() {        return id;    }

@MiniServerInit    public void init() {        this.money = 10000;        System.out.println("id : " + id + " coming, rest " + this.money);    }

@MiniServerDestroy    public void destroy() {        System.out.println("id : " + id + " leave, rest " + this.money);    }}

3.Start

在玩家和奖池都设计完后,就是启动类了。首先我先初始化最核心的管理类MiniServerController,然后再管理类加载完之后初始化控制台管理服务,此时会将所有的服务加载到此InputServer中,便于控制台管理(其实此样例有没有无所谓)。先获得玩家服务,然后初始化5个玩家,加入到玩家服务中(事实上是可以多线程添加的,但是为了展示抽奖的效果,就同步添加了)。然后多线程的对玩家服务传递info的抽奖消息,最后玩家在退出,此处由于是异步的,所以有可能玩家会先退出再抽奖,但是没关系,系统做了处理,对于离开的玩家有两种特殊处理情形,一种为玩家呼叫退出时,还有一部分消息滞留在消息队列中,此时玩家并不会直接退出,而是等此部分消息处理完再退出,同时在呼叫退出时,此时队列不再接受此玩家的所有消息,另一种为玩家退出后,过一会儿又回来了(可能是断线重连),此时如果玩家由于之前退出时还有消息没处理完而没有退出的,那就像什么事都没发生过一样,继续保留。由于不知道玩家哪一条消息式最后一条消息,而每个服务只有一个消息队列,所以我采取的策略是在处理下一条指令时判断指令接受时间与退出时间作对比,所以为了示例,我最后添加了玩家30的消息处理,以防玩家没有退出(此处以后会改)

package example;

import com.basic.stableserver.InputServer;
import example.server.PlayerServer;
import com.basic.stableserver.MiniServer;
import com.basic.stableserver.MiniServerController;

/**
 * Created by Mich on 17/7/7.
 */
public class Start {
    public static void main(String[] args) {
        MiniServerController miniServerController = MiniServerController.getInstance();
        miniServerController.init();
        InputServer inputServer = new InputServer();
        inputServer.start();
        MiniServer playerMiniServer = miniServerController.getMiniServer(PlayerServer.class);
        int playersNum = 5;
        for (int i = 0; i < playersNum; i++) {
            PlayerServer playerServer = new PlayerServer();
            playerServer.setId(i);
            playerMiniServer.addSubject(playerServer);
        }
        for (int i = 0; i < 5; i++) {
            final int tmp = i;
            Thread thread = new Thread(new Runnable() {
                @Override
                public void run() {
                    playerMiniServer.info(tmp, "draw");
                }
            });
            thread.start();
        }
        for (int i = 0; i < playersNum; i++) {
            miniServerController.unregister(PlayerServer.class, i);
        }
        PlayerServer playerServer = new PlayerServer();
        playerServer.setId(30);
        playerMiniServer.addSubject(playerServer);
        playerMiniServer.info(30, "draw");
    }
}

最后看一下执行结果

最先看见的是玩家的进入,之后由于玩家3和玩家2退出指令比抽奖早,所以遗憾的没有尝试抽奖就退出了,而玩家1和30由于玩家0和4抽取到了奖品而奖品池只有两份奖品而最终没有获得奖品。

时间: 2024-10-31 21:22:29

消息化服务自实现设计的相关文章

NoSQL初探之人人都爱Redis:(3)使用Redis作为消息队列服务场景应用案例

一.消息队列场景简介 “消息”是在两台计算机间传送的数据单位.消息可以非常简单,例如只包含文本字符串:也可以更复杂,可能包含嵌入对象.消息被发送到队列中,“消息队列”是在消息的传输过程中保存消息的容器. 在目前广泛的Web应用中,都会出现一种场景:在某一个时刻,网站会迎来一个用户请求的高峰期(比如:淘宝的双十一购物狂欢节,12306的春运抢票节等),一般的设计中,用户的请求都会被直接写入数据库或文件中,在高并发的情形下会对数据库服务器或文件服务器造成巨大的压力,同时呢,也使响应延迟加剧.这也说明

使用Redis作为消息队列服务场景应用案例

一.消息队列场景简介 "消息"是在两台计算机间传送的数据单位.消息可以非常简单,例如只包含文本字符串:也可以更复杂,可能包含嵌入对象.消息被发送到队列中,"消息队列"是在消息的传输过程中保存消息的容器. 在目前广泛的Web应用中,都会出现一种场景:在某一个时刻,网站会迎来一个用户请求的高峰期(比如:淘宝的双十一购物狂欢节,12306的春运抢票节等),一般的设计中,用户的请求都会被直接写入数据库或文件中,在高并发的情形下会对数据库服务器或文件服务器造成巨大的压力,同时

【转】NoSQL初探之人人都爱Redis:(3)使用Redis作为消息队列服务场景应用案例

一.消息队列场景简介 “消息”是在两台计算机间传送的数据单位.消息可以非常简单,例如只包含文本字符串:也可以更复杂,可能包含嵌入对象.消息被发送到队列中,“消息队列”是在消息的传输过程中保存消息的容器. 在目前广泛的Web应用中,都会出现一种场景:在某一个时刻,网站会迎来一个用户请求的高峰期(比如:淘宝的双十一购物狂欢节,12306的春运抢票节等),一般的设计中,用户的请求都会被直接写入数据库或文件中,在高并发的情形下会对数据库服务器或文件服务器造成巨大的压力,同时呢,也使响应延迟加剧.这也说明

[分布式服务]海量互联网服务设计之降级设计

目录 降级一致性 缓存的使用 流程异步化 行为聚集化 体验降级 简化流程 分级体验 降级服务要点 上周在 [分布式服务]海量互联网服务设计的有损价值观 这篇文章中提到,与金融行业服务要求的强一致性不同,海量互联网服务要求的是能够扛住更高的qps,服务降级研究的问题是在服务器资源有限的情况下,如何提供更大的访问量,并保证系统稳定运行. 最近我搬了个房子,房东还没来得及上面装宽带,所以在家里我是用手机热点上网的.热点网速有限,看视频的时候,为了视频流程的播放,我将视频从蓝光调整到270P,虽然视频清

微服务架构的设计和实践-培训感悟

这两天(4月8号,9号)我有幸参加了极客邦的培训课程-微服务架构的设计和实践,能够面对面倾听58架构师-孙玄的亲身授课,个人也是感到非常的荣幸.两天的时间,来回于广州和深圳,虽然不能说自己的技术有了一个质的提升,但至少也是一次很好的交流体现,这一趟不白走! 身为一个技术小白(虽然个人也有四年的开发经验,但大多的技术只是知其然而不知其所以然,而且接触面太狭隘),此次学习最明显的感受是,如果你只会写软件代码,了解与某种语言相关的语法,框架以及架构包括技术,那你肯定会"死的很惨".作为软件行

流程管理中WEB表单开发服务需求分析及设计思路

在流程管理应用中,BPM产品所提供的表单设计工具,主要是面向开发人员的.而一些办公系统产品所提供的表单设计工具,受自身平台限制,无法在大型定制化应用中使用.在此通过对用户需求分析,提出WEB表单开发服务设计思路. 一.需求分析 现如今,在创新与改革社会环境推动下,办公管理系统的管理需求变化已经是常态了,如何让信息系统快速响应支撑管理需求的多变,已经成为使信息化建设和运维人员头痛的事情.特别是在一些大型企事业单位,快速支撑需求更突出.而原有信息系统很难适应这样的需求,必须走创新的路来解决这些需求,

用MongoDB数据库来管理办公系统中文档型的表单和信息——通用流程化应用审批单设计思路(二,续)

1.办公系统中文档的定义 办公系统中的文档就是指对数据不敏感的业务,例如流程中的审批单.信息专栏.数据上报.信息记录等.而对于这些信息的管理,特别是时效性较强的管理记录,仍采用关系型数据库进行管理. (1)流程中审批单 流程中审批单由功能按钮区.特殊功能区.业务表单区.附件区.审批意见区等区域构成,其中,业务表单区理论上包含附件和意见,但是由于附件和意见的业务特殊性,需要单独进行管理,剩下的业务表单就可以看作文档了. 在一些流程审批业务中,业务信息有的是以Excel或word文件等方式专递,这样

SOA实践之基于服务总线的设计

在上文中,主要介绍了SOA的概念,什么叫做“服务”,“服务”应该具备哪些特性.本篇中,我将介绍SOA的一种很常见的设计实践--基于服务总线的设计. 基于服务总线的设计 基于总线的设计,借鉴了计算机内部硬件组成的设计思想(通过总线传输数据).在分布式系统中,不同子系统之间需要实现相互通信和远程调用,比较直接的方式就是“点对点”的通信方式,但是这样会暴露出一些很明显的问题:系统之间紧密耦合.配置和引用混乱.服务调用关系错综复杂.难以统一管理.异构系统之间存在不兼容等.而基于总线的设计,正是为了解决上

去中心化概念模型与架构设计

去中心化概念模型与架构设计 今天打算写写关于 IM 去中心化涉及的架构模型变化和设计思路,去中心化的概念就是说用户的访问不是集中在一个数据中心,这里的去中心是针对数据中心而言的. 站在这个角度而言,实际上并非所有的业务都能做去中心化设计,对于一致性要求越高的业务去中心化越难做.比如电商领域的库存就是一个对一致性要求很高的业务,不能超卖也不能少卖,这在单中心容易实现,但多中心纯从技术层面感觉无解,可能需要从业务和技术层面一起去做个折衷. 反过来看 IM 的业务场景是非常适合做去中心化设计的,因为其