Sphinx 客户端API编写过程中遇到的问题
Sphinx是什么阿蒙在这里就不解释了,直接进正题吧。
官方提供的API接口实在是太简陋了,完全是从PHP迁移到C#的,对于不熟悉Sphinx的开发人员来说,颇费一番功夫才能明白如何去调用各个方法,而且在网络连接上未使用连接池,这对于工作在Nginx或lighttpd这类单进程单线程的Web Server下的PHP来说,的确是比较好的,但对于工作在IIS下的.NET程序就不那么令人愉悦了。
在这个前提下,于是决定自己动手开发一个Sphinx的客户端类库。
Sphinx协议是很简单的,但是其中也隐含着一些陷阱,例如今天在测试接口时,发现的一些问题:
1、按时间(DateTime)或整型(Int32)过滤结果时,始终报错:“invalid or truncated request”,在网上搜索半天无果,只有自己动眼看服务端源码(伸手党不好做:-()。
在源码中发现了,分析范围过滤的方式的相关代码:
代码
switch ( tFilter.m_eType )
{
case SPH_FILTER_RANGE:
tFilter.m_uMinValue = ( iVer>=0x114 ) ? tReq.GetUint64() : tReq.GetDword ();
tFilter.m_uMaxValue = ( iVer>=0x114 ) ? tReq.GetUint64() : tReq.GetDword ();
break;
case SPH_FILTER_FLOATRANGE:
tFilter.m_fMinValue = tReq.GetFloat ();
tFilter.m_fMaxValue = tReq.GetFloat ();
break;
case SPH_FILTER_VALUES:
{
bool bRes = ( iVer>=0x114 )
? tReq.GetQwords ( tFilter.m_dValues, g_iMaxFilterValues, "invalid attribute set length %d (should be in 0..%d range)" )
: tReq.GetDwords ( tFilter.m_dValues, g_iMaxFilterValues, "invalid attribute set length %d (should be in 0..%d range)" );
if ( !bRes )
return false;
}
break;
default:
tReq.SendErrorReply ( "unknown filter type (type-id=%d)", tFilter.m_eType );
return false;
}
{
case SPH_FILTER_RANGE:
tFilter.m_uMinValue = ( iVer>=0x114 ) ? tReq.GetUint64() : tReq.GetDword ();
tFilter.m_uMaxValue = ( iVer>=0x114 ) ? tReq.GetUint64() : tReq.GetDword ();
break;
case SPH_FILTER_FLOATRANGE:
tFilter.m_fMinValue = tReq.GetFloat ();
tFilter.m_fMaxValue = tReq.GetFloat ();
break;
case SPH_FILTER_VALUES:
{
bool bRes = ( iVer>=0x114 )
? tReq.GetQwords ( tFilter.m_dValues, g_iMaxFilterValues, "invalid attribute set length %d (should be in 0..%d range)" )
: tReq.GetDwords ( tFilter.m_dValues, g_iMaxFilterValues, "invalid attribute set length %d (should be in 0..%d range)" );
if ( !bRes )
return false;
}
break;
default:
tReq.SendErrorReply ( "unknown filter type (type-id=%d)", tFilter.m_eType );
return false;
}
原来Sphinx的服务端在客户端代码版本高于0x114时,是以8字节长整型来读取的最大最小值,问题找到了,将所有进行范围过滤的值在发送到服务端之前都转换为Int64,再写入流中,OK,问题解决。
2、用Socket不要用TcpClient - -
在做压力测试时,Socket通信的性能明显好于TcpClient,而且TcpClient在压力测试过程中,经常报错,目前尚未去查找原因,不过用Socket的话,工作得非常好。
目前该类库还在测试中,可能还会遇到其他问题,慢慢补充。