DELPHI盒子
!实时搜索: 盒子论坛 | 注册用户 | 修改信息 | 退出
检举帖 | 全文检索 | 关闭广告 | 捐赠
技术论坛
 用户名
 密  码
自动登陆(30天有效)
忘了密码
≡技术区≡
DELPHI技术
lazarus/fpc/Free Pascal
移动应用开发
Web应用开发
数据库专区
报表专区
网络通讯
开源项目
论坛精华贴
≡发布区≡
发布代码
发布控件
文档资料
经典工具
≡事务区≡
网站意见
盒子之家
招聘应聘
信息交换
论坛信息
最新加入: szliyu112358
今日帖子: 60
在线用户: 21
导航: 论坛 -> DELPHI技术 斑竹:liumazi,sephil  
作者:
男 chonghai (DBlue) ★☆☆☆☆ -
盒子活跃会员
2016/10/18 8:49:23
标题:
一个用Pascal写的HTTP框架 浏览:2935
加入我的收藏
楼主: https://www.habarisoft.com/daraja_framework.html

看介绍很不错,有空测试看看。
有兴趣的朋友也可以关注下。
----------------------------------------------
喜欢Delphi,关注Delphi,愿和广大爱好者交朋友。
作者:
男 akay (akay) ★☆☆☆☆ -
普通会员
2016/10/18 9:26:30
1楼: 基于indy的,但indy本身就问题多多。
里面贴出来的,用vs来写pascal
----------------------------------------------
-
作者:
男 cuit_xiong (熊猫) ★☆☆☆☆ -
普通会员
2016/10/18 11:19:37
2楼: 对的基于indy,是收费的
----------------------------------------------
-
作者:
男 yuzhenguo0 (金远见) ▲▲▲▲▲ -
普通会员
2016/10/18 14:18:03
3楼: vs?
----------------------------------------------
学DELPHI http://www.studydelphi.com
作者:
男 nevergrief (孤独骑士) ★☆☆☆☆ -
盒子活跃会员
2016/10/18 16:13:43
4楼: indy不要紧的。unigui也是基于Indy,没有任何问题
----------------------------------------------
只有偏执狂才能生存!
作者:
男 138soft (138soft) ★☆☆☆☆ -
盒子活跃会员
2016/10/18 16:58:36
5楼: 真正的WEB服务器是不会用Indy写的。因为它是基于每连接每线程的。

其实真正的服务器需要下很多功夫,无法快速开发的。
比如说,字符串处理。玩服务器基本上就是玩内存。举个例子:

var
 str:AnsiString;
begin
 str:='HTTP 1.1/200 OK'#$D#$A;
 str:=str+xxxxxxx;
 str:=str+yyyyyyy;
 ......
end;

编译器实际上上怎么做的?第一行代码:先根据字符长度,为str分配17字节空间(这里不讨论头部计数器和锁占用的空间)。第二行代码,假设xxxxxx的长度为3,那么再申请一个20字节的空间,将原来17字节的内容拷贝过去,再在后面接上3个字节的内容,然后释放原来的17个字节。第三行同理。内存会变成怎么样?

[ 17个字节的空洞][ 20字节的新内容]..........

这个时候,如果你需要分配一个18字节的内存,只能从[ 20字节的新内容]后面申请,因为内存块必须是连续的。换句话说,前面那个17字节的内存就废了。除非分配的是小于等于17字节的。

随着运行的时间越来越长,类似的空洞会越来越多。最后,如果你是32位应用程序,那么有可能面临很多错误(比如说:GetMem失败,对象创建失败)。


MFC的CString实质上原理类似。

服务器开发跟桌面应用是两码事,因为桌面应用程序,从你启动到结束,一般就运行几个小时,但服务器是24小时*365运行的,需要注意的事情海了去。很多时候,一些好像不要紧的细节,累加起来,就有质的区别。

服务器开发,不是有一个不错的网络库就OK的。网络仅是负责数据的收发,你如何快速处理收到的数据呢(比如说,使用传统锁来生产者消费者队列,或者双队列,或者原子队列,或者真正逻辑上完全无锁队列)?如果避免更多的内核和应用层切换?启动多少个线程刚好合适?选用什么加密算法?等等等等。不要小看效率,假如你的服务器长连接峰值是10万,一个加密算法提示了10毫秒,10毫秒乘以10万就是16分钟,8核服务器在理想状态下,最后那个登录的可怜虫也要多等待2分钟。仅仅追求连接数是毫无意义的,如果你的机器性能够强大,如果你使用完成端口,如果客户端仅是连接而不用做其它事情,一个最蹩脚的程序员写的也能同时支持百万级别的连接。但这个是操作系统的功劳,跟你的程序关系不大。仅连接不做事情的程序也没什么用处。

当然,桌面程序开发人员是不用关心这些的。如果仅是开发http server,我强烈建议直接调用操作系统的http.sys,这个也是IIS的本质。除了避免内核和应用层的切换,还可以避免很多问题。你自己实现一个其实是不可能比这个更好---你用的操作系统都是人家的,你会比他更了解系统么?
----------------------------------------------
是你上错了车,还是我下错了站?
作者:
男 doorkey (DoorKey) ★☆☆☆☆ -
盒子活跃会员
2016/10/18 17:59:03
6楼: 非常同意楼上的,我也是基于http.sys来开发的,真的是非常稳定。
----------------------------------------------
QQ: 9717005 我的Blog:http://www.cnblogs.com/anydelphi/
作者:
男 wr960204 (武稀松) ★☆☆☆☆ -
盒子活跃会员
2016/10/18 22:15:29
7楼: Delphi已经集成了FastMM,这个内存管理器对大中小块内存做了分别的优化。
例如小块内存,不是17,18字节这样的。而是xxK对齐(例如4K,不一定是)。
中块xxK字节对齐,大块xxK对齐。
这样,内存回收后小块的还可以给以后的小块重用。
尽量避免出现内存碎片导致不连续和浪费。

不过一切通用的算法和代码都不如专用的效率高,如果这样想把某种业务做到及至,那么需要针对这种业务做专用的处理。

HTTP.SYS避免了频繁的一次次的内核和应用层间的切换和数据传输,效率是非常高的。
另外Windows的IOCP模型比Linux的epoll效率还是要高很多的。

所以如果在Windows平台上基本没有什么Web服务器效率和通用性能高过IIS了。
----------------------------------------------
武稀松http://www.raysoftware.cn
作者:
男 138soft (138soft) ★☆☆☆☆ -
盒子活跃会员
2016/10/18 23:31:01
8楼: FastMM是Delphi7后才集成的,Delphi7及之前的版本并不自带。另外,它的内存释放有时候有些问题,就是会发生释放并不成功的情况。老外有个修改版本丢在git上面。但是内存问题,除了碎片,还有很多其它讲究的地方,都是开发服务器需要注意的。

IOCP才是真正的异步模型,真正的异步。epoll并不是。我以前在Windows下实现过epoll模型,无非是使用纤程之类来实现完全的自己调度。如果一定要比较,Windows的IOCP模型的确是要比Linux的epoll效率高很多。

HTTP.SYS除了避免切换,也涉及到内存问题---驱动里面关键代码都是使用物理内存的,避免了内存不足虚拟内存跟磁盘IO之间的切换。这个切换在严重的情况下是卡电脑的。
----------------------------------------------
是你上错了车,还是我下错了站?
作者:
男 138soft (138soft) ★☆☆☆☆ -
盒子活跃会员
2016/10/18 23:37:28
9楼: 另外,其实很多年前老外放在torry.net上面的一个基于IOCP的http模型都比indy的强大,里面也使用了很多lock free的技巧。当然,lock free其实只是原子锁,并非真正的无锁。真正的无锁比原子的效率至少高7倍以上。

类似wr960204说的,如果一个东西要做到极致,基本上不存在通用的可能。但极致本身是值得追求的,一些技巧也是可以通用的。比如说:相同一个函数,不同的写法,查看CPU反汇编,生成的代码行(你可以通俗看成是执行所需要花的CPU时间片)也是不一样。又比如说:如何合理利用CPU的cache提高效率(一个简单的例子是TRTLCriticalSection类型后面多定义一个padding数组)。等等等等。
----------------------------------------------
是你上错了车,还是我下错了站?
作者:
男 chonghai (DBlue) ★☆☆☆☆ -
盒子活跃会员
2016/10/19 0:55:29
8楼: 使用场景不一样,如果在不需要那么高效的情况下或者是单机使用还是可以一试的。
----------------------------------------------
喜欢Delphi,关注Delphi,愿和广大爱好者交朋友。
作者:
男 mricy (Icy) ▲▲▲▲△ -
普通会员
2016/10/19 11:46:20
10楼: 过去看了一下 不想下载这东西...
----------------------------------------------
哦哟喂,看过来: http://zelig.cn
作者:
男 drroc (mvcxe) ★☆☆☆☆ -
盒子活跃会员
2016/10/19 15:05:21
11楼: 还好啊,开源的,为什么喷人家呢
----------------------------------------------
MVCXE中国首个DELPHI MVC WEB框架:https://www.mvcxe.com/
作者:
男 bahamut8348 (leonna) ★☆☆☆☆ -
普通会员
2016/10/19 20:42:11
12楼: 这不如去扩展nginx。。。
----------------------------------------------
--
作者:
男 hawke2e (hawke2e) ★☆☆☆☆ -
普通会员
2016/10/21 12:24:32
13楼: 我是针对5楼说的。
技术人员要避免完美主义。所谓大牛写的超棒服务器程序,或许一个普通的方案再加多1、2台服务器备用就解决了。什么真正服务器就不能用Indy,什么事情都要考虑适用性,成本和效率。
对于你说的第一个问题,根本解决方案是从架构入手,你想找个非常好的内存管理,很难,倒不如用双进程,原进程到一定程度自动结束释放,启动备用进程服务。这样成本更低,稳定性更高。
对于第二个,如果真要考虑这么细,还要考虑主板的性能和驱动程序的性能,一台服务器当性能长期满载是会容易出问题。

软件跟硬件的最大差别就在于汽车一个零件装得不好,有可能车毁人忙;软件相对要求要宽松很多很多。所以,不是写桌面程序的水平比写服务器的水平要低,只是服务器某些性能指标上要求相对高,桌面程序一样要下很多功夫,比服务器程序都要多。
----------------------------------------------
软件是什么,相信很多人都说不清。
作者:
男 hawke2e (hawke2e) ★☆☆☆☆ -
普通会员
2016/10/21 12:42:16
14楼: 写高性能的程序。
首先要看瓶颈在哪里,是CPU不够快,主板吞吐效率不高,硬盘 还是网络,还是某个加密程序还是有点慢。但你针对某配置服务器去写,迁移就有成本,所以没必要考虑得这么细。把主要的解决了,通用性强适当牺牲性能。况且也没必要搞得服务器满载。
----------------------------------------------
软件是什么,相信很多人都说不清。
作者:
男 138soft (138soft) ★☆☆☆☆ -
盒子活跃会员
2016/10/22 4:04:22
15楼:     我觉得你并未理解我的意思。
    Indy是基于一个连接一个线程的,真的不适合于真正的服务器,否则也不会出现IOCP这种解决C10K、C100K问题的方案。默认情况下,32位进程大概启动2010个线程就会报存储空间不足,你看看真正的连接能支持多少个?更加不用说那么多线程切换带来的时间开销。
    追求性能并不意味着不通用。如果针对某配置服务器去写,是没有必要的。所谓追求性能,很多时候是指选择适合的方案。比如说,加密算法,拿非对称算法来说,在相同的强度下,ECC算法就比RSA运算时间更加少。这个运算时间不可能仅针对具体的机器配置而不同。再比如说,生产者消费者队列(例如,生产者网络收发数据放到队列A,消费者处理队列从队列A获取、处理并删除),真正无锁的算法比lock-free处理速度高7倍左右),这些都是通用的,不是说换个机器就会反过来。
    我有十年的客户端开发经验,“不是写桌面程序的水平比写服务器的水平要低,”,不是指低,比如说,你桌面程序点击按钮,调用一个函数,里面即使Sleep(125)也没什么影响。我的意思是,你要抛弃这种单机的想法,时刻抱着这个函数或算法是可能同时N个并发的,这个跟水平无关,但跟认识有关。另外一个意思是,要写一个真正好的服务器程序,需要对操作系统、线程、切换、内存等等都很了解,然后针对需求有所取舍,让程序函数之间很协调。而桌面程序,比如说一个多媒体播放器,你并不需要了解那么多,你可能有一些多媒体编码解码常识就好,也不需要考虑连续24*365长时间运行有可能带来的问题。
    另外,任何成熟的服务器都会有性能监测。例如腾讯的服务器,CPU利用率一旦达到50%,监控程序就会报警。而追求性能的意义在于,比如说相同的机器,都是占用35%的CPU,但性能好的可能可以同时处理10万个连接和数据逻辑,而性能不好的,可能只有几千。

    所以你的理解是:如果追求高性能,那么就要牺牲稳定性、通用性之类。这是并未真正理解我上面说的。下图是我以前写的IOCP的DEMO,我不相信Indy可以在相同开销下达到如此的网络利用率。
此帖子包含附件:
PNG 图像
大小:72.3K
----------------------------------------------
是你上错了车,还是我下错了站?
作者:
男 138soft (138soft) ★☆☆☆☆ -
盒子活跃会员
2016/10/22 4:22:42
16楼:   例子中的ECC算法也不可能不通用。
此帖子包含附件:
PNG 图像
大小:38.2K
----------------------------------------------
是你上错了车,还是我下错了站?
作者:
男 138soft (138soft) ★☆☆☆☆ -
盒子活跃会员
2016/10/22 4:22:57
17楼: .
此帖子包含附件:
PNG 图像
大小:19.7K
----------------------------------------------
是你上错了车,还是我下错了站?
作者:
男 138soft (138soft) ★☆☆☆☆ -
盒子活跃会员
2016/10/22 15:54:09
18楼: 既然说到这个份上了,顺便说说Indy这个控件吧。早年我也用过很多次Indy,对它的流程也比较熟悉了。Indy的优点实际上是做客户端的时候,控件内部使用阻塞模式,而调用者使用起来不阻塞。比如说,它的连接函数(下面说的均是Delphi7年代的Indy9版本,后面的没有再看过,所以不一定对应的起来)是有连接超时参数的,而阻塞Socket是很难控制超时的,它是怎么干的呢?

1、Connect函数放到一个线程里面:

constructor TConnectThread.Create(ASocket: TSocket; var sAddr: TSockAddr);
begin
  m_Sock := ASocket;
  m_SockAddr := sAddr;
  m_bConnected := False;
  inherited Create(False);
end;

destructor TConnectThread.Destroy;
begin
  inherited Destroy;
end;

procedure TConnectThread.Execute;
begin
  m_bConnected := WinSock2.Connect(m_Sock, m_SockAddr, Sizeof(TSockAddrIn)) = 0;
  Terminate;
end;

2、对外的连接函数,类似这样:

  if nTimeOut = -1 then
  begin
    //Result:=connect(s,SockAddr,sizeof(TSockAddr))=0;
    MyConnectThread := TConnectThread.Create(ASocket, PSockAddr(@SockAddrIn)^);
    try
      while not MyConnectThread.Terminated do
      begin
        Sleep(1);
        Application.ProcessMessages;
      end;
      Result := MyConnectThread.m_bConnected;
    finally
      MyConnectThread.Free;
    end;
  end
  else
  begin
    MyConnectThread := TConnectThread.Create(ASocket, PSockAddr(@SockAddrIn)^);

    try
      nSleepTime := 125;

      while nTimeout > nSleepTime do
      begin
        Sleep(nSleepTime);
        nTimeout := nTimeout - nSleepTime;
        Application.ProcessMessages;
        if MyConnectThread.Terminated then
        begin
          nTimeout := 0;
          Break;
        end;
      end;

      Sleep(nTimeout);

      if MyConnectThread.Terminated then Result := MyConnectThread.m_bConnected
      else
      begin
        MyConnectThread.Terminate;
        closesocket(ASocket);
        ASocket := INVALID_SOCKET;
        MyConnectThread.WaitFor;
      end;
    finally
      MyConnectThread.Free;
    end;
  end;



也就是说,connect仍然是阻塞的,但是因为放到一个新线程里面,所以不会阻塞调用者的界面UI。比如说,设置的连接超时是3000毫秒,这个函数就是切小到125毫秒一次来连续循环Sleep+Application.ProceMessages响应界面。当超时时间到达而连接线程仍然阻塞未返回,就CloseSocket让连接线程的connect马上返回。
 

接收过程,它是中间有一个TMemorystream缓冲成员,首先从里面读取,如果里面数据不足够,才真正调用recv。总而言之,它一切就是靠线程来保证不影响界面。但实质上这个TMemorystream,就不细说了,自己测试吧,一切以测试结果为准。凡事不要想当然。就好像有人觉得在多线程里面通过SendMessage之类来实现“无锁”,这种就是想当然。如果实际写个测试程序,可能还不如临界区快,因为在线程内调用这种API,操作系统会在底层帮你上锁了。切记,不要想当然。

另外,Indy一切是函数形式的。拿接收数据来说,有两种函数原型:

function Recv:Boolean;//函数方式
procedure Recv;//过程方式

Indy都是基于过程方式,如果函数失败,就Raise触发一个异常。所以使用的时候,总是:
 try
 xxxxxx
except
end;
我们先不说异常、中断带来的开销,光是这个调用就够别扭的。
----------------------------------------------
是你上错了车,还是我下错了站?
作者:
男 lsz100 (lsz) ★☆☆☆☆ -
盒子活跃会员
2016/10/27 9:36:35
19楼: 是的 服务端开发和桌面开发是两个不同思路 前者要考虑性能 后者考虑的客户操作
----------------------------------------------
我为人人为我
作者:
男 gaoyong_gy (gaoyong_gy) ★☆☆☆☆ -
盒子活跃会员
2016/10/31 11:38:22
20楼: 都是牛人啊
----------------------------------------------
Delphi 的移动程序开发,是您不可再错失的机遇:http://blog.163.com/you888@188/blog/static/6723961920169319529515/
作者:
男 hdcopy (hdcopy) ★☆☆☆☆ -
普通会员
2016/10/31 14:24:28
21楼: 都对啊,高连接高并发的server不能用indy,对啊。
平时最多只有几十上百在线,并发更少的可以用indy,也没问题啊。

接收数据需要即时处理,尽快返回,整个过程只有XX毫秒,
尽力优化接收数据算法,省下10毫秒,那就是性能提升xx%。善哉。

接收数据到返回,整个过程需要XX秒,
尽力优化接收数据算法,省下10毫秒,那就是性能提升0.xx%。愚。
----------------------------------------------
-
作者:
男 dinkysoft (天地弦) ★☆☆☆☆ -
盒子活跃会员
2016/10/31 15:09:03
22楼: DIOCP的http服务,性能也不错的。
DIOCP-RPC和DSS中间件都是基于DIOCP HTTP协议的。
----------------------------------------------
DIOCP官方社区|MyBean官方社区http://www.diocp.org/
作者:
男 aizjcn (还情) ★☆☆☆☆ -
普通会员
2016/11/14 8:57:05
23楼: 好鸡毛热闹啊,惊涛还是骇浪啊,热闹忍不住来一发!一把年纪了还不减当年。
----------------------------------------------
-
信息
登陆以后才能回复
Copyright © 2CCC.Com 盒子论坛 v3.0.1 版权所有 页面执行125毫秒 RSS