5

Qt, WebService, 负载均衡

 2 years ago
source link: http://antkillerfarm.github.io/technology/2015/06/02/qt.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Qt, WebService, 负载均衡

2015-06-02

Qt主循环

这篇文章有个大概的比较和说明:

http://blog.chinaunix.net/uid-20754930-id-1877623.html

GUI主循环设计及其在MiniGUI, GTK, QT的实现

以下是我针对Qt5代码(2015.4)的一个研究。

QApplication::exec

QGuiApplication::exec

QCoreApplication::exec

QEventLoop::exec

QEventLoop::processEvents

QEventDispatcher::processEvents

再以下就和具体的平台相关了。

Windows平台:

QEventDispatcherWin32::processEvents

它的实现主要是GetMessage+WaitForMultipleObjects,如上文中对MiniGUI的主循环所述。

Unix平台:

QEventDispatcherUNIX::processEvents

QEventDispatcherUNIXPrivate::doSelect

这个函数主要使用select系统调用来监听事件源。

Android平台:

QAndroidEventDispatcher::processEvents

QUnixEventDispatcherQPA::processEvents

QEventDispatcherUNIX::processEvents

以下和Unix平台相同。

Qt多线程中connect的使用

近日在研究OpenGL多线程处理时,偶然看到了如下代码:

http://download.csdn.net/detail/zhoukuanbin/7669187

没有CSDN账号的读者,也可以在这里下载:

https://github.com/antkillerfarm/antkillerfarm_crazy/tree/master/Qt/MyGlTest

粗看代码,发现并无特殊的OpenGL处理,理论上应该无法达到一个线程处理渲染,另一个线程处理贴图的目标。但实际编译运行代码,又确实可用。因此这里面一定有什么原因。

void ThreadGl::run()
{
    connect(this, SIGNAL(SigCopy()), this, SLOT(Copy()));
    printf("ID 0:%x\n", currentThreadId());
    while(1)
    {
        if(!m_bEndFlag)
        {
            break;
        }

        usleep(16000);
        emit SigCopy();
    }

    qDebug("Copy End\n");
}

void ThreadGl::Copy()
{
    m_glWidgets -> OnTimeOut(m_pImage, m_Formal, m_pthId);
}

这段代码引起了我的注意。粗一看,connect函数连接的SIGNAL和SLOT都属于同一个对象。而connect函数的第5个参数(这是个有默认值的可省略参数)的默认值为Qt::AutoConnection。

这是Qt官方对Qt::AutoConnection的解释:

  • If the receiver lives in the thread that emits the signal, Qt::DirectConnection is used. Otherwise, Qt::QueuedConnection is used. The connection type is determined when the signal is emitted.

按照字面上的意思,既然SIGNAL和SLOT都属于同一个对象,那么这里的Qt::AutoConnection就等同于Qt::DirectConnection。而Qt::DirectConnection与直接调用SLOT函数是一个效果。

于是这里将emit SigCopy();替换为Copy();,结果程序运行出错。

再试一下,将connect函数的第5个参数设为Qt::DirectConnection,同样有问题。

而如果将之设为Qt::QueuedConnection的话,程序运行一切正常。

综上,Qt在这里的处理,显然认为SIGNAL和SLOT属于不同的线程。

那么判断的依据是什么呢?

这里有必要对emit SigCopy();emit背后的戏法做一个剖析。

众所周知,emit并非C++关键字,而属于Qt扩展的一部分。Qt为了处理这些扩展,引入了moc工具作为预处理工具。

而moc处理之后,emit SigCopy();就变成了QMetaObject::activate

QMetaObject::activate中使用以下代码,判定信号接收者的线程是否和信号发送者的一致。

const bool receiverInSameThread = currentThreadId == receiver->d_func()->threadData->threadId;

于是问题转化为receiver->d_func()->threadData是怎么来的呢?

答案在QObject::QObject中:

d->threadData = (parent && !parent->thread()) ? parent->d_func()->threadData : QThreadData::current();

从这里可以看出所谓信号接收者的线程,实际上是接收者对象创建时所处的线程。

回到原来的问题。ThreadGl虽然是Qt的线程对象,但它本身却是在主线程中创建的,所以以它为接收者,实际上就是以主线程为接收者。

显然这个例子代码并没有真正实现OpenGL多线程处理,所有的OpenGL操作实际上都是在主线程完成的。

https://blog.csdn.net/feiyangqingyun/

一个Qt的blog

PyQt是一个python语言的Qt封装。除此之外,还有一个叫PySide的库也是干这个的。

它们的区别在于:PyQt是Riverbank Computing开发的,历史早,功能强。PySide是Qt官方提供的,然而很久以来都比不过前者。。。

https://mp.weixin.qq.com/s/jNa4JTefasFDWoGJDBL6-Q

PyQt编写GUI界面

https://mp.weixin.qq.com/s/sR1R2DRA2XASx9LJExasfA

15个开源示例手把手带你用PyQt做小型桌面应用

WebService

WebService经过近二十年的发展,已经有非常多的框架了。知名的有:Axis1、Axis2、Xfire、CXF、JWS等。

其中的JWS在JDK 1.6之后被集成到JDK中,成为了我学习的首选。

JWS包含了JAX-WS、JAX-RS、JAXB、JAXR、SAAJ、StAX等组件。这里主要涉及的是JAX-WS。

http://www.blogjava.net/zjhiphop/archive/2009/04/29/webservice.html

java调用webservice的各种方法总结

http://blog.csdn.net/lifetragedy/article/details/7205832

5天学会jaxws-webservice编程

以上两篇是中文blog。

http://java.globinch.com/enterprise-java/web-services/jax-ws/java-jax-ws-tutorial-develop-web-services-clients-consumers/

这个教程虽然是英文的,但质量超过前两篇。且该网站还有其他相关文章,质量也颇高。

本文相关的demo参见:

https://github.com/him-bhar/jax-ws

这个demo包括jaxws-demo、jaxws-demo-client-stubs和jaxws-demo-client三个模块。

使用这个demo会有若干问题,也可直接采用本人修改之后的代码:

https://github.com/antkillerfarm/antkillerfarm_crazy/tree/master/java/jax-ws

JAX-WS 2.0有两种开发过程:自顶向下自底向上。自顶向下方式指通过一个WSDL文件来创建Web Service,自底向上是从Java类出发创建Web Service。

demo选用Server端通过Java Class生成webservice,而客户端通过wsdl生成Java调用类的做法。

这种方法的优点在于:

1.服务端开发基于Java,基本不需要对WSDL有过多研究,上手简单。

2.客户端通过wsdl生成Java调用类,可以很方便的导入第三方WebService,同样无需对WSDL有过多研究。

综上,这实际上是个由服务端驱动的开发模型

jaxws-demo的结构

jaxws-demo包含了两个WebService例子分别是rpc_type和document_type。

这两种类型实际上指的是SOAP Binding的类型。两者的区别参见:

http://java.globinch.com/enterprise-java/web-services/soap-binding-document-rpc-style-web-services-difference/

吐槽一下,虽然这只是个基本的问题,然而中文blog中竟然没有令人满意的文章。
这些文章的毛病在于:
1.对Java和JWS过于细节,而忽视了交互报文。SOAP Binding类型主要是个通讯协议问题,而不是Java或者JWS的问题。
2.没有比较交互报文,就来笼统的谈各自的优缺点的,都是耍流氓。

从上文的交互报文可以看出,document_type虽然更复杂,但也更灵活。从直观来看,前者只有wsdl一个文件,而后者有wsdl和xsd两个文件。

jaxws-demo的部署

jaxws-demo编译之后,除了生成相应的.class之外,还会生成对应的wsdl和xsd文件。

通常的做法是将这些文件一起部署到诸如Tomcat之类的Web容器中。

但JDK也提供了更简易的做法,使用javax.xml.ws.Endpoint类的publish方法,将WebService绑定到特定的URI上。

这里我们将com.himanshu.poc.jaxws.service.deploy.EndpointPublisherDocument设为主类,并执行程序。

在浏览器上输入:

http://localhost:9999/ws/hellodocument?wsdl

正常情况下会返回一个wsdl文件。

jaxws-demo-client-stubs

JDK中,有两个和WebService相关的工具:

JAXWS为我们提供了两个工具:

wsgen。主要用于Server端通过Java类编译成Webservice及相关的wsdl文件。

wsimport。主要用于Client端(调用端)通过wsdl编译出调用Server端的Java文件。

jaxws-demo中,调用wsgen生成的wsdl和xsd文件,在这里被wsimport编译成客户端的桩代码。

由于我使用的JDK是JDK 1.8,因此会遇到如下问题:

由于 accessExternalSchema属性设置的限制而不允许 'file' 访问, 因此无法读取方案文档'xjc.xsd'。

解决方法:

<plugin>
    <groupId>org.jvnet.jax-ws-commons</groupId>
    <artifactId>jaxws-maven-plugin</artifactId>
    <version>2.3</version>
    <configuration>
        <!-- Needed with JAXP 1.5 -->
        <vmArgs>
            <vmArg>-Djavax.xml.accessExternalSchema=all</vmArg>
        </vmArgs>
    </configuration>
</plugin>

这个问题是由于JDK 1.8以后相关权限变得更加严格所导致的。

https://my.oschina.net/fuckmylife0/blog/325432

jaxws-demo-client

jaxws-demo-client就是具体的客户端实现了,可以看出相比于上一步的桩代码,这里的代码文件,数量上要少得多。

正向代理,“它代理的是客户端,代客户端发出请求”。

反向代理,“它代理的是服务端,代服务端接收请求”。

http://blog.csdn.net/gzh0222/article/details/8540604

lvs、haproxy、nginx负载均衡的比较分析

https://mp.weixin.qq.com/s/SO1ZLSPaRkk8WwUl9u-JPA

仅需这一篇,吃透“负载均衡”妥妥的

https://mp.weixin.qq.com/s/3KZ99d94yqRDxEByn7nGWg

QPS比Nginx提升60%,阿里Tengine负载均衡算法揭秘

https://mp.weixin.qq.com/s/XsyXkaOIJ3m8sdCt8Pl5Ig

计算密集型服务的负载均衡策略

https://mp.weixin.qq.com/s/SmpUPJRK0TMdA0rkb_Q6VQ

什么是集群?什么又是负载均衡?

https://mp.weixin.qq.com/s/sCGI3XPga5gTZF0iskJlMA

全网最详尽的负载均衡原理图解

https://mp.weixin.qq.com/s/o5lTN4IpHmZqLUKoJsSyKw

爱奇艺TFServing负载均衡问题研究及改进实践

Nginx

https://mp.weixin.qq.com/s/31DGDYpDHcYg-4qM4OczxA

深入浅出Nginx

https://mp.weixin.qq.com/s/h9sXZc4Y62f4KOSVXAB1Pg

Nginx基本功能极速入门

https://www.cnblogs.com/wcwnina/p/8728391.html

Nginx相关介绍

https://mp.weixin.qq.com/s/aCAuJQEB2pmL92OTEb_4Xg

Nginx为什么这么快?

https://mp.weixin.qq.com/s/3GSuB1tLe-G5hZPUiAXuVA

Nginx,为什么依旧这么“香”?

https://blog.csdn.net/yujing1314/article/details/107000737

搞懂Nginx一篇文章就够了

https://mp.weixin.qq.com/s/-8Ka8nMYpH7cipzfm36utw

写给小白的Nginx文章

https://mp.weixin.qq.com/s/gd59U50tlJPa4B4avXRG1Q

Nginx架构浅析

https://mp.weixin.qq.com/s/eUindWNZiCv_tSLQeYfmLg

Nginx常用配置清单

https://mp.weixin.qq.com/s/LmtHTOVOvdcnMBuxv7a9_A

Nginx最全操作总结


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK