当前位置: 首页 > news >正文

04 http连接处理(上)

基础知识:epoll、http报文格式、状态码和有限状态机
代码:对服务端处理http请求的全部流程进行简要介绍,然后结合代码对http类及请求接收进行详细分析。

epoll

epoll_create函数

#include <sys/epoll.h>
int epoll_create(int size)

创建一个指示epoll内核事件表的文件描述符,该描述符将用作其他epoll系统调用的第一个参数,size不起作用。

epoll_ctl函数

#include <sys.epoll.h>
int epoll_ctl(int epfd,int op,struct epoll_event *event)

该函数用于操作内核事件表监控的文件描述符上的事件:注册、修改、删除

  • epfd:为epoll_create的句柄
  • op:表示动作,用3个宏来表示
    EPOLL_CTL_ADD注册新的fd到epfd
    EPOLL_CTL_MOD修改已经注册的fd的监听事件
    EPOLL_CTL_DEL从epfd删除一个fd
  • event:告诉内核需要监听的事件
    上述event是epoll_event结构体指针类型,表示内核所监听的事件,具体定义如下:
struct epoll_event{
__unit32_t events;
epoll_data_t data;
};
  • events描述事件类型,其中epoll事件类型有以下几种:
    EPOLLIN表示对应的文件描述符可读(包括对端SOCKET正常关闭)
    EPOLLOUT表示对应的文件描述符可以写
    EPOLLPRI表示对应的文件描述符有紧急的数据可读(这里应该表示有带外数据到来)
    EPOLLERR表示对应的文件描述符发生错误
    EPOLLHUP表示对应的文件描述符被挂断
    EPOLLET将EPOLL设为边缘触发Edge Triggered模式,这是相对于水平触发Level Triggered而言的
    EPOLLONESHOT只监听一次事件,当监听完这次事件之后,如果还需要继续监听这个socket的话,需要再次把这个socket加入到EPOLL队列里

epoll_wait函数

#include <sys/epoll.h>
int epoll_wait(int epfd,struct epoll_event *events,int maxevents,int timeout)

该函数用于等待所监控文件描述符上有事件的产生,返回就绪的文件描述符个数

  • events:用来存内核得到事件的集合
  • maxevents:告之内核整个events有多大,这个maxevents的值大于创建epoll_create()时的size
  • timeout超时时间
    -1:阻塞
    0:立即返回,非阻塞
    大于0:指定毫秒
  • 返回值:成功返回有多少文件描述符就绪,事件到时返回0,出错返回-1

select/poll/epoll

  • 调用函数
    select和poll都是一个函数,epoll是一组函数
  • 文件描述符数量
    select通过线性表描述文件描述符集合,文件描述符有上限,一般是1024,但可以修改源码,重新编译内核,不推荐
    poll是链表描述,突破了文件描述符上限,最大可以打开文件的数目
    epoll通过红黑树描述,最大可以打开文件的数目,可以通过命令ulimit -n number修改,仅对当前终端有效
  • 将文件描述符从用户传给内核
    select和poll通过将所有文件描述符拷贝到内核态,每次调用都需要拷贝
    epoll通过epoll_create建立一棵红黑树,通过epoll_ctl将要监听的文件描述符注册到红黑树上
  • 内核判断就绪的文件描述符
    select和poll通过遍历文件描述符集合,判断哪个文件描述符上有事件发生
    epoll_create时,内核除了帮我们在epoll文件系统里建了个红黑树用于存储以后epoll_ctl传来的fd外,还会再建立一个list链表,用于存储准备就绪的事件,当epoll_wait调用时,仅仅观察这个list链表里有没有数据即可
    epoll是根据每个fd上面的回调函数(中断函数)判断,只有发生了事件的socket才会主动的去调用callback函数,其他空闲状态socket则不会,若是就绪事件,插入list
  • 应用程序索引就绪文件描述符
    select/poll只返回了事件的文件描述符的个数,若知道是哪个事件发生了事件,同样需要遍历
    epoll返回的发生了事件的个数和结构体数组,结构体包含socket的信息,因此直接处理返回的数组即可
  • 工作模式
    select和poll都只能工作在相对低效的LT模式下
    epoll则可以工作在ET高效模式,并且epoll还支持EPOLLONESHOT事件,该事件能进一步减少可读、可写和异常事件被触发的次数。
  • 应用场景
    当所有的fd都是活跃连接,使用epoll,需要建立文件系统,红黑书和链表对于此来说,效率反而不高,不如select和poll
    当监测的fd数目较小,且各个fd都比较活跃,建议使用select或者poll
    当监测的fd数目非常大,成千上万,且单位时间只有其中一部分fd处于就绪状态,这个时候使用epoll能够明显提升性能。

ET、LT、EPOLLONESHOT

  • LT水平触发模式
    epoll_wait检测到文件描述符有事件发生,则将通知给应用程序,应用程序可以不立即处理该事件;当下一次调用epoll_wait时,epoll_wait还会再次向应用程序报告此事件,直至被处理。
  • ET边缘触发模式
    epoll_wait检测到文件描述符有事件发生,则将其通知给应用程序,应用程序必须立即处理该事件;必须要一次性将数据读取完,使用非阻塞I/O,读取到出现eagain
  • EPOLLONESHOT
    一个线程读取某个socket上的数据后开始处理数据,在处理过程中该socket上又有新数据可读,此时另一个线程被唤醒读取,此时出现两个线程处理同一个socket
    我们期望的是一个socket连接在任一时刻都只被一个线程处理,通过epoll_ctl对该文件描述符注册epolloneshot事件,一个线程处理socket时,其他线程无法处理,当线程处理完后,需要通过epoll_ctl重置epolloneshot事件

HTTP报文格式

HTTP报文分为请求报文和响应报文两种,每种报文必须按照特有格式生成,才能浏览器端识别。其中,浏览器端向服务器发送的为请求报文,服务器处理后返回给浏览器端的为响应报文。

请求报文

HTTP请求报文由请求行、请求头部、空行和请求数据四个部分组成。
请求分为GET和POST两种。

  • GET

在这里插入图片描述

  • POST
1     POST / HTTP1.1
2     Host:www.wrox.com
3     User-Agent:Mozilla/4.0 (compatible;MSIE 6.0; Windowa NT 5.1;SV1; .NET CLR 2.0.50727; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022)
4     Content-Type:application/x-www-form-urlencoded
5     Content-Length:40
6     Connection:Keep-Alive
7     空行
8     name=Professional%20Ajax&publisher=Wiley
  • 请求行:说明请求类型,要访问的资源以及所使用的HTTP版本

GET说明请求类型为GET,/562f25980001b1b106000338.jpg(URL)为要访问的资源,该行的最后一部分说明使用的是HTTP1.1版本。

  • 请求头部:紧接着请求行(第一行)之后的部分,用来说明服务器要使用的附加信息。

HOST,给出请求资源所在服务器的域名
User-Agent,HTTP客户端程序的信息,该信息由你发出请求使用的浏览器来定义,并且在每个请求中自动发送等。
Accept,说明用户代理可处理的媒体类型。
Accept-Encoding,说明用户代理支持的内容编码。
Accept-Language,说明用户代理能够处理的自然语言集
Content-Type,说明实现主体的媒体类型
Content-Length,说明实现主体的大小
Connection,连接管理,可以是Keep-Alive或close

  • 空行,请求头部后面的空行是必须的即使第四部分请求数据为空,也必须有空行
  • 请求数据也叫主体,可以添加任意的其他数据

响应报文

HTTP响应也由四个部分组成,分别是:状态行、消息报头、空行和响应正文
在这里插入图片描述

  • 状态行,由HTTP协议版本号,状态码,状态消息 三部分组成

第一行为状态行,(HTTP/1.1)表明HTTP版本为1.1版本,状态码为200,状态消息为OK

  • 消息报头,用来说明客户端要使用的一些附加信息

第二行和第三行为消息报头,Date生成响应的日期和时间;Content-Type指定了MME类型的HTML(text/html),编码类型是UTF-8

  • 空行,消息报头后面的空行是必须的
  • 响应正文,服务器返回给客户端的文本信息。空行后面的html部分为响应正文。

HTTP状态码

  • 1xx:指示信息-表示请求已接收,继续处理。
  • 2xx:成功-表示请求正常处理完毕
    200 OK:客户端请求被正常处理
    206 Partial content:客户端进行了范围请求
  • 3xx:重定向-要完成请求必须进行更进一步的操作
    301 Moved Permanently:永久重定向,该资源已被永久移动到新位置,将来任何对该资源的访问都要使用本响应返回的若干个URL之一。
    302 Found:临时重定向,请求的资源现在临时从不同的URI中获得
  • 4xx:客户端错误-请求有语法错误,服务器无法处理请求
    400 Bad Request:请求报文存在语法错误
    403 Forbidden:请求被服务器拒绝
    404 Not Found:请求不存在,服务器上找不到请求的资源
  • 5xx:服务器端错误-服务器处理请求出错
    500 Internal Server Error:服务器在执行请求时出现错误

有限状态机

有限状态机,是一种抽象的理论模型,它能够把有限个变量描述的状态变化过程,以可构造可验证的方式呈现出来。比如,封闭的有向图。
有限状态机可以通过if-else,switch-case和函数指针来实现,从软件工程的角度看,主要是为了封装逻辑。
带有状态转移的有限状态机示例代码。

STATE_MACHINE(){State cur_State=type_A;while(cur_State!=type_C){Package _pack=getNewPackage();switch(){case type_A:process_pkg_state_A(_pack);cur_State=type_B;break;case type_B:process_pkg_state_B(_pack);cur_State=type_C;break;}}
}

该状态机包含三种状态:type_A,type_B和type_C。其中,type_A是初始状态,type_C是结束状态。
状态机的当前状态记录在cur_State变量中,逻辑处理时,状态机先通过getNewPackage获取数据包,然后根据当前状态对数据进行处理,处理完后,状态机通过改变cur_State完成状态转移。
有限状态机一种逻辑单元内部的一种高效编程方法,在服务器编程中,服务器可以根据不同状态或者消息类型进行相应的处理逻辑,使得程序逻辑清晰易懂。

http处理流程

首先对http报文处理的流程进行简要介绍,然后具体介绍http类的定义和服务器接收http请求的具体过程。

http报文处理流程

  • 浏览器发出http连接请求,主线程创建http对象接收请求并将所有数据读入对应buffer,将改对象插入任务队列,工作线程从任务队列中取出一个任务进行处理。
  • 工作线程取出任务后,调用process_read函数,通过主、从状态机请求报文进行解析。
  • 解析完之后,跳转do_request函数生成响应报文,通过process_write写入buffer,返回给浏览器端。

http类

http_conn.h中,主要是http类的定义。

class http_conn{public://设置读取文件的名称m_real_file大小static const int FILENAME_LEN=200;//设置读缓冲区m_read_buf大小static const int READ_BUFFER_SIZE=2048;//设置写缓冲区m_write_buf大小static const int WRITE_BUFFER_SIZE=1024;//报文的请求方法,本项目只用到GET和POSTenum METHOD{GET=0,POST,HEAD,PUT,DELETE,TRACE,OPTIONS,CONNECT,PATH};//主状态机的状态enum CHECK_STATE{CHEACK_STATE_QEQUESTLINE=0,CHECK_STATE_HEADER,CHECK_STATE_CONTENT};//报文解析的结果enum HTTP_CODE{NO_REQUEST,GET_REQUEST,BAD_REQUEST,NO_RESOURCE,FORBIDDEN_REQUEST,FILE_REQUEST,INTERNAL_ERROR,CLOSED_CONNECTION};//从状态机的状态enum LINE_STATUS{LINE_OK=0,LINE_BAD,LINE_OPEN};public:http_conn(){}~http_conn(){}public://初始化套接字地址,函数内部会调用私有方法initvoid init(int sockfd,const sockaddr_in &addr);//关闭http连接void close_conn(bool real_close=true);void process();//读取浏览器端发来的全部数据bool read_once();//响应报文写入函数bool write();sockaddr_in *get_address(){return &m_address;}//同步线程初始化数据库读取表void initmysql_result();//CGI使用线程池初始化数据库表void initresultFile(connection_pool *connPool);private:void init();//从m_read_buf读取,并处理请求报文HTTP_CODE process_read();//向m_write_buf写入响应报文数据bool process_write(HTTP_CODE ret);//主状态机解析报文中的请求行数据HTTP_CODE parse_request_line(char* text);//主状态机解析报文中的请求头数据HTTP_CODE parse_headers(char* text);//主状态机解析报文中的请求内容HTTP_CODE parse_content(char* text);//生成响应报文HTTP_CODE do_request();//m_start_line是已经解析的字符//get_line用于将指针向后偏移,指向未处理的字符char* get_line(){return m_read_buf+m_start_line;};//从状态机读取一行,分析是请求报文的哪一部分LINE_STATUS parse_line();void unmap();//根据响应报文格式,生成对应8个部分,以下函数均由do_request调用bool add_reponse(const char* format,...);bool add_content(const char* content);bool add_status_line(int status,const char* title);bool add_headers(int content_length);bool add_content_type();bool add_content_length(int content_length);bool add_linger();bool add_blank_line();public:static int m_epollfd;static int m_user_count;MYSQL *mysql;private:int m_sockfd;sockaddr_in m_address;//存储读取的请求报文数据char m_read_buf[READ_BUFFER_SIZE];//缓冲区中m_read_buf中数据的最后一个字节的下一个位置int m_read_idx;//m_read_buf读取的位置m_checked_idxint m_checked_idx;//m_read_buf中已经解析的字符个数int m_start_line;//存储发出的响应报文数据char m_write_buf[WRITE_BUFFER_SIZE];//指示buffer中的长度int m_write_idx;//主状态机的状态CHECK_STATE m_check_state;//请求方法METHOD m_method;//以下为解析请求报文中对应的6个变量//存储读取文件的名称char m_real_file[FILENAME_LEN];char *m_url;char *m_version;char *m_host;int m_content_length;bool m_linger;char *m_file_address;//读取服务器上的文件地址struct stat m_file_stat;struct iovec m_iv[2];//io向量机制iovecint m_iv_count;int cgi;//是否启用的POSTchar *m_string;//存储请求头数据int bytes_to_send;//剩余发送字节数int bytes_have_send;//已发送字节数
};

在http请求接收部分,会涉及到init和read_once函数,但init仅仅是对私有成员变量进行初始化,不用过多讲解。
read_once读取浏览器端发送来的请求报文,直到无数据可读或对方关闭连接,读取到m_read_buffer中,并更新m_read_idx。

//循环读取客户数据,直到无数据可读或对方关闭连接
bool http_conn::read_once()
{if(m_read_idx>=READ_BUFFER_SIZE){return false;}int bytes_read=0;while(true){//从套接字接收数据,存储在m_read_buf缓冲区bytes_read=recv(m_sockfd,m_read_buf+m_read+idx,READ_BUFFER_SIZE-m_read_idx,0);if(bytes_read==-1){//非阻塞ET模式下,需要一次性将数据读完if(errno==EAGAIN||errno==EWOULDBLOCK){break;return false;}}else if(bytes_read==0){return false;}//修改m_read_idx的读取字节数1m_read_idx+=bytes_read;}return true;
}

epoll相关代码

项目中epoll相关代码部分包括非阻塞模式、内核事件表注册事件、删除事件、重置EPOLLONESHOT事件四种。

  • 非阻塞模式
//对文件描述符设置非阻塞模式
int setnoblocking(int fd){int old_option=fcntl(fd,F_GETFL);//获取文件fd的当前状态int new_option=old_option|O_NONBLOCK;fcntl(fd,F_SETFL,new_option);return old_option;
}
  • 内核事件表注册新事件,开启EPOLLONESHOT,针对客户端连接的描述符,listenfd不用开启
void addfd(int epollfd,int fd,bool one_shot)
{epoll_event event;event.data.fd=fd;#ifdef ETevent.events=EPOLLIN|EPOLLET|EPOLLRDHUP;
#endif#ifdef LTevent.events=EPOLLIN|EPOLLRDHUP;
#endifif(one_shot)event.events|=EPOLLONESHOT;epoll_ctl(epollfd,EPOLL_CTL_ADD,fd,&event);setnonblocking(fd);
}
  • 内核事件表删除事件
void removefd(int epollfd,int fd){epoll_ctl(epollfd,EPOLL_CTL_DEL,fd,0);close(fd);
}
  • 重置EPOLLONESHOT事件
void modfd(int epollfd,int fd,int ev){epoll_event event;event.data.fd=fd;#ifdef ETevent.events=ev|EPOLLET|EPOLLONESHOT|EPOLLRDHUP;
#endif#ifdef LTevent.events=ev|EPOLLONESHOT|EPOLLRDHUP;
#endifepoll_ctl(epollfd,EPOLL_CTL_MOD,fd,&event);
}

服务器接收http请求

浏览器端发出http连接请求,主线程创建http对象接收请求并所有数据读入对应buffer,将该对象插入任务队列,工作线程从任务队列取出一个任务进行处理。

//创建MAX_FD个http类对象
http_conn* user=new http_conn[MAX_FD];//创建内核事件表
epoll_event events[MAX_EVENT_NUMBER];
epollfd=epoll_create(5);
assert(epollfd!=-1);//将listenfd放在epoll数上
addfd(epollfd,listenfd,false);//将上述epollfd赋值给http类对象的m_epollfd属性
http_conn::m_epollfd=epollfd;while(!stop_server){//等待所监控文件描述符上有事件的产生int number=epoll_wait(epollfd,events,MAX_EVENT_NUMBER,-1);if(number<0&&errno!=EINTR){break;}//对所有就绪事件进行处理for(int i=0;i<number;i++){int sockfd=events[i].data.fd;//处理新到的客户连接if(sockfd==listenfd){struct sockaddr_in client_address;socklen_t client_addrlength=sizeof(client_address);
//LT水平触发
#ifdef LTint connfd=accept(listenfd,(struct sockaddr*)&client_address,&client_addrlength);if(connfd<0){continue;}if(http_conn::m_user_count>=MAX_FD){show_error(connfd,"Internal server busy");continue;}users[connfd].init(connfd,client_address);
#endif//ET非阻塞边缘触发
#ifdef ET//需要循环接收数据while(1){int connfd=accept(listenfd,(struct sockaddr *)&client_address,&client_addrlength);if(connfd<0){break;}if(http_conn::m_user_count>=MAX_FD){show_error(connfd,"Internal server busy");break;}users[connfd].init(connfd,client_address);}continue;
#endif}//处理异常事件else if(events[i].events&(EPOLLRDRDHUP|EPOLLHUP|EPOLLERR)){//服务器端关闭连接}//处理信号else if((sockfd==pipefd[0])&&(events[i].events&EPOLLIN)){}//处理客户连接上接收到的数据else if(events[i].events&EPOLLIN){//读入对应缓冲区if(users[sockfd].read_once()){//若监测到读事件,将该事件放入请求队列pool->append(users+sockfd);}else{//服务器关闭连接}}}
}

相关文章:

04 http连接处理(上)

基础知识&#xff1a;epoll、http报文格式、状态码和有限状态机 代码&#xff1a;对服务端处理http请求的全部流程进行简要介绍&#xff0c;然后结合代码对http类及请求接收进行详细分析。 epoll epoll_create函数 #include <sys/epoll.h> int epoll_create(int size)…...

c++(强生成关键字+可变参数模板+emplace)[26]

强制生成 不生成 在C中&#xff0c;可以通过一些方式来控制编译器是否生成某些特殊成员函数&#xff08;如默认构造函数、拷贝构造函数、拷贝赋值运算符、析构函数等&#xff09;。 默认生成&#xff1a;如果你没有显式地定义这些特殊成员函数&#xff0c;编译器会自动生成它们…...

Mysql 数据库开发及企业级应用

文章目录 1、Mysql 数据库开发及企业级应用1.1、为什么要使用数据库1.1.1、数据库概念&#xff08;Database&#xff09;1.1.2、为什么需要数据库 1.2、程序员为什么要学习数据库1.3、数据库的选择1.3.1、主流数据库简介1.3.2、使用 MySQL 的优势1.3.3、版本选择 1.4、Windows …...

【数据结构】_6.队列

目录 1.概念 2.队列的使用 3.队列模拟实现 4.循环队列 5.双端队列 6.OJ题 6.1 用队列实现栈 6.2 用栈实现队列 1.概念 &#xff08;1&#xff09;队列是只允许在一端进行插入数据操作&#xff0c;在另一端进行删除数据操作的特殊线性表&#xff1b; &#xff08;2&am…...

7 网络通信(上)

文章目录 网络通信概述ip地址ip的作用ip地址的分类私有ip 掩码和广播地址 linux 命令&#xff08;ping ifconfig&#xff09;查看或配置网卡信息&#xff1a;ifconfig(widows 用ipconfig)测试远程主机连通性&#xff1a;ping路由查看 端口端口是怎样分配的知名端口动态端口 查看…...

MFC图表控件high-speed-charting的使用

high-speed-charting是MFC上的开源图表库,Teechart的替代品。 high-speed-charting的下载地址 https://www.codeproject.com/Articles/14075/High-speed-Charting-Control 特性 High-speed drawing (when axis is fixed) which allows fast plotting of dataUnlimited number …...

Unity中常用方法

1.基础 //初始化引入 [RequireComponent(typeof(BoxCollider2D))] [RequireComponent(typeof(Rigidbody2D))]//游戏帧率设置 60帧Application.targetFrameRate 60;//获取物体对象 //获取到当前物体(根据名称&#xff0c;也可以根据路径)GameObject go GameObject.Find("…...

【监控系统】可视化工具Grafana简介及容器化部署实战

1.什么是Grafana 官网地址&#xff1a;https://grafana.com/ Grafana用Go语言开发的开源数据可视化工具&#xff0c;可以做数据监控和数据统计&#xff0c;带有告警功能。支持快速灵活的客户端图表&#xff0c;面板插件有许多不同方式的可视化指标和日志&#xff0c;官方库中…...

VUE之VueRouter页面跳转

参考资料&#xff1a; 参考视频 参考demo及视频资料 VUE之基本部署及VScode常用插件 VUE之基本组成和使用 VUE之Bootstrap和Element-UI的使用 VUE之axios使用&#xff0c;跨域问题&#xff0c;拦截器添加Token Vue Router官网 Vue Router说明&#xff1a; 说明&#xf…...

【188】Java8利用AVL树实现Map

AVL树又被叫做平衡二叉搜索树、平衡二叉树。AVL是其发明者的首字母缩写。 这篇文章中&#xff0c;AVLTreeMap 类集成了 java.util.Map 接口&#xff0c;并利用 AVL 树结构实现了 Map 接口的所有方法。本文还给出了测试代码。 为什么要发明AVL树&#xff1f; 当我按照从小到大…...

[SQL挖掘机] - 右连接: right join

介绍: 右连接是一种多表连接方式&#xff0c;它以右侧的表为基础&#xff0c;并返回满足连接条件的匹配行以及右侧表中的所有行&#xff0c;即使左侧的表中没有匹配的行。右连接将右表的每一行与左表进行比较&#xff0c;并根据连接条件返回结果集。其实, 左连接和右连接原理一…...

bug篇之基于docker安装nacos(2.1.1)使用dubbo连接不上的问题

说明&#xff1a;首先我的nacos安装是2.1.1版本&#xff0c;请注意版本问题。另外启动时用dubbo的话必须先启动服务提供者再启动服务使用者&#xff0c;否则会报错&#xff0c;同时也必须开放三个端口&#xff1a;8848&#xff0c;9848&#xff0c;9849 java.lang.IllegalStat…...

【Python入门系列】第二十一篇:Python物联网和传感器应用

文章目录 前言一、Python在物联网和传感器应用中的优势二、连接传感器和设备三、读取传感器数据四、示例代码和讲解五、进一步处理和分析传感器数据六、更多应用示例1、温湿度监测系统2、智能家居系统 - 灯光控制 总结 前言 物联网和传感器在现代科技中扮演着重要的角色。物联…...

Python爬虫的urlib的学习(学习于b站尚硅谷)

目录 一、页面结构的介绍  1.学习目标  2.为什么要了解页面&#xff08;html&#xff09;  3. html中的标签&#xff08;仅介绍了含表格、无序列表、有序列表、超链接&#xff09;  4.本节的演示 二、Urllib  1.什么是互联网爬虫&#xff1f;  2.爬虫核心  3.爬虫…...

【MongoDB】--MongoDB聚合Aggregation

目录 一、前言二、聚合管道操作2.1、实际案例1(1)、案例--根据学生no&#xff0c;找到对应班级名称(2)、案例--这个班级有哪些学生和哪些老师在任课 2.2、实际案例2(1)、案例--主表和关联表都有条件限制&#xff0c;且分页返回 一、前言 聚合操作组值来自多个文档&#xff0c;…...

Hadoop学习指南:探索大数据时代的重要组成——Hadoop概述

前言 在当今大数据时代&#xff0c;处理海量数据成为了一项关键任务。Hadoop作为一种开源的分布式计算框架&#xff0c;为大规模数据处理和存储提供了强大的解决方案。本文将介绍Hadoop的组成和其在大数据处理中的重要作用&#xff0c;让我们一同踏上学习Hadoop的旅程。 Hado…...

Java实现简单小画板

Java制作简单画板&#xff0c;包括两个类&#xff0c;一个主要画板类Drawpad&#xff0c;一个画板监听器DrawListener类。 1、Drawpad类&#xff0c;包括画板&#xff0c;画板功能设计&#xff0c;保存图片等 ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 2…...

B078-项目实战--支付模块 领养订单支付流程

目录 支付模块需求分析表设计支付单表支付宝账号信息表-商家账号微信支付账号信息表-商家账号银行账号表-商家资金账号表支付流水表 流程分析支付基础模块继承加密算法沙箱环境准备支付宝支付-流程分析根据demo封装工具类导入依赖AlipayConfigAlipayInfoAlipayUtil 内网穿透 领…...

[css]margin-top不起作用问题(外边距合并)

在初学css时&#xff0c;会遇到突然间margin-top不起作用的情况。如下面&#xff1a; 情况一&#xff1a; 代码&#xff1a; <html> <head><style type"text/css"> * {margin:0;padding:0;border:0; }#outer {width:300px;height:300px;backgroun…...

Vue2基础八、插槽

零、文章目录 Vue2基础八、插槽 1、插槽 &#xff08;1&#xff09;默认插槽 作用&#xff1a;让组件内部的一些 结构 支持 自定义需求: 将需要多次显示的对话框, 封装成一个组件问题&#xff1a;组件的内容部分&#xff0c;不希望写死&#xff0c;希望能使用的时候自定义。…...

自然语言处理从入门到应用——LangChain:提示(Prompts)-[提示模板:连接到特征存储]

分类目录&#xff1a;《自然语言处理从入门到应用》总目录 特征存储是传统机器学习中的一个概念&#xff0c;它确保输入模型的数据是最新和相关的。在考虑将LLM应用程序投入生产时&#xff0c;这个概念非常重要。为了个性化LLM应用程序&#xff0c;我们可能希望将LLM与特定用户…...

jenkins自定义邮件发送人姓名

jenkins发送邮件的时候发送人姓名默认的&#xff0c;如果要自定义发件人姓名&#xff0c;只需要修改如下信息即可&#xff1a; 系统管理-system-Jenkins Location下的系统管理员邮件地址 格式为&#xff1a;自定义姓名<邮件地址>...

SolidWorks二次开发---简单的连接solidworks

创建一个.net Framework的应用&#xff0c;正常4.0以上就可以了。 打开nuget包管理 在里面搜索paine 在版中选择对应的solidworks年份开头的&#xff0c;进行安装。 安装完之后 : 同时选中下面两个dll,把嵌入操作类型改为false 然后在按钮的单击事件中输入: Connect.Crea…...

docker 安装 active Mq

在安装完Docker的机器上&#xff0c;安装activeMQ。 拉取镜像&#xff1a; docker pull webcenter/activemq 查看镜像&#xff1a; docker images Docker运行ActiveMQ镜像 docker run --name activemq -d -p 8161:8161 -p 61616:61616 --privilegedtrue --restartalways …...

【Linux】TCP协议

​&#x1f320; 作者&#xff1a;阿亮joy. &#x1f386;专栏&#xff1a;《学会Linux》 &#x1f387; 座右铭&#xff1a;每个优秀的人都有一段沉默的时光&#xff0c;那段时光是付出了很多努力却得不到结果的日子&#xff0c;我们把它叫做扎根 目录 &#x1f449;TCP协议&…...

DevOps系列文章之 自动化测试大全(单测和集成测试)

自动化测试业界主流工具 核心目标&#xff1a; 主要是功能测试和覆盖率测试 业界常用主流工具 GoogleTest GoogleTest是一个跨平台的(Liunx、Mac OS X、Windows 、Cygwin 、Windows CE and Symbian ) C单元测试框架&#xff0c;由google公司发布&#xff0c;为在不同平台上为编…...

Android启动速度优化

本节主要内容&#xff1a;了解APP启动流程、启动状态、查看启动时间、CPU Profile定位启动耗时代码、StrictMode严苛模式检测不合理写法、解决启动黑白屏问题。 一、APP启动流程 ①用户点击桌面App图标&#xff0c;Launcher进程采用Binder IPC向system_server进程发起startAc…...

linux 日志 系统安全日志 web日志

web日志 LINUX日志系统之WEB日志&#xff08;一&#xff09;_dracut.log_麻子来了的博客-CSDN博客 系统安全日志 Linux系统安全日志详解_sinolover的博客-CSDN博客 wtmp和utmp文件都是二进制文件&#xff0c;需使用who、w、users、last和ac来操作这两个文件。 who /var/lo…...

SpringBoot 整合 MongoDB 连接 阿里云MongoDB

注&#xff1a;spring-boot-starter-data-mongodb 2.7.5&#xff1b;jdk 1.8 阿里云MongoDB是副本集实例的 在网上查找了一番&#xff0c;大多数都是教连接本地mongodb或者linux上的mongodb 阿里云上有java版连接教程&#xff0c;但它不是SpringBoot方法配置的&#xff0c;是手…...

Debeizum 增量快照

在Debeizum1.6版本发布之后&#xff0c;成功推出了Incremental Snapshot&#xff08;增量快照&#xff09;的功能&#xff0c;同时取代了原有的实验性的Parallel Snapshot&#xff08;并行快照&#xff09;。在本篇博客中&#xff0c;我将介绍全新快照方式的原理&#xff0c;以…...