当前位置:网站首页>Push related summary
Push related summary
2022-06-09 07:17:00 【The first person in the examination】

First of all, let's introduce the scenario above :
When our front end requests the rear terminal service , When our back terminal service handles related logic , It is likely that the complexity of the business will lead to http Request connection timed out , And for the current era , We all require high-performance systems , After the user submits a request , Separate assumptions 20s Just responded , Obviously, it is also unreasonable .
The traditional way to solve the above problems :
The front end sends the request , Our sub service can respond immediately and return , But the return is the request success, not the processing success , After the back-end business logic is processed , And then it is returned to the front end for processing , This obviously meets the requirements of high-performance systems . But there is also a problem http Request after our first response , The back end has no ability to notify the front end , And because the completion time of back-end business logic processing is uncertain , The traditional way is to call the service by front-end polling , This will greatly increase the pressure on the server , Obviously, although the above methods can solve , But we don't use .
The promotion method solves the above problems :

As shown in the figure above , We set up a push service ( use websocket agreement , Some companies are called message centers just by name ), When the sub service is unable to push the corresponding message to the front end , Push messages can be pushed to the message center , The message center maintains a long connection with the front end , In this way, messages can be pushed to the front end .( According to different front-end users, we can id And corresponding sessionId To establish a mapping relationship )
Websocket It's a full duplex protocol ( The server can push the front end , The front end can also be pushed to the server ), It is only used by the front-end push back-end http agreement , That is, half of it is used websocket agreement .
PS:Websocket Introduction to the agreement :HTML5 WebSocket | Novice tutorial
Use Java Language in springboot Realize... In the project :
The first must be import dependencies :
<!-- websocket rely on -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>Establish backend :
① structure WebSocket
package com.qianfeng.gp09.server;
import com.alibaba.fastjson.JSONObject;
import com.qianfeng.gp09.dao.MessageDao;
import com.qianfeng.gp09.model.Message;
import com.qianfeng.gp09.model.MessageExample;
import com.qianfeng.gp09.util.SpringContextUtil;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
/**
* websocket The server
*
*/
@ServerEndpoint("/webSocket/{uid}")
@Component
public class WebSocketServer {
/**
* Each user establishes a session with the server
* We consider saving the session
* One uid Corresponding to one session
* It should be a multi-threaded concurrency map
*/
private static ConcurrentHashMap<String,Session> sessionPool=new ConcurrentHashMap<>();
@Resource
private MessageDao messageDao;
/**
* When the connection is established , Method of operation .
* @param session Conversation object
* @param uid user id
*/
@OnOpen
public void onOpen(Session session, @PathParam(value="uid") String uid){
sessionPool.put(uid,session);
// Inquire about uid The news of state=0 And overTime Is greater than the current time .
MessageExample example=new MessageExample();
MessageExample.Criteria criteria = example.createCriteria();
criteria.andUidEqualTo(uid);
criteria.andStateEqualTo(0);
criteria.andOverTimeGreaterThanOrEqualTo(new Date());
if(messageDao==null){
// Get this object manually .
messageDao=SpringContextUtil.getBean(MessageDao.class);
}
List<Message> messages = messageDao.selectByExample(example);
sendMessage(session, JSONObject.toJSONString(messages));
}
/**
* When the other party sends me data , This method runs .
* @param message The message content
*/
@OnMessage
public void onMessage(String message){
// no need .
}
/**
* When the connection is closed , This method runs
* @param uid user id
*/
@OnClose
public void onClose(@PathParam(value="uid")String uid){
sessionPool.remove(uid);
}
/**
* When a connection error occurs , This method runs
* @param session Conversation object
* @param throwable error
*/
@OnError
public void onError(Session session,Throwable throwable){
throwable.printStackTrace();
}
/**
* according to session Send a message
* @param session Session with user
* @param message Content sent to users
*/
private boolean sendMessage(Session session,String message){
if(session!=null){
synchronized (session){
try{
// According to a session, Send message content to the other party .
session.getBasicRemote().sendText(message);
return true;
}catch (Exception e){
e.printStackTrace();
return false;
}
}
}
return false;
}
/**
* Appoint id Send messages to users
* Implementation of business logic
* @param uid user id
* @param message The content of the message sent to the user
* @return Whether the sending is successful
*/
public boolean sendInfo(String uid,String message){
Session session=sessionPool.get(uid);
if(session==null){
return false;
}
return sendMessage(session,message);
}
}
② structure websockect The configuration is as follows :
package com.qianfeng.gp09.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
/**
* Configuration manager
*
*/
@Configuration
public class WebSocketConfig {
/**
* To configure a serverendpoint
* Used to manage the connection server uri
*/
@Bean
public ServerEndpointExporter serverEndpointExporter(){
return new ServerEndpointExporter();
}
}
③ stay controller In the injection :
package com.qianfeng.gp09.controller;
import com.alibaba.fastjson.JSONObject;
import com.qianfeng.gp09.dto.MessageDTO;
import com.qianfeng.gp09.model.Message;
import com.qianfeng.gp09.model.User;
import com.qianfeng.gp09.result.R;
import com.qianfeng.gp09.server.WebSocketServer;
import com.qianfeng.gp09.service.PushService;
import com.qianfeng.gp09.service.UserService;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
/**
* User interface
*
*/
@RestController
@RequestMapping("qf/user")
public class UserController {
@Resource
private WebSocketServer webSocketServer;
@Resource
private PushService pushService;
@PostMapping("pushWeb")
public R pushWeb(@RequestBody MessageDTO messageDTO){
String uid=messageDTO.getUid();
String message=messageDTO.getMessage();
Integer overTime=messageDTO.getOverTime();
boolean flag = webSocketServer.sendInfo(uid, message);
Message msg=new Message();
msg.setUid(uid);
msg.setContent(message);
msg.setSendTime(new Date());
msg.setOverTime(new Date(System.currentTimeMillis()+overTime*1000*60));
if(flag){
msg.setState(1);
pushService.saveMessage(msg);
return R.ok(" Send successfully ");
}else{
msg.setState(0);
pushService.saveMessage(msg);
return R.ok(" User offline , Push task has been set .");
}
}
}
Build the front end :
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<input type="text" id="uid" placeholder=" Please enter id"/>
<br>
<button onclick="onConnectionClick();"> Connect to server </button>
<br>
<div id="messages"></div>
<script>
let socket;
function onConnectionClick(){
if(typeof(WebSocket) == "undefined") {
// This browser does not support WebSocket
alert(" Please use the latest Google Chrome browser ");
return ;
}
if(socket!=null){
socket.close();
socket=null;
}
// Get the id
let uid=document.getElementById("uid").value;
// Connect to the server url
let url="ws://localhost:8080/webSocket/"+uid;
// Instantiation webSocket
socket=new WebSocket(url);
socket.onopen=function(){
console.info(" A connection has been established with the server ");
};
socket.onmessage=function(msg){
let receiveMessage=msg.data;
document.getElementById("messages").innerHTML+="<span>"+receiveMessage+"</span><br>"
};
socket.onclose=function(){
console.info(" Disconnected from the server ");
};
socket.onerror=function(){
console.info(" An error occurred while connecting to the server ");
};
}
</script>
</body>
</html>PS: In verifying the above logic , encounter dao The problem of null pointer of items during layer injection , This is because Spring At the time of Injection , According to the situation and notes , It is injected in a different order , So I wrote a tool class directly , You can use injection directly , There is no need to focus on the order . Tools are as follows :
package com.qianfeng.gp09.util;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
/**
* spring Tool classes for context
*
*
*/
@Component
public class SpringContextUtil implements ApplicationContextAware {
/**
* It is spring Context object , You can use it to get spring Any object in the container
*/
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
SpringContextUtil.applicationContext=applicationContext;
}
public static <T> T getBean(Class<T> clazz){
return applicationContext.getBean(clazz);
}
}
There is also an extension of the above , The details are shown in the picture , Do not go into :

Mobile terminal APP push

First, describe the above scenario :
When one of our mobile phones App You want to push messages to your mobile phone , We use a third-party Aurora server or Youmeng server , Explain why , Pictured above , If you do not use a three-party integrated server , Servers for different mobile phones , our App All have to be connected separately , And special customer service is needed to ensure the smoothness of this line , Therefore, the three-party integration platform is recommended , They help us connect with all mobile phone manufacturers .
边栏推荐
猜你喜欢

10. regular expression matching

Naive Bayes classifier

The 11th finals of the electronic single chip microcomputer of the Blue Bridge Cup

Technology sharing | discussion on the design of dispatching platform

Squid代理服务器应用

性能测试流程,指标,实现方法以及总结

UML summary

数据可视化之特别案例的运用与分析

UML series articles (25) high level behavior - state diagram
The new colleagues optimized the project performance once, trembling
随机推荐
5. Multimedia Foundation
[STL] Introduction to the use of set and map
多余的时间不要浪费,玩玩手机可开启“副业人生”
New occupation: digital management abbess is in hot demand. As long as she comes for an interview, the enterprise will make an offer
Matlab: difference between tf2zp and tf2zpk
Opengauss database operation steps
多线程-程序进程线程的概念
10. regular expression matching
How to select Bucher hydraulic pump? It is important to master these three points!
Performance test process, index, implementation method and summary
257. all paths of binary tree
UML series articles (20) basic behavior - activity diagram
Distributed message middleware -- Introduction to message queue
[guide to stepping on the big pit] CSharp_ Process_ Prompt after running: no such file or pyinstaller prompt badzip, etc
Flutter learning Hello World
Common classes - overview of string classes
Squid proxy application
Jump from one pit to another
Do you really understand the logic that two objects are equal in dart?
Google browser F12 (developer tool) ---network