Commit 36f24527 by ziyue

http cookie减少互斥锁,优化性能

parent c510f376
......@@ -11,13 +11,13 @@
#ifndef SRC_HTTP_COOKIEMANAGER_H
#define SRC_HTTP_COOKIEMANAGER_H
#include <memory>
#include <unordered_map>
#include "Common/Parser.h"
#include "Network/Socket.h"
#include "Util/TimeTicker.h"
#include "Util/mini.h"
#include "Util/util.h"
#include "Util/TimeTicker.h"
#include "Network/Socket.h"
#include "Common/Parser.h"
#include <memory>
#include <unordered_map>
#define COOKIE_DEFAULT_LIFE (7 * 24 * 60 * 60)
......@@ -28,9 +28,9 @@ class HttpCookieManager;
/**
* cookie对象,用于保存cookie的一些相关属性
*/
class HttpServerCookie : public toolkit::AnyStorage , public toolkit::noncopyable{
class HttpServerCookie : public toolkit::noncopyable {
public:
typedef std::shared_ptr<HttpServerCookie> Ptr;
using Ptr = std::shared_ptr<HttpServerCookie>;
/**
* 构建cookie
* @param manager cookie管理者对象
......@@ -40,12 +40,10 @@ public:
* @param max_elapsed 最大过期时间,单位秒
*/
HttpServerCookie(const std::shared_ptr<HttpCookieManager> &manager,
const std::string &cookie_name,
const std::string &uid,
const std::string &cookie,
uint64_t max_elapsed);
~HttpServerCookie() ;
HttpServerCookie(
const std::shared_ptr<HttpCookieManager> &manager, const std::string &cookie_name, const std::string &uid,
const std::string &cookie, uint64_t max_elapsed);
~HttpServerCookie();
/**
* 获取uid
......@@ -65,13 +63,13 @@ public:
* 获取cookie随机字符串
* @return cookie随机字符串
*/
const std::string& getCookie() const;
const std::string &getCookie() const;
/**
* 获取该cookie名
* @return
*/
const std::string& getCookieName() const;
const std::string &getCookieName() const;
/**
* 更新该cookie的过期时间,可以让此cookie不失效
......@@ -85,26 +83,35 @@ public:
bool isExpired();
/**
* 获取区域锁
* @return
* 设置附加数据
*/
std::shared_ptr<std::lock_guard<std::recursive_mutex> > getLock();
void setAttach(std::shared_ptr<void> attach);
/*
* 获取附加数据
*/
template <class T>
const T& getAttach() const {
return *static_cast<const T *>(_attach.get());
}
private:
std::string cookieExpireTime() const ;
std::string cookieExpireTime() const;
private:
std::string _uid;
std::string _cookie_name;
std::string _cookie_uuid;
uint64_t _max_elapsed;
toolkit::Ticker _ticker;
std::recursive_mutex _mtx;
std::shared_ptr<void> _attach;
std::weak_ptr<HttpCookieManager> _manager;
};
/**
* cookie随机字符串生成器
*/
class RandStrGeneator{
class RandStrGeneator {
public:
RandStrGeneator() = default;
~RandStrGeneator() = default;
......@@ -120,8 +127,10 @@ public:
* @param str 随机字符串
*/
void release(const std::string &str);
private:
std::string obtain_l();
private:
//碰撞库
std::unordered_set<std::string> _obtained;
......@@ -135,8 +144,8 @@ private:
*/
class HttpCookieManager : public std::enable_shared_from_this<HttpCookieManager> {
public:
typedef std::shared_ptr<HttpCookieManager> Ptr;
friend class HttpServerCookie;
using Ptr = std::shared_ptr<HttpCookieManager>;
~HttpCookieManager();
/**
......@@ -152,7 +161,10 @@ public:
* @param max_elapsed 该cookie过期时间,单位秒
* @return cookie对象
*/
HttpServerCookie::Ptr addCookie(const std::string &cookie_name,const std::string &uid, uint64_t max_elapsed = COOKIE_DEFAULT_LIFE,int max_client = 1);
HttpServerCookie::Ptr addCookie(
const std::string &cookie_name, const std::string &uid, uint64_t max_elapsed = COOKIE_DEFAULT_LIFE,
std::shared_ptr<void> attach = nullptr,
int max_client = 1);
/**
* 根据cookie随机字符串查找cookie对象
......@@ -160,7 +172,7 @@ public:
* @param cookie cookie随机字符串
* @return cookie对象,可以为nullptr
*/
HttpServerCookie::Ptr getCookie(const std::string &cookie_name,const std::string &cookie);
HttpServerCookie::Ptr getCookie(const std::string &cookie_name, const std::string &cookie);
/**
* 从http头中获取cookie对象
......@@ -168,7 +180,7 @@ public:
* @param http_header http头
* @return cookie对象
*/
HttpServerCookie::Ptr getCookie(const std::string &cookie_name,const StrCaseMap &http_header);
HttpServerCookie::Ptr getCookie(const std::string &cookie_name, const StrCaseMap &http_header);
/**
* 根据uid获取cookie
......@@ -176,7 +188,7 @@ public:
* @param uid 用户id
* @return cookie对象
*/
HttpServerCookie::Ptr getCookieByUid(const std::string &cookie_name,const std::string &uid);
HttpServerCookie::Ptr getCookieByUid(const std::string &cookie_name, const std::string &uid);
/**
* 删除cookie,用户登出时使用
......@@ -184,8 +196,10 @@ public:
* @return
*/
bool delCookie(const HttpServerCookie::Ptr &cookie);
private:
HttpCookieManager();
void onManager();
/**
* 构造cookie对象时触发,目的是记录某账号下多个cookie
......@@ -193,7 +207,7 @@ private:
* @param uid 用户id
* @param cookie cookie随机字符串
*/
void onAddCookie(const std::string &cookie_name,const std::string &uid,const std::string &cookie);
void onAddCookie(const std::string &cookie_name, const std::string &uid, const std::string &cookie);
/**
* 析构cookie对象时触发
......@@ -201,7 +215,7 @@ private:
* @param uid 用户id
* @param cookie cookie随机字符串
*/
void onDelCookie(const std::string &cookie_name,const std::string &uid,const std::string &cookie);
void onDelCookie(const std::string &cookie_name, const std::string &uid, const std::string &cookie);
/**
* 获取某用户名下最先登录时的cookie,目的是实现某用户下最多登录若干个设备
......@@ -210,7 +224,7 @@ private:
* @param max_client 最多登录的设备个数
* @return 最早的cookie随机字符串
*/
std::string getOldestCookie(const std::string &cookie_name,const std::string &uid, int max_client = 1);
std::string getOldestCookie(const std::string &cookie_name, const std::string &uid, int max_client = 1);
/**
* 删除cookie
......@@ -218,16 +232,21 @@ private:
* @param cookie cookie随机字符串
* @return 成功true
*/
bool delCookie(const std::string &cookie_name,const std::string &cookie);
bool delCookie(const std::string &cookie_name, const std::string &cookie);
private:
std::unordered_map<std::string/*cookie_name*/,std::unordered_map<std::string/*cookie*/,HttpServerCookie::Ptr/*cookie_data*/> >_map_cookie;
std::unordered_map<std::string/*cookie_name*/,std::unordered_map<std::string/*uid*/,std::map<uint64_t/*cookie time stamp*/,std::string/*cookie*/> > >_map_uid_to_cookie;
std::unordered_map<
std::string /*cookie_name*/, std::unordered_map<std::string /*cookie*/, HttpServerCookie::Ptr /*cookie_data*/>>
_map_cookie;
std::unordered_map<
std::string /*cookie_name*/,
std::unordered_map<std::string /*uid*/, std::map<uint64_t /*cookie time stamp*/, std::string /*cookie*/>>>
_map_uid_to_cookie;
std::recursive_mutex _mtx_cookie;
toolkit::Timer::Ptr _timer;
RandStrGeneator _geneator;
};
}//namespace mediakit
} // namespace mediakit
#endif //SRC_HTTP_COOKIEMANAGER_H
#endif // SRC_HTTP_COOKIEMANAGER_H
......@@ -34,9 +34,6 @@ static const string kHlsSuffix = "/hls.m3u8";
class HttpCookieAttachment {
public:
HttpCookieAttachment() {};
~HttpCookieAttachment() {};
public:
//cookie生效作用域,本cookie只对该目录下的文件生效
string _path;
//上次鉴权失败信息,为空则上次鉴权成功
......@@ -265,13 +262,12 @@ static void canAccessPath(TcpSession &sender, const Parser &parser, const MediaI
if (cookie) {
//找到了cookie,对cookie上锁先
auto lck = cookie->getLock();
auto attachment = (*cookie)[kCookieName].get<HttpCookieAttachment>();
if (path.find(attachment._path) == 0) {
auto& attach = cookie->getAttach<HttpCookieAttachment>();
if (path.find(attach._path) == 0) {
//上次cookie是限定本目录
if (attachment._err_msg.empty()) {
if (attach._err_msg.empty()) {
//上次鉴权成功
if (attachment._is_hls) {
if (attach._is_hls) {
//如果播放的是hls,那么刷新hls的cookie(获取ts文件也会刷新)
cookie->updateTime();
cookie_from_header = false;
......@@ -282,7 +278,7 @@ static void canAccessPath(TcpSession &sender, const Parser &parser, const MediaI
//上次鉴权失败,但是如果url参数发生变更,那么也重新鉴权下
if (parser.Params().empty() || parser.Params() == cookie->getUid()) {
//url参数未变,或者本来就没有url参数,那么判断本次请求为重复请求,无访问权限
callback(attachment._err_msg, cookie_from_header ? nullptr : cookie);
callback(attach._err_msg, cookie_from_header ? nullptr : cookie);
return;
}
}
......@@ -301,9 +297,9 @@ static void canAccessPath(TcpSession &sender, const Parser &parser, const MediaI
//该用户从来未获取过cookie,这个时候我们广播是否允许该用户访问该http目录
HttpSession::HttpAccessPathInvoker accessPathInvoker = [callback, uid, path, is_dir, is_hls, mediaInfo, info]
(const string &errMsg, const string &cookie_path_in, int cookieLifeSecond) {
(const string &err_msg, const string &cookie_path_in, int life_second) {
HttpServerCookie::Ptr cookie;
if (cookieLifeSecond) {
if (life_second) {
//本次鉴权设置了有效期,我们把鉴权结果缓存在cookie中
string cookie_path = cookie_path_in;
if (cookie_path.empty()) {
......@@ -311,26 +307,22 @@ static void canAccessPath(TcpSession &sender, const Parser &parser, const MediaI
cookie_path = is_dir ? path : path.substr(0, path.rfind("/") + 1);
}
cookie = HttpCookieManager::Instance().addCookie(kCookieName, uid, cookieLifeSecond);
//对cookie上锁
auto lck = cookie->getLock();
HttpCookieAttachment attachment;
auto attach = std::make_shared<HttpCookieAttachment>();
//记录用户能访问的路径
attachment._path = cookie_path;
attach->_path = cookie_path;
//记录能否访问
attachment._err_msg = errMsg;
attach->_err_msg = err_msg;
//记录访问的是否为hls
attachment._is_hls = is_hls;
attach->_is_hls = is_hls;
if (is_hls) {
//hls相关信息
attachment._hls_data = std::make_shared<HlsCookieData>(mediaInfo, info);
//hls未查找MediaSource
attachment._have_find_media_source = false;
// hls相关信息
attach->_hls_data = std::make_shared<HlsCookieData>(mediaInfo, info);
// hls未查找MediaSource
attach->_have_find_media_source = false;
}
(*cookie)[kCookieName].set<HttpCookieAttachment>(std::move(attachment));
callback(errMsg, cookie);
callback(err_msg, HttpCookieManager::Instance().addCookie(kCookieName, uid, life_second, attach));
} else {
callback(errMsg, nullptr);
callback(err_msg, nullptr);
}
};
......@@ -401,8 +393,7 @@ static void accessFile(TcpSession &sender, const Parser &parser, const MediaInfo
//文件鉴权失败
StrCaseMap headerOut;
if (cookie) {
auto lck = cookie->getLock();
headerOut["Set-Cookie"] = cookie->getCookie((*cookie)[kCookieName].get<HttpCookieAttachment>()._path);
headerOut["Set-Cookie"] = cookie->getAttach<HttpCookieAttachment>()._path;
}
cb(401, "text/html", headerOut, std::make_shared<HttpStringBody>(errMsg));
return;
......@@ -411,15 +402,13 @@ static void accessFile(TcpSession &sender, const Parser &parser, const MediaInfo
auto response_file = [file_exist, is_hls](const HttpServerCookie::Ptr &cookie, const HttpFileManager::invoker &cb, const string &strFile, const Parser &parser) {
StrCaseMap httpHeader;
if (cookie) {
auto lck = cookie->getLock();
httpHeader["Set-Cookie"] = cookie->getCookie((*cookie)[kCookieName].get<HttpCookieAttachment>()._path);
httpHeader["Set-Cookie"] = cookie->getAttach<HttpCookieAttachment>()._path;
}
HttpSession::HttpResponseInvoker invoker = [&](int code, const StrCaseMap &headerOut, const HttpBody::Ptr &body) {
if (cookie && file_exist) {
auto lck = cookie->getLock();
auto is_hls = (*cookie)[kCookieName].get<HttpCookieAttachment>()._is_hls;
if (is_hls) {
(*cookie)[kCookieName].get<HttpCookieAttachment>()._hls_data->addByteUsage(body->remainSize());
auto& attach = cookie->getAttach<HttpCookieAttachment>();
if (attach._is_hls) {
attach._hls_data->addByteUsage(body->remainSize());
}
}
cb(code, HttpFileManager::getContentType(strFile.data()), headerOut, body);
......@@ -436,10 +425,10 @@ static void accessFile(TcpSession &sender, const Parser &parser, const MediaInfo
//是hls直播,判断HLS直播流是否已经注册
bool have_find_media_src = false;
if (cookie) {
auto lck = cookie->getLock();
have_find_media_src = (*cookie)[kCookieName].get<HttpCookieAttachment>()._have_find_media_source;
auto& attach = cookie->getAttach<HttpCookieAttachment>();
have_find_media_src = attach._have_find_media_source;
if (!have_find_media_src) {
(*cookie)[kCookieName].get<HttpCookieAttachment>()._have_find_media_source = true;
const_cast<HttpCookieAttachment &>(attach)._have_find_media_source = true;
}
}
if (have_find_media_src) {
......@@ -450,9 +439,8 @@ static void accessFile(TcpSession &sender, const Parser &parser, const MediaInfo
//hls文件不存在,我们等待其生成并延后回复
MediaSource::findAsync(mediaInfo, strongSession, [response_file, cookie, cb, strFile, parser](const MediaSource::Ptr &src) {
if (cookie) {
auto lck = cookie->getLock();
//尝试添加HlsMediaSource的观看人数(HLS是按需生成的,这样可以触发HLS文件的生成)
(*cookie)[kCookieName].get<HttpCookieAttachment>()._hls_data->addByteUsage(0);
cookie->getAttach<HttpCookieAttachment>()._hls_data->addByteUsage(0);
}
if (src && File::is_file(strFile.data())) {
//流和m3u8文件都存在,那么直接返回文件
......@@ -531,7 +519,7 @@ void HttpFileManager::onAccessPath(TcpSession &sender, Parser &parser, const Htt
}
StrCaseMap headerOut;
if (cookie) {
headerOut["Set-Cookie"] = cookie->getCookie((*cookie)[kCookieName].get<HttpCookieAttachment>()._path);
headerOut["Set-Cookie"] = cookie->getAttach<HttpCookieAttachment>()._path;
}
cb(errMsg.empty() ? 200 : 401, "text/html", headerOut, std::make_shared<HttpStringBody>(strMenu));
});
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论