At that time, the project was developed for a media company in mid-2019. It has many functions, but it does not involve many technical points. It may be the reason why customers need fewer functions. But it's still quite cumbersome, because there are many function points.
Dominate the screen, grab red envelopes, interaction, crowdfunding, cash withdrawal, reward, reward animation, agency, etc.
The project is net 4.5, because it was considered that the large screen should be synchronized with the user in real time and the user should be connected with the user, so we didn't choose php (not because php is not good, but our company's technology stack is. net, so we can only use php to make some simple cms and websites. Don't spray php). At first, I wanted to use polling. I thought there was a delay, and the concurrency would explode. Later, considering the long connection and H5 WebSocket, we started to implement them ourselves at first. Later, we learned that Microsoft has a special solution for this, namely [SignalR], which is very simple to use and reliable in stability. We will automatically select polling according to the user's environment. Long connection or WebSocket.
At the bottom of the article is the effect of the project. At that time, customers carried out more than 20 bars, and less than 1000 people were online at the peak. At that time, the server used was 8g, 8-core, the cpu was less than 30%, and the memory was about 4 G. it may be that the user scale has not come up yet. The database uses Sql server 2008R2,iis 8.5. Red envelope grabbing uses the redis+lua script, which is quite reliable. Because there was a queue on the screen at that time, it was also implemented using redis+lua.
The design idea is to set up a separate chat room for each bar. After entering through the QR code, each user is bound into the chat room of the bar, and the chat information and screen information are pushed to the large screen. It just happens that signalr has type functions. How to use signalr is not repeated. There are many searches on the Internet. Here we only talk about the design ideas.
The following is the code entered by the js user
$.connection.hub.qs = { nId:nid }; //Unique ID generated in the background for the bar var chat = $.connection.chatHub; chatClientCore = chat.client; $.connection.hub.start().done(function () { chatServerCore = chat.server; console.log("Connection succeeded!"); }); $.connection.hub.disconnected(function () { if (reConnect == undefined || reConnect==null) { reConnectServer();//Reconnect } });
When users connect to the chat room, they will be added to the collection of the bar in the background
public override Task OnConnected() { //When connecting data //UserInfo u = new SessionRedisHub(Context).GetLoginUser(); string cid = Context.ConnectionId; //Here, nid is obtained from the parameters passed from the previous connection int nId = Convert.ToInt32(Context.QueryString["nId"]); Groups.Add(cid, "node_" + nId); return base.OnConnected(); }
Here's a detail. If you need private chat, you have to save the cid when connecting. In our project, redis is used for session. The specific implementation details can also be found on the Internet. The web address is not recorded here. It needs to be mentioned again here, that is, if it is realized by itself, it needs to be in startup IUserIdProvider is registered in configuresignalr with the following code
public static void ConfigureSignalR(IAppBuilder app) { var userIdProvider = new MyUserFactory(); GlobalHost.DependencyResolver.Register(typeof(IUserIdProvider), () => userIdProvider); //var config = new HubConfiguration(); //app.MapSignalR("/chat",config); app.MapSignalR(); } //MyUserFactory public class MyUserFactory : IUserIdProvider { /// <summary> ///Get the sessionid stored by the current login user /// </summary> /// <param name="request"></param> /// <returns></returns> public string GetUserId(IRequest request) { string cnnId = new SessionRedis(request).SessionId; if (!string.IsNullOrEmpty(cnnId)) return cnnId; return "404"; } }
When sending a private chat, you can directly take the sessionID and send it to the user
//Group chat code ChatToNodeInfo nInfo = ChatCorrelation.GetChatNode(cId); Clients.OthersInGroup("node_" + nInfo.MNId).BPtoScreen(nInfo); //Private chat code Clients.User(new SessionRedisHub(Context).SessionId).test(cPageInfo); //Push large screen IHubContext ScreenHub = GlobalHost.ConnectionManager.GetHubContext<ScreenHub>(); nInfo.PostTime = DateTime.Now.ToString("MM-dd HH:mm"); ScreenHub.Clients.Group("screen_"+nInfo.MNId).BPtoScreen(nInfo);
The large screen is similar to the chat room, that is, the added group names cannot be the same, because the large screen accepts push unilaterally. If the content of the chat room wants to be pushed to the large screen, it only needs to obtain the Hub of the large screen to complete the push.
The general implementation scheme is like this. After using signal, the implementation is still relatively simple. The specific details still depend on the specific business.
Red envelope grabbing and screen bullying are both controlled by redis. I'll write it next time.
Some pictures of the project