论坛乐鱼app乐鱼app官网首页 综合技术论坛

[完结13章]c 从0实现百万并发reactor服务器 -乐鱼入口

浏览 219 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2024-01-29  
学习地址:https://pan.baidu.com/s/1ghdnvoomuqevr4nrtnmf2w 提取码:4upy
备用地址:https://share.weiyun.com/yamzj8n9 密码:viangd


是否具备高并发、高性能、分布式、事件驱动框架设计能力,是优秀c 中高级工程师的分水岭,我将通过本文带领大家纯手写一个reactor服务器,让大家可以高效掌握三高框架设计思维,同时让你对c 网络编程、线程、智能指针、c 11标准高阶技术等运用自如。

 reactor是一种事件驱动机制,和普通函数调用的不同之处在于:应用程序不是主动的调用某个api完成处理,而是恰恰相反,reactor逆置了事件处理流程,应用程序需要提供相应的接口并注册到reactor上,如果相应的事件发生,reactor将主动调用应用程序注册的接口,这些接口又称为“回调函数”。用“好莱坞原则”来形容reactor再合适不过了:不要打电话给我们,我们会打电话通知你。

websocket是基于tcp协议的应用层协议,也就是建立在tcp协议之上的自定义协议。这个协议比http协议更加的简单,因为websocket只对协议的格式做要求,只要符合数据格式就可以使用。
  websocket一般用来服务器主动推送消息给客户端,反观http,http是请求响应的模式,客户端来一个请求,服务器响应一个请求,服务器无法主动发送数据给客户端;并且使用websocket,客户端和服务器只需要一次“握手”,两者之间就成功建立了长连接,可以双向传输数据

项目定位
a. 主从reactor模型服务器,主reactor线程只负责监听描述符,获取新建连接。这样就保证了新连接的获取比较高效,提高了服务器的并发性能。主reactor获取到新连接后分发给子reactor进行通信事件监控。

b.子(从)reactor线程监控各自文件描述符下的读写事件,进行数据读写以及业务处理。

c.one thread one loop的思想就是把所有的操作都放到线程中进行,一个线程对应一个eventloop。

在com.example.emos.wx.config.shiro中创建shiroconfig类。
package com.example.emos.wx.config.shiro;

import org.apache.shiro.mgt.securitymanager;
import org.apache.shiro.spring.lifecyclebeanpostprocessor;
import org.apache.shiro.spring.security.interceptor.authorizationattributesourceadvisor;
import org.apache.shiro.spring.web.shirofilterfactorybean;
import org.apache.shiro.web.mgt.defaultwebsecuritymanager;
import org.springframework.context.annotation.bean;
import org.springframework.context.annotation.configuration;

import javax.servlet.filter;
import java.util.hashmap;
import java.util.linkedhashmap;
import java.util.map;

@configuration
public class shiroconfig {

    @bean("securitymanager")
    public securitymanager securitymanager(oauth2realm oauth2realm) {
        defaultwebsecuritymanager securitymanager = new defaultwebsecuritymanager();
        securitymanager.setrealm(oauth2realm);
        securitymanager.setremembermemanager(null);
        return securitymanager;
    }

    @bean("shirofilter")
    public shirofilterfactorybean shirofilter(securitymanager securitymanager,oauth2filter oauth2filter) {
        shirofilterfactorybean shirofilter = new shirofilterfactorybean();
        shirofilter.setsecuritymanager(securitymanager);

        //oauth过滤
        map filters = new hashmap<>();
        filters.put("oauth2", oauth2filter);
        shirofilter.setfilters(filters);

        map filtermap = new linkedhashmap<>();
        filtermap.put("/webjars/**", "anon");
        filtermap.put("/druid/**", "anon");
        filtermap.put("/app/**", "anon");
        filtermap.put("/sys/login", "anon");
        filtermap.put("/swagger/**", "anon");
        filtermap.put("/v2/api-docs", "anon");
        filtermap.put("/swagger-ui.html", "anon");
        filtermap.put("/swagger-resources/**", "anon");
        filtermap.put("/captcha.jpg", "anon");
        filtermap.put("/user/register", "anon");
        filtermap.put("/user/login", "anon");
        filtermap.put("/test/**", "anon");
        filtermap.put("/**", "oauth2");
        shirofilter.setfilterchaindefinitionmap(filtermap);
        return shirofilter;
    }

    @bean("lifecyclebeanpostprocessor")
    public lifecyclebeanpostprocessor lifecyclebeanpostprocessor() {
        return new lifecyclebeanpostprocessor();
    }

    @bean
    public authorizationattributesourceadvisor authorizationattributesourceadvisor(securitymanager securitymanager) {
        authorizationattributesourceadvisor advisor = new authorizationattributesourceadvisor();
        advisor.setsecuritymanager(securitymanager);
        return advisor;
    }

}


向后端提交数据之前,我们先要做好前端的数据验证,比如说验证激活码必须是6位数字。
let that = this;
if (that.registercode == null || that.registercode.length == 0) {
uni.showtoast({
title: '邀请码不能为空',
icon: 'none'
});
return;
}
else if (/^[0-9]{6}$/.test(that.registercode) == false) {
uni.showtoast({
title: '邀请码必须是6为数字',
icon: 'none'
});
return;
}
在onshow()函数中发送ajax请求,检查当前时刻能否签到
onshow: function() {
let that = this;
that.ajax(that.url.validcancheckin, 'get', null, function(resp) {
let msg = resp.data.msg;
if (msg != '可以考勤') {
settimeout(function() {
uni.showtoast({
title: msg,
icon: 'none'
});
}, 1000);
that.cancheckin = false;
}
});
}

我个人对于reactor的理解,reactor主要围绕事件派发和自动反应展开的,就比如连接请求到来,epoll_wait提醒程序员就绪的事件到来,应该尽快处理,则与就绪事件相关联的sock会对应着一个connection结构体,这个结构体我觉得就是反应堆模式的精华所在,无论是什么样就绪的事件,每个sock都会有对应的回调方法,所以处理就绪的事件很容易,直接回调connection内的对应方法即可,是读事件就调用读方法,是写事件就调用写方法,是异常事件,则在读方法或写方法中处理io的同时,顺便处理掉异常事件。
 
global site tag (gtag.js) - google analytics
网站地图