Linux平台下C++实现的新闻推荐系统

时间:2024-04-08 07:10:52

基本描述

新闻推荐系统能够支持用户登录,注册,检索新闻,并根据登录用户的浏览记录进行新闻推荐。支持360浏览器,Chrome浏览器,IE浏览器,安卓手机浏览器,苹果手机浏览器的访问。部署在云服务器上,以守护进程的方式运行。

主要分为5个模块:

l  爬虫模块

使用python的Scrapy框架爬取新浪新闻网页存储到MySQL数据库中,爬取的过程中使用结巴分词对标题进行关键词过滤,便于后期的推荐和检索。

l  后台服务器模块

使用EPOLL边缘触发,线程池,多线程异步日志。使用简单的HTML,支持get和post。

l  数据库模块

使用MySQL数据库管理新闻信息,用户身份信息,用户访问记录。

l  搜索模块

使用MySQL5.7新增的全文索引,并且通过c++多线程调用python程序,对检索结果使用BM25算法进行相关度排序。

l  推荐模块

根据用户的访问记录,使用结巴分词的关键词抽取模块对关键词进行排序,得到5个权重最高的关键词,在数据库中检索,实现推荐。

系统框图

Linux平台下C++实现的新闻推荐系统


遇到的主要问题:

1、 后台服务器的搭建,这是最主要的问题。

目前是采用的方案是主线程接受连接,对数据进行读,读完之后将请求的任务分给线程池中的线程去做,线程池中的线程处理完之后,让主线程去写。这种方案对主线程的负担比较大,不适合处理高并发的请求。改进方案是采用经典的One Thread Per Loop方案,主线程只负责连接的建立,然后将这个连接以RoundRobin的方式分摊给线程池的线程,此后这个线程就全权接管这个连接。

一开始我就使用的性能比较高的EPOLL加边缘触发的方式。但是由于对EPOLL和非阻塞读写的理解没有到位,程序出现了很多bug。印象最深的是我采用条件变量搭建的线程池,主线程接受连接之后让线程池中的线程来处理,但是我只注册了EPOLLIN事件,所以导致在对方断开连接的时候也会触发一个可读事件,当线程池中的线程去对他进行读的时候就会出错。还有我一开始对EAGAIN或者EWOULDBLOCK这个错误没有正确的认识,其实忽略它就可以了。

还有accept必须非阻塞,在ET模式下必须用while循环去接受accept连接。

2、 程序的调试问题

网络编程的程序错误一般为运行期的错误。并且我们的系统有一部分是调用的python程序,程序运行到python代码时如果有错,能给我们的出错信息很少。这给调试带来了很大的麻烦,必须让服务器运行起来,让用户去访问,看看哪里出错了。由于是在云服务器上搭建的http服务器,终端退出之后需要http服务器还能运行,所以需要设置守护进程,并且启用日志系统记录系统的关键信息。总的来说,调试的方式有:

全局变量errno

Assert断言

终端输出

打日志

程序崩溃查看core dump文件

使用gdb调试

3、 c++多线程调用python的过程中出现的GIL极大地影响程序的性能

一开始只能搜索一次,搜索完之后搜索第二次就一直卡住。后来多方求证,终于找到问题的所在,就是在多线程环境下,python程序执行需要有GIL锁,用完之后必须释放,否则会造成死锁的情况。

4、建立全文索引之后极大地影响数据库的插入性能,导致爬虫效率低下。(一开始我还以为是我的ip被网站封了,直到我用慢查询日志抓出每条插入语句都是慢查询。)删掉索引又是不行的,因为我们需要索引来检索,来保证爬虫的时候存入数据库中的新闻是没有重复的。目前准备采用的方案是爬虫程序存储到另一个数据库中,这个数据库是没有索引的,服务器访问的数据库是有索引的,爬虫的时候先检索服务器访问的数据库,如果数据库中没有记录,就存到没有索引的那个数据库中。一段时间之后删除服务器访问的那个数据库上的索引,将另一个数据库中的数据导入之后再建立索引。基本的思路如图:

Linux平台下C++实现的新闻推荐系统