1 使用缓存:为了提高响应速度和处理效率,可以使用缓存来存储常用的数据和页面内容。可以使用内存缓存、分布式缓存等不同的缓存策略来减少网络访问和数据库查询次数,从而提升应用程序的性能。
2 使用负载均衡:可以使用负载均衡器将请求分配到多台服务器上,在扩展应用程序的同时确保高可用性和稳定性。可以使用硬件负载均衡器或软件负载均衡器来实现,例如,Nginx、HAProxy 等。
3 使用 CDN:可以使用 CDN(内容分发网络)来加速静态资源的传输和加载,减少请求对服务器的压力。可以将静态资源(如、样式表、脚本等)缓存在 CDN 上,并通过 CDN 调用来提供服务。
4 预渲染静态页面:在 Nextjs 中,可以使用“静态生成”或“服务器端渲染”来生成 HTML 页面。如果应用程序的内容和数据不经常变化,则可以通过预渲染静态页面来减轻服务器的负担,加快页面的加载速度。
5 使用缓存策略控制头文件:>
0Redis主从架构的问题
1哨兵服务介绍
2架构图
3主从服务搭建
4配置哨兵服务
5启动哨兵服务
6验证哨兵服务
对于Redis的主从架构而言,无法实现 master 和 slave 角色的自动切换, 即当 master 出现 redis 服务异常、主机断电、磁盘损坏等问题导致 master 无法使用,而 redis 高可用无法实现自故障转移(将 slave 提升为 master),需要手动改环境配置才能切换到 slave redis 服务器。另外无法横向扩展 Redis 服务的并行写入性能, 当单台 Redis 服务器性能无法满足业务写入需求的时候就必须需要一种方式解决此问题。
1master和slave角色的无缝切换,让业务无感知从而不影响业务使用
2可以横向动态扩展Redis服务器, 从而实现多台服务器并行写入以实现更高并发的目的。
Sentinel进程是用于监控redis集群中Master主服务器工作的状态,在Master主服务器发生故障的时候,可以实现Master和Slave服务器的切换,保证系统的高可用,其已经被集成在 redis26+的版本中,Redis的哨兵模式到了28版本之后就稳定了下来。一般在生产环境也建议使用Redis28以后版本。哨兵(Sentinel)是一个分布式系统,你可以在一个架构中运行多个哨兵(sentinel) 进程,这些进程使用流言协议(gossipprotocols)来接收关于Master主服务器是否下线的信息,并使用投票协议(Agreement Protocols)来决定是否执行自动故障迁移,以及选择哪个 Slave 作为新的 Master。每个哨兵(Sentinel)进程会向其它哨兵(Sentinel)、Master、Slave定时发送消息,以确认对方是否”活”着,如果发现对方在指定配置时间(可配置的)内未得到回应,则暂时认为对方已掉线,也就是所谓的”主观认为宕机” ,英文名称:Subjective Down,简称SDOWN。有主观宕机,肯定就有客观宕机。当“哨兵群”中的多数 Sentinel 进程在对 Master 主服务器做出 SDOWN 的判断,并且通过SENTINEL is-master-down-by-addr 命令互相交流之后,得出的Master Server下线判断,这种方式就是“客观宕机”,英文名称是: Objectively Down, 简称 ODOWN。通过一定的 vote 算法,从剩下的 slave 从服务器节点中,选一台提升为 Master 服务器节点,然后自动修改相关配置,并开启故障转移(failover)。Sentinel 机制可以解决 master 和 slave 角色的切换问题。
安装
修改配置文件
启动服务
192168177139
192168177140
其他地方配置和主服务器一致
启动服务
查看主从状态
MASTER
SLAVE1
SLAVE2
MASTER
SLAVE1
SLAVE2
主服务器
SLAVE1:升级为主服务器
SLAVE2:主服务器变为node10
主服务器
从服务器
socket接受线程:C语言为了高并发所以选择了epoll。当程序启动的时候(g_net_updatec文件中main函数,会启动一个thread见函数create_accept_task)这个thread就处理一件事情,只管接收客户端的连接,当有连接进来的时候 通过epoll_ctl函数,把socket fd 加入到epoll里面去,epoll设置监听事件EPOLLIN | EPOLLET; 主要是监听的是加入到epoll中的socket是否可读(因为我的需求是客户端连上了server就会马上向server发送一份数据的)。其它的部分在主线程中处理。
主线程:是一个无线循环,epoll_wait 函数相当于把客户端的连接从epoll中拿出来(因为我们监听的是EPOLLIN | EPOLLET)说明这个时候客户端有数据发送过来)。再通过recv_buffer_from_fd 函数把客户端发送过来的数据读出来。然后其他的一切就抛给线程池去处理。
线程池:(代码中我会在池里面创建15个线程) 双向链表。加入线程就是在链表后面加一个链表项,链表的前面会一个一个被拿出来处理。主要是malloc 函数free函数,sem_wait函数sem_post的处理(sem_wait 会阻塞当值大于0是会减一,sem_post是值加一)。typedef void (FUNC)(void arg, int index);是我们自定义的线程的逻辑处理部分,arg是参数,index是第几个线程处理(我们隐形的给每个线程都标了号),例如代码中的respons_stb_info,更加具体可以看看代码里面是怎么实现的。聪明的你也可以改掉这块的内容改成动态线程池,当某个时刻的处理比较多的时候能够动态的增加线程,而不像我代码里面的是固定的。
数据库连接池:按照我的需求在处理客户端请求数据的时候是要访问数据库的。就是一下子创建出一堆的数据连接。要访问数据库的时候先去数据库连接池中找出空闲的连接,具体可以看下代码。使用的时候可以参考下database_processc文件(代码中数据库连接池和线程池中的个数是一样的)。这里我想说下get_db_connect_from_pool这个函数,我用了随机数,我是为了不想每次都从0开始去判断哪个连接没有用到。为了数据库连接池中的每个链接都能等概率的使用到,具体的还是可以看下代码的实现。
要求很高啊,我这有段代码,你看看。package comtest;
import javaioBufferedReader;
import javaioBufferedWriter;
import javaioInputStreamReader;
import javaioOutputStreamWriter;
import javanetSocket;
public class Test>Nginx会按需同时运行多个进程:一个主进程(master)和几个工作进程(worker),配置了缓存时还会有缓存加载器进程(cache loader)和缓存管理器进程(cache manager)等。Nginx主要通过“共享内存”的机制实现进程间通信。主进程以root用户身份运行,而worker、cache loader和cache manager均应以非特权用户身份运行。
在工作方式上,Nginx分为单工作进程和多工作进程两种模式。在单工作进程模式下,除主进程外,还有一个工作进程,工作进程是单线程的;在多工作进程模式下,每个工作进程包含多个线程。Nginx默认为单工作进程模式。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)