存储优化

第一种情况,站内的用户是少量级别的。(几十到上百)

这种情况,由于用户的数量非常少,因此,没有必要过多的考虑数据库的优化,采用简单的表格,对系统的设计也来的简单,后期也比较容易维护,是典型的用空间换时间的做法。

数据库的设计如下:表名:Message

ID:编号;SendID:发送者编号;RecID:接受者编号(如为0,则接受者为所有人);Message:站内信内容;Statue:站内信的查看状态;PDate:站内信发送时间;

第二种情况,站内的用户中量级别的(上千到上万)。

如果还是按照第一种情况的思路。那发一条站内信的后果基本上就是后台崩溃了。因为,发一条站内信,得重复上千个插入记录,这还不是最主要的,关键是上千 乃至上万条记录,Message字段的内容是一样的,而Message有大量的占用存储空间。比方说,Message字段有100个汉字,占用200个字 节,那么5万条,就占用200×50000=10000000个字节=10M。简单的一份站内信,就占用10M,这还让不让人活了。

因此,将原先的表格拆分为两个表,将Message的主体放在一个表内,节省空间的占用

数据库的设计如下:

表名:Message

ID:编号;SendID:发送者编号;RecID:接受者编号(如为0,则接受者为所有人);MessageID:站内信编号;Statue:站内信的查看状态;

表名:MessageText

ID:编号;Message:站内信的内容;PDate:站内信发送时间;

在管理员发一封站内信的时候,执行两步操作。先在MessageText表中,插入站内信的内容。然后在Message表中给所有的用户插入一条记录,标识有一封站内信。

这样的设计,将重复的站内信的主体信息(站内信的内容,发送时间)放在一个表内,大量的节省存储空间。不过,在查询的时候,要比第一种情况来的复杂。

第三种情况,站内的用户是大量级的(上百万),并且活跃的用户只占其中的一部分。

大家都有这样的经历,某日看一个网站比较好,一时心情澎湃,就注册了一个用户。过了一段时间,由于种种原因,就忘记了注册时的用户名和密码,也就不再登陆了。那么这个用户就称为不活跃的。从实际来看,不活跃的用户占着不小的比例。

我们以注册用户2百万,其中活跃用户只占其中的10%。

就算是按照第二种的情况,发一封“站内信”,那得执行2百万个插入操作。但是其中的有效操作只有10%,因为另外的90%的用户可能永远都不会再登陆了。

在这种情况下,我们还得把思路换换。

数据库的设计和第二种情况一样:

表名:Message

ID:编号;SendID:发送者编号;RecID:接受者编号(如为0,则接受者为所有人);MessageID:站内信编号;Statue:站内信的查看状态;

表名:MessageText

ID:编号;Message:站内信的内容;PDate:站内信发送时间;

管理员发站内信的时候,只在MessageText插入站内信的主体内容。Message里不插入记录。

那么,用户在登录以后,首先查询MessageText中的那些没有在Message中有记录的记录,表示是未读的站内信。在查阅站内信的内容时,再将相关的记录插入到Message中。

这个方法和第二种的比较起来。如果,活跃用户是100%。两者效率是一样的。而活跃用户的比例越低,越能体现第三种的优越来。只插入有效的记录,那些不活跃的,就不再占用空间了。

查询优化

使用Ajax轮询开销大,可以使用websocket来实现。JavaEE 7中出了JSR-356:Java API for WebSocket规范。不少Web容器,如Tomcat,Nginx,Jetty等都支持WebSocket。Tomcat从7.0.27开始支持 WebSocket,从7.0.47开始支持JSR-356,下面的Demo代码也是需要部署在Tomcat7.0.47以上的版本才能运行。

1、添加依赖包

javax

javaee-api

7.0

provided

2、JS代码

var websocket = null;//判断当前浏览器是否支持WebSocket

if ('WebSocket' inwindow) {

websocket= new WebSocket("ws://localhost:8080/websocket");

}else{

alert('当前浏览器 Not support websocket')

}//连接发生错误的回调方法

websocket.onerror =function () {

setMessageInnerHTML("WebSocket连接发生错误");

};//连接成功建立的回调方法

websocket.onopen =function () {

setMessageInnerHTML("WebSocket连接成功");

}//接收到消息的回调方法

websocket.onmessage = function (event) {

setMessageInnerHTML(event.data);

}//连接关闭的回调方法

websocket.onclose =function () {

setMessageInnerHTML("WebSocket连接关闭");

}//监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。

window.onbeforeunload =function () {

closeWebSocket();

}//将消息显示在网页上

function setMessageInnerHTML(innerHTML) {

document.getElementById('message').innerHTML += innerHTML + '
';

}//关闭WebSocket连接

function closeWebSocket() {

websocket.close();

}//发送消息

function send() {var message = document.getElementById('text').value;

websocket.send(message);

}

3、后端代码

import java.io.IOException;

import java.util.concurrent.CopyOnWriteArraySet;

import javax.websocket.*;

import javax.websocket.server.ServerEndpoint;/**

* @ServerEndpoint 注解是一个类层次的注解,它的功能主要是将目前的类定义成一个websocket服务器端,

* 注解的值将被用于监听用户连接的终端访问URL地址,客户端可以通过这个URL来连接到WebSocket服务器端*/@ServerEndpoint("/websocket")public classWebSocketTest {//静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。

private static int onlineCount = 0;//concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。若要实现服务端与单一客户端通信的话,可以使用Map来存放,其中Key可以为用户标识

private static CopyOnWriteArraySet webSocketSet = new CopyOnWriteArraySet();//与某个客户端的连接会话,需要通过它来给客户端发送数据

privateSession session;/**

* 连接建立成功调用的方法

* @param session 可选的参数。session为与某个客户端的连接会话,需要通过它来给客户端发送数据*/@OnOpenpublic voidonOpen(Session session){this.session =session;

webSocketSet.add(this); //加入set中

addOnlineCount(); //在线数加1

System.out.println("有新连接加入!当前在线人数为" +getOnlineCount());

}/**

* 连接关闭调用的方法*/@OnClosepublic voidonClose(){

webSocketSet.remove(this); //从set中删除

subOnlineCount(); //在线数减1

System.out.println("有一连接关闭!当前在线人数为" +getOnlineCount());

}/**

* 收到客户端消息后调用的方法

* @param message 客户端发送过来的消息

* @param session 可选的参数*/@OnMessagepublic voidonMessage(String message, Session session) {

System.out.println("来自客户端的消息:" +message);//群发消息

for(WebSocketTest item: webSocketSet){try{

item.sendMessage(message);

}catch(IOException e) {

e.printStackTrace();continue;

}

}

}/**

* 发生错误时调用

* @param session

* @param error*/@OnErrorpublic voidonError(Session session, Throwable error){

System.out.println("发生错误");

error.printStackTrace();

}/**

* 这个方法与上面几个方法不一样。没有用注解,是根据自己需要添加的方法。

* @param message

* @throws IOException*/

public voidsendMessage(String message) throws IOException{this.session.getBasicRemote().sendText(message);//this.session.getAsyncRemote().sendText(message);

}public static synchronized intgetOnlineCount() {returnonlineCount;

}public static synchronized voidaddOnlineCount() {

WebSocketTest.onlineCount++;

}public static synchronized voidsubOnlineCount() {

WebSocketTest.onlineCount--;

}

}

浏览器通过JavaScript向服务端发出建立WebSocket连接的请求,在WebSocket连接建立成功后,客户端和服务端就可以通过 TCP连接传输数据。因为WebSocket连接本质上是TCP连接,不需要每次传输都带上重复的头部数据,所以它的数据传输量比轮询和Comet技术小 了很多。

java 实现站内信_群发站内信实现相关推荐

  1. 仿站和模板建站的区别_建站方式多种,哪个比较适合?

    网站制作一年350元,五站合一,快速建站 ,www.sxjcwzjs.com,只需进入网站右上角注册快速建站即可(需要电脑登录注册),需要联系我吧!电话:13752214574,微信号:m107858 ...

  2. 如何利用腾讯云短信服务群发祝福短信?

    节日问候以及日常问候已经是企业维护已有会员的重要方式之一,我们可以利用腾讯云短信服务群发节假日祝福以及问候短信. 准备工作: 1.购买腾讯云短信套餐包[国内短信首购低至0.032元/条] 2.准备短信 ...

  3. java站群系统_分布式站群系统设计与实现

    摘  要: 分析了高等院校构建网站时遇到的普遍问题,提出了文件分布存储.数据集中存储的设计思想,并且在Java EE平台上设计和实现了分布式站群管理系统,其站点分布式部署.高度的代码共享.内嵌的网页编 ...

  4. listctrl 优化_上海SEO整站优化公司_新站整站快速排名优化

    百度营销凭借强大的用户产品优势,每天数十亿次搜索请求.超过1亿用户浏览百度信息流.800亿次定位服务请求,为客户提供全系列产品广告资源覆盖用户生活全场景. seo搜索优化具体长期稳定流量,推广费用极低 ...

  5. java 代码圣诞的祝福_圣诞祝福短信全集

    1.一天我擦亮阿拉丁的神灯,灯神说:我会满足你一个愿望.我说:请祝福正在看短信的人圣诞快乐! 2.孩子,我是圣诞老人,有一份圣诞大礼要送给你.什么--你们家没有烟囱?还不去买! 3.如果圣诞老人给我一 ...

  6. 机器人磨内孔_半导体阀块内孔机器人打磨,效果超乎想象!

    导读:伴随着芯片的集成度越来越高,半导体制造的先进程度也逐渐提升.阀块作为半导体制造设备的一个重要零部件,其精度要求也随着半导体制造要求的提高而提升,工艺加工难度也越大. 图源pixbay 以阀块内孔 ...

  7. python perl 比较生信_科学网—生信人写程序1. Perl语言模板及配置 - 刘永鑫的博文...

    科学网对Markdown排版支持较差,对格式不满意的用户请跳转至 CSDN 或微信阅读: 如果感觉文章对您有帮助,想继续阅读同类文章,请扫描下方二维码关注"生信宝典"公众号,每天接 ...

  8. ssh 怎么通过跳板机传文件到内网_黑客攻击内网穿透

    声明:严禁用作非法目的,谢绝一切形式的转载. 如何实现远程打卡?远程打卡的问题在于你和公司处在不同的局域网之中,要实现远程打卡,虽然有些软件可以使用(比如向日葵.teamviwer等),但是实现功能也 ...

  9. qq 实现连接内网_如何穿透内网稳定进行远程桌面?花生壳盒子来搞定

    内网的电脑访问,一直都是一个比较麻烦的问题,虽然可以通过路由器来设置,但是对于很多用户来说,那繁琐的设置,简直就跟天书一样,劝退效果一流.笔者从事IT行业,内网穿透笔者有需求,笔者的很多客户也有这样的 ...

  10. python工程师求职信_如何写求职信更容易被录用?

    用用邮箱投递简历,如何在求职信中简短有力地说明自己的优势和与应聘岗位的匹配点,给HR留有印象呢? 1⃣️开头--称谓得当,注重礼节 在求职信的开头要有称谓,一般为"尊敬的×××,您好&quo ...

最新文章

  1. json数据解析_ORACLE中Clob字段在不同数据库间自由地飞翔——SQL+JSON字段解析
  2. TikTok游戏话题浏览上涨,预示出海新机会
  3. 智能合约重构社会契约 (4)预言机基础说明
  4. ArcGIS编辑操作的常用快捷键一览表
  5. 分治法在排序算法中的应用(JAVA)--快速排序(Lomuto划分、Hoare划分、随机化快排)
  6. manchi翻译中文 mi_求这一段意大利文歌词中文翻译(Mi Manchi)
  7. MySQL基础篇(07):用户和权限管理,日志体系简介
  8. 小米手机不弹出usb连接设置_安卓手机数据备份教程(华为、小米、oppo、vivo)...
  9. 毕设一:python 爬取苏宁的商品评论
  10. PixiJS学习(9)动画序列帧
  11. Ubuntu20.04下opencv的安装
  12. android 壁纸改变回调,android_launcher的源码详细分析和壁纸修改
  13. 发现隐患里的自己,原来我是**人!
  14. 360看在线视频加速
  15. 敏捷顾问的MBTI体验:8个认知能力胜过4个字母组合
  16. 抢答器c语言程序设计,基于单片机的智能抢答器设计与实现
  17. 如何将小鹤单字挂接到搜狗输入法
  18. 数学建模之规划1——线性规划
  19. PAT练习 蜜蜂寻路
  20. Android自定义相机镂空遮罩

热门文章

  1. 红米手机html文件,红米手机怎么传文件到电脑
  2. 必读| 关于机器学习最全面无痛的入门路径和资源!(下)
  3. 电子签名如何制作——word
  4. Python实例3:中文词语统计
  5. 家里蹲太孤单?来用python画一只单身狗吧
  6. 荣耀4a刷android 6,荣耀4A全网通(SCL-AL00)一键救砖教程,轻松刷回官方系统
  7. 易捷行云新一代私有云平滑无感升级|轻运维之升级
  8. 李沐动手学深度学习V2-BERT预训练和代码实现
  9. 趣味小游戏——扫雷(优化版)
  10. mysql lsl_GitHub - LSL-Git/MyBatis_Dynamic_SQL: mybatis 动态SQL使用