• [集群&DWS] GaussDB(DWS)集群通信系列三:集群通信常用视图
    视图是检测数据库运行状态的重要工具和手段,GaussDB(DWS)集群通信常用视图主要包含pg_stat_activity、pg_comm_client、pgxc_thread_wait_status、pgxc_comm_recv_stream、pgxc_comm_send_stream、pgxc_comm_status,其在数据库通信问题定位中发挥了重要作用。1、pg_stat_activity该视图显示和当前用户查询相关的信息。主要用于查看当前用户执行查询的状态和查询对应的query_id,2、pg_comm_client_info该视图存储单个节点客户端连接信息(DN上查询该视图显示CN连接DN的信息)。3、pgxc_thread_wait_status该视图显示由执行语句产生的线程之间层次调用关系,以及各个线程的阻塞等待状态。该视图常用来定位数据库通信过程中的hang问题,主要用于定位的信息包括:Ø  query_id:查询IDØ  tlevel:线程层级,对于集群通信而言,Postgres thread线程为0级线程,其根据任务会fork其他子线程,集群通信线程间的关系具体可以参考http://3ms.huawei.com/hi/group/2191/wiki_5275953.html?for_statistic_from=all_group_wikiØ  wait_status:等待线程的当前等待状态,none表示没有等待,其他状态可参考产品文档。4、pgxc_comm_recv_stream该视图显示DN上所有的通信库接收流的状态。5、pgxc_comm_send_stream该视图显示DN上所有的通信库发送流的状态。6、pgxc_comm_status该视图显示所有DN的通信库状态。包含:节点名称、节点通信库发送/接收速率、cmailbox的buffer大小、libcomm/libpq进程通信内存大小、线程实时/最高实时使用率、当前使用的逻辑连接总数。通信视图的关联关系使用和hang问题定位示例查询单个的视图往往信息有限而作用不大,视图最大的妙用在于利用各信息的关联关系,要求使用者能够联系多方信息,进行问题定位和状态监测,这一点无疑比较困难,因此整理和介绍视图的关联关系对于视图使用者极为重要,此处仅通过hang问题的示例,和视图部分信息的关联关系使用,介绍这种运用思想和方法,通信视图完整的关联关系将在后续GaussDB(DWS) 集群通信系列中给出。可以看出,定位hang问题的一般步骤为:1、  根据pg_stat_activity视图查看当前查询的query_id。2、  根据pgxc_thread_wait_status中相应的query_id查询对应的线程状态,是等待什么导致的hang3、  根据wait_status的信息,查看对端信息,包含线程层级,节点等4、  查看对端具体的线程信息pg_thread_wait_status,如果是DN可查对应的连接流信息,可以利用netstat,线程号查看对端信息,分析对端的行为。通信hang问题典型案例:原文链接:https://bbs.huaweicloud.com/blogs/209112【推荐阅读】【最新活动汇总】DWS活动火热进行中,互动好礼送不停(持续更新中)  HOT  【博文汇总】GaussDB(DWS)博文汇总1,欢迎大家交流探讨~(持续更新中)【维护宝典汇总】GaussDB(DWS)维护宝典汇总贴1,欢迎大家交流探讨(持续更新中)【项目实践汇总】GaussDB(DWS)项目实践汇总贴,欢迎大家交流探讨(持续更新中)【DevRun直播汇总】GaussDB(DWS)黑科技直播汇总,欢迎大家交流学习(持续更新中)【培训视频汇总】GaussDB(DWS) 培训视频汇总,欢迎大家交流学习(持续更新中)扫码关注我哦,我在这里↓↓↓
  • [SQL] PB级数仓GaussDB(DWS)性能黑科技之并行计算技术解密
    【摘要】 随着硬件系统的越来越好,数据库运行的CPU、磁盘、内存资源都日渐增大,SQL语句的串行执行由于不能充分利用资源,已经不能满足日益发展的需要。为此,GaussDB(DWS)开发了并行计算技术,在语句执行时可以充分利用硬件资源进行并行加速,提高执行的吞吐率。本文将详细介绍GaussDB(DWS)并行计算技术的原理,以及其在performance信息中的展示,帮助各位开发者朋友更好地分析并行的性能。随着硬件系统的越来越好,数据库运行的CPU、磁盘、内存资源都日渐增大,SQL语句的串行执行由于不能充分利用资源,已经不能满足日益发展的需要。为此,GaussDB(DWS)开发了并行计算技术,在语句执行时可以充分利用硬件资源进行并行加速,提高执行的吞吐率。本文将详细介绍GaussDB(DWS)并行计算技术的原理,以及其在performance信息中的展示,帮助各位开发者朋友更好地分析并行的性能,从而进行并行执行方面的调优。并行计算的原理很简单,将原本一个线程的工作平均分配到多个线程来完成,示意图如下图所示:图示中的关联操作,原本需要操作四份数据,通过并行度为4的并行计算后,每个子线程仅需要处理一份数据,理论上性能提升可以达到4倍。通常情况下,理论上的性能提升是达不到的,因为并行计算也有其性能损耗,包括:启动线程的代价,以及线程之间进行数据传输的代价。因此,只能性能损耗较低,大大低于并行带来的收益时,并行计算的收益才比较明显。所以,并行只有在数据量较大的场景下才能获得较高的性能收益,非常适合于分析型的AP场景。通过上述分析,我们可以看出,并行计算的难点不在于如何并行,而在于如何正确选择并行度。当数据量较小时,也许串行的性能是最好的,当数据量增大时,可以考虑进行并行。对于一个复杂的执行计划来说,可能包含多个算子,每个算子处理的数据量都不一样,如何综合考虑并行度,以及处理好各算子之间的数据收发关系,将成为并行计算技术的关键难点。GaussDB(DWS)基于代价估算,根据表的数据量信息来为计划片段生成合适的并行度,下面以TPC-DS Q48为例来看一下,GaussDB(DWS)的并行计划长什么样?select sum (ss_quantity)  from   store_sales, store, customer_demographics, customer_address, date_dim  where s_store_sk = ss_store_sk  and    ss_sold_date_sk = d_date_sk and d_year = 1998 and  (  (      cd_demo_sk = ss_cdemo_sk      and      cd_marital_status = 'M'      and      cd_education_status = '4 yr Degree'      and      ss_sales_price between 100.00 and 150.00       ) or  (     cd_demo_sk = ss_cdemo_sk      and      cd_marital_status = 'D'      and      cd_education_status = 'Primary'      and      ss_sales_price between 50.00 and 100.00     ) or   (     cd_demo_sk = ss_cdemo_sk     and      cd_marital_status = 'U'      and      cd_education_status = 'Advanced Degree'      and      ss_sales_price between 150.00 and 200.00   )  ) and (  (     ss_addr_sk = ca_address_sk     and     ca_country = 'United States'     and     ca_state in ('KY', 'GA', 'NM')     and ss_net_profit between 0 and 2000      ) or    (ss_addr_sk = ca_address_sk     and     ca_country = 'United States'     and     ca_state in ('MT', 'OR', 'IN')     and ss_net_profit between 150 and 3000   ) or    (ss_addr_sk = ca_address_sk     and     ca_country = 'United States'     and     ca_state in ('WI', 'MO', 'WV')     and ss_net_profit between 50 and 25000   )  );对应的performance信息为:通过将performance信息转变为计划树,可以得到该计划的计划树如下图所示:其中1-3号算子在CN上执行,DN上以跨线程数据传输的Stream算子进行分隔,一共会启动5个线程。GaussDB(DWS)采用pipeline的迭代执行模式,线程4和5从磁盘读取数据,其它每个Stream算子分隔的线程从子线程读取数据,进行执行,并将结果返回给上层算子,顶层DN线程将数据返回给CN处理。通过这个图,我们可以看出,线程1,4,5采用的并行度是1,而线程2,3采用的并行度是26。通过计划信息,我们可以看出,8-13号算子处理的数据量较大,刚好是线程2,3处理的范围,所以选择了较高的并行度。并行计算的Stream线程仍然沿用DN间的Stream线程进行启动和停止,但DN内部的数据传输改为内存拷贝进行,更节省网络资源,但带来一定程度的内存开销。同时,并行度的增大也使得跨DN间数据传输的数据缓冲区增大,内存开销变大。因此,大内存也是提高并行度的一个必备因素。那么线程之间是如何进行并行度的衔接呢?通过计划,我们可以看出,并行场景下,Stream线程均显示为:Streaming(type: T dop:N/M),这是在串行场景基础上的扩展,同时也可以以线程为级别看到每个线程执行时间,处理的行数和使用的内存。在串行场景下,我们支持三种类型的Stream算子,分别为redistribute, broadcast和gather,详细介绍参见《GaussDB(DWS)性能调优系列基础篇二:大道至简explain分布式计划》中第一章节介绍。并行场景是对串行场景中DN上的redistribute和broadcast类型Stream算子进行扩充,包括以下几类:1)Streaming(type: SPLIT REDISTRIBUTE):同串行场景下的Redistribute,但以线程为单位进行数据传输,每条元组发送给一个目的线程。2)Streaming(type: SPLIT BROADCAST):同串行场景下的Broadcast,但以线程为单位进行数据传输,每个线程都将收到全量数据。3)Streaming(type: LOCAL REDISTRIBUTE):作用是DN内部根据当前分布键进行数据Redistribute。通常作用于基表扫描后,因为基表扫描是按页面进行线程划分,此时线程间并不是按DN的分布键分布的,需要增加该DN内重分布操作。4)Streaming(type: LOCAL BROADCAST):作用是DN内部进行数据Broadcast,每个线程把数据发送给这个DN的所有线程,每个线程获得该DN的全量数据。5)Streaming(type: LOCAL GATHER):作用是DN内部把数据从多线程汇总到一个线程。注意:“dop:N/M”表示发送端的dop为M,接收端的dop为N,从而完成从M个线程的并行度转变为N个线程并行度的任务。在GaussDB(DWS)中,我们增加了参数query_dop,来控制语句的并行度,取值如下:1)query_dop=1,串行执行,默认值2)query_dop=[2..N],指定并行执行并行度3)query_dop=0,自适应调优,根据系统资源和语句复杂度情况自适应选择并行度由于开启并行会占用较多的内存,所以目前GaussDB(DWS)的默认并行度为1。在内存较大的环境下,可以通过手动设置query_dop达到并行加速的目的。通常情况下,我们可以考虑首先设置query_dop=0,查看语句的执行计划、performance信息和性能。在performance信息的下方Query Summary一栏,可以看到自适应dop选择的信息,例如:TPC-DS Q48 dop选择信息如下图所示,可以看出初步选定的initial dop为24,最终确定的final dop为26。dop的选择会综合考虑各种因素,其信息也在图中显示出来。由于自适应选择并行度是根据语句复杂度和系统资源利用情况来进行选择,而系统资源利用情况是获取前一段时间的资源利用情况,有可能出现不准确的情况,此时就需要人为来设置并行度了。人为设置并行度,并不是设置越大越好,dop设置过大,会导致系统中的线程数量急剧增多,导致CPU冲突进行线程切换的额外开销。要想人为设置并行度,同样需要使用单机CPU核数和语句复杂程度进行考量。我们定义单机CPU核数/单机DN数为每个DN可用的CPU核数x,然后根据串行计划中DN Stream算子的个数初步判定语句的复杂度y(例如下图TPC-H Q1计划中只有一个Stream节点,则y为1),单并发时,使用x/y的值设置query_dop。并发场景,再除以并发数p设置query_dop。由于此公式为粗略估计值,因此在设置时可以考虑扩大搜索范围,来寻找合适的并行度。在并发场景下,GaussDB(DWS)还支持max_active_statements来控制执行语句的个数,当语句的个数超过CPU核数时,可以考虑使用该参数限制并发数,然后再设置合理的query_dop进行调优。还是以刚才的示例为例,单机有96核,2个DN,则每个DN可用48核,则同时执行6个TPC-H Q1查询时,并行度可以设置为8。通过这篇文章,我们了解了GaussDB(DWS)并行计算技术的原理以及调优策略。希望广大开发者朋友们能够在实践中尝试该技术,更好地进行性能优化。原文链接:https://bbs.huaweicloud.com/blogs/203426【推荐阅读】【最新活动汇总】DWS活动火热进行中,互动好礼送不停(持续更新中)  HOT  【博文汇总】GaussDB(DWS)博文汇总1,欢迎大家交流探讨~(持续更新中)【维护宝典汇总】GaussDB(DWS)维护宝典汇总贴1,欢迎大家交流探讨(持续更新中)【项目实践汇总】GaussDB(DWS)项目实践汇总贴,欢迎大家交流探讨(持续更新中)【DevRun直播汇总】GaussDB(DWS)黑科技直播汇总,欢迎大家交流学习(持续更新中)【培训视频汇总】GaussDB(DWS) 培训视频汇总,欢迎大家交流学习(持续更新中)扫码关注我哦,我在这里↓↓↓
  • [集群&DWS] GaussDB(DWS) 集群通信系列一:pooler连接池
    【摘要】 pooler连接池介绍。一、pooler连接池是什么?pooler连接池是GaussDB CN进程内保存与其他GaussDB进程数据连接的数据结构,主要作用是连接复用,节省建连、认证、对端线程启动初始化开销。如上图所示,CN的pooler连接池中会保存与其他CN/DN的连接,每一个连接在对端会对应一个postgres工作线程。postgres工作线程是带状态属性的,如database,所以可以认为pooler连接池中的连接也是带属性的。不同属性间的连接是不能复用的,如上图所示,按不同属性切分为pool A/B/C等连接池。每个连接池中会存有连接往不同节点的空闲连接的数组,提供接口给外部使用或放入连接。CN上的postgres工作线程在需要连接其他节点时,会创建一个本地agent,尝试从pooler连接池取跟本线程相同属性的空闲连接,pooler如果没有空闲连接,就会新建一个连接。连接交给agent后,可以视为线程私有。在线程退出时,agent才会将连接还给pooler。注意:enable_stateless_pooler_reuse为on时,连接只按database区分连接池;enable_stateless_pooler_reuse为off时,连接按database+user+option区分连接池。二、怎么查看pooler连接池可以连接CN后通过pg_pooler_status查看,如下图:一般pooler连接池中的连接会非常多,可以按不同字段group by查看某个db pool池中的连接情况,或连往某个node的连接情况,如:select database,user_name,node_name,in_use,count(*) from pg_pooler_status group by 1, 2, 3 ,4 order by 5 desc limit 50;三、pooler连接池相关问题定位1,空闲连接太多导致DN线程超过max_connectionsDN上报错误信息:FATAL :dn_6011_6012 :[FATAL] Already too many clients. active/non-active: 998/1069/3 表明DN上2000个线程用满了,但有1069个空闲线程,此时可以通过在各个CN上查询pooler视图,统计连接此DN的空闲连接,确认问题。并通过手动clean connection清理空闲连接。CLEAN CONNECTION TO ALL FORCE FOR DATABASE postgres;GaussDB内核8.0.0版本已支持自动清理空闲连接功能。2,查询性能慢,查看CN pg_thread_wait_status视图显示大量建连状态"pooler create conn"大量pooler建连状态,说明空闲连接不够用。需要先确认当前的空闲连接状态:select in_use,count(*) from pg_pooler_status group by 1 order by 2 desc where database='XXX' and node_name='XXX';如果空闲连接和非空闲连接都很少,说明连接用完即销毁了。需要确认pooler连接池开关参数cache_connection=on,并确认CN日志没有报错。如果非空闲连接很多,空闲连接很少,说明并发太大,连接都在使用中,需要降低并发,或调大max_pool_size。原文链接:https://bbs.huaweicloud.com/blogs/200909【推荐阅读】【最新活动汇总】DWS活动火热进行中,互动好礼送不停(持续更新中)  HOT  【博文汇总】GaussDB(DWS)博文汇总1,欢迎大家交流探讨~(持续更新中)【维护宝典汇总】GaussDB(DWS)维护宝典汇总贴1,欢迎大家交流探讨(持续更新中)【项目实践汇总】GaussDB(DWS)项目实践汇总贴,欢迎大家交流探讨(持续更新中)【DevRun直播汇总】GaussDB(DWS)黑科技直播汇总,欢迎大家交流学习(持续更新中)【培训视频汇总】GaussDB(DWS) 培训视频汇总,欢迎大家交流学习(持续更新中)扫码关注我哦,我在这里↓↓↓
  • [存储] 云社区 博客 博客详情 Linux的Zombie进程的成因以及优化方法
    在linux系统中,进程(通过系统fork产生的)存在如下的一些状态(摘自ps官方manual手册)PROCESS STATE CODES       Here are the different values that the s, stat and state output specifiers (header "STAT" or "S") will display to       describe the state of a process:               D    uninterruptible sleep (usually IO)               R    running or runnable (on run queue)               S    interruptible sleep (waiting for an event to complete)               T    stopped by job control signal               t    stopped by debugger during the tracing               W    paging (not valid since the 2.6.xx kernel)               X    dead (should never be seen)               Z    defunct ("zombie") process, terminated but not reaped by its parent       For BSD formats and when the stat keyword is used, additional characters may be displayed:               <    high-priority (not nice to other users)               N    low-priority (nice to other users)               L    has pages locked into memory (for real-time and custom IO)               s    is a session leader               l    is multi-threaded (using CLONE_THREAD, like NPTL pthreads do)               +    is in the foreground process group这些状态一般通过ps -x可以查看,我们本次探讨的主要是关于Z状态的进程。我们先以一个例子简单说明一下什么是Zombie状态进程,以C代码为例 pid_t child = 0;         if ((child = fork()) < 0) { printf("fork err\n"); return; } else if (child == 0) { printf("child pid : %d,father is %d\n",getpid(),getppid()); _exit(0); } printf("pid is %d\n",getpid()); sleep(10); return 0;执行一下结果:此时可以看到子进程先退了,但是是真的完全没有了么,我们再看一下ps的结果:可以看到4418的进程变成了defunct,也就是我们常说的Zombie进程,再看一下state:这个是怎么产生的呢,我们回来再看代码,子进程退出前,执行了exit(0),通过查看exit的手册,我们找到了答案       After  exit(), the exit status must be transmitted to the parent process.  There are three cases.  If the parent has set       SA_NOCLDWAIT, or has set the SIGCHLD handler to SIG_IGN, the status is discarded.  If the  parent  was  waiting  on  the       child  it  is  notified  of the exit status.  In both cases the exiting process dies immediately.  If the parent has not       indicated that it is not interested in the exit status, but is not waiting, the exiting process turns  into  a  "zombie"       process (which is nothing but a container for the single byte representing the exit status) so that the parent can learn       the exit status when it later calls one of the wait(2) functions.这样也就是说,zombie状态实际是给父进程汇报子进程执行结束后的结果的,因此,如果父进程没有明确表示不关心这个结果,子进程会保持该状态,那么接下来就有两种处理方法:1、通过waitpid的方法,获取子进程的结束status,我们查看waitpid的系统调用可以了解到,最终的release_task是由父进程完成的(参考kernel3.10的源码调用)2、通过注册SIGCHLD信号处理的方式,明确父进程不关心子进程,这样在子进程退出时,则不会变成zombie状态(linux的wait手册)       A child that terminates, but has not been waited for becomes a "zombie".  The kernel maintains a minimal set of informa-       tion about the zombie process (PID, termination status, resource usage information) in order  to  allow  the  parent  to       later  perform  a  wait to obtain information about the child.  As long as a zombie is not removed from the system via a       wait, it will consume a slot in the kernel process table, and if this table fills, it will not  be  possible  to  create       further  processes.   If  a parent process terminates, then its "zombie" children (if any) are adopted by init(8), which       automatically performs a wait to remove the zombies.因此,可以看到,子进程的退出状态实际是由父进程来控制的(大概翻了一下代码实际是由进程组的leader的行为来决定的),而最为关键的一步,也是确保系统健康的一步,就是对于父进程退出后,所有的zombie进程都会由1号进程接管,因此,1号进程如果出现故障,或者回收的比较慢,就会造成zombie进程积压,最终引发系统崩溃。--------------------------------------------------------------------------------再来看一个python的案例(偷个懒,换个方便的语言,道理差不多,c整起来略麻烦):>>> import os>>> a = os.popen("date")>>> 通过a.close()的方法,可以回收掉这个defunct,python的popen实际是基于popen函数实现,内部会调用fork,这个和pclose成对,通过查看pclose源码,可以看到,这里面会调用waitpid来主动清理popen的Zombie进程。再来看一下通过信号明确不关心返回的处理方式SIGCHLD>>> import signal>>> signal.signal(signal.SIGCHLD,signal.SIG_IGN)0>>> b = os.popen("date")可以很明显看到不会残留一个Z状态的进程所以,我们在调用fork时(或者基于fork实现的功能时),要在代码中明确考虑SIGCHLD信号或者调用wait来清理子进程的退出状态,来防止Zombie进程的产生;当然,站在整个系统层面来说,尽量减少fork的总次数,也是一个不错的思路。原文链接:https://bbs.huaweicloud.com/blogs/178868【推荐阅读】【最新活动汇总】DWS活动火热进行中,互动好礼送不停(持续更新中)  HOT  【博文汇总】GaussDB(DWS)博文汇总1,欢迎大家交流探讨~(持续更新中)【维护宝典汇总】GaussDB(DWS)维护宝典汇总贴1,欢迎大家交流探讨(持续更新中)【项目实践汇总】GaussDB(DWS)项目实践汇总贴,欢迎大家交流探讨(持续更新中)【DevRun直播汇总】GaussDB(DWS)黑科技直播汇总,欢迎大家交流学习(持续更新中)【培训视频汇总】GaussDB(DWS) 培训视频汇总,欢迎大家交流学习(持续更新中)扫码关注我哦,我在这里↓↓↓
  • [问题求助] openmp 在由IBM aix 迁移到鲲鹏(Kylin v10)时 设置线程数函数无法使用
    【功能模块】openmp 多线程并行计算【操作步骤&问题现象】1、makefile  文件里 gcc增加编译选项 -fopenmp 增加链接库 -lgomp 2、源代码中存在 omp_set_num_threads(iTotalThreadNumber) 函数,使用此函数  iTotalThreadNumber=253、使用指令#pragma omp parallel for 使之下面 for循环都在多线程运行中4、使用 omp_get_thread_num ()函数获取线程号,线程号始终为 0 以下截图 一 部分代码供参考 其中 openmp  已经做宏定义。5、自己写了简单代码,gcc 编译时加编译选项 -fopenmp  可以实现多线程并行 请参考截图 二:【截图信息】迁移源码 图 一:截图 二:【日志信息】(可选,上传日志内容或者附件)
  • [技术干货] 【云上苏城,以梦为码】华为云MVP徐烨:这20年,我与应用系统的“云化”之路
    目前,以数字技术为主导的新一轮科技革命加速演进,数字化的进程一直伴随着互联网的发展过程。在国家政策和市场需求双重压力下,企业上云成为数字化转型升级新的突破口,越来越多的企业选择通过上云最大限度创造价值。在应用架构,物联网等方面有着丰富经验的徐烨,回望过去20年的工作经历,他表示应用系统的发展,就是一个不断“云化”的过程。这里说的“云化”,不只是信息化应用系统上云,而是要将应用系统技术及业务架构与云计算平台相互融合的过程,并为推动行业发展服务。他以三个有代表性的项目,讲述他与应用系统的“云化”之路。云化之路一:可视化并行申报+实时划缴税款,江苏省地级市应用系统近10年2001年,无锡宜兴国税局启动了电子申报项目,该项目主要是能够让纳税人通过本机软件填写和提交纳税申报表,税局接收申报数据进行自动申报,成功后自动划缴税款,并把相关结果反馈给纳税人。项目有两个技术亮点:一是可视化并行申报,二是实时划缴税款。在我们推出可视化并行申报以前,当时在行业内已经实现的电子申报后端服务,不但都是通过定时扫描纳税数据文件来串行处理申报,而且往往高峰时段要让纳税人等上2个小时以上才有申报结果,对处理程序也没有监看状态界面,都只有日志记录。项目中自行实现了动态数据展示组件和线程管理器组件,可视化并行申报监看界面上可以对已处理申报、成功数、待申报数和正在申报的纳税人数据情况一目了然,联想到现在,这个和现在很多的监控大屏功能有些类似;由于当时所有的申报数据都是数据文件和数据库操作为多,磁盘IO和等待数据库处理会花大量的时间,所以通过线程管理器配制合理线程数量并行处理后,申报效率有了倍数的提高,高峰期纳税人等待申报结果的时间也明显缩短。实时划款功能是初期讨论项目时提出来的,这在当时还是比较有创新性的,要知道当时根本没有税银联网协议,合作的三家银行中行、工行和建行,打报告一直到了总行才批复下来;当时虽然我刚参加工作,但对网络协议相对较熟,自己的毕业设计也因此获得了校优秀论文,所以很有信心的承担了这个任务。这个功能最后是通过线程管理组件和同步SOCKET来实现同三家银行对接,在申报成功后,可以提供秒级划缴税款,在顺利上线后,还获得了客户的高度认可。在接下来几年中,项目开发出的软件系统在江苏省内大部分地级市里得到了推行,并制定的税银协议。直至2011年全国TIPS系统上线后,使用新的硬件加密三方划缴体系后,才逐步被替换。云化之路二:发票存储+多服务器均衡,成国税总局参考依据2008年,公司启动了网票项目,项目主体功能是能够自动获取开票方领购发票信息,然后进行在线或离线开俱打印发票,数据都会自动传至税局服务端,再作票税比对及纳税分析。项目主要针对增值税普通发票,涉及纳税人广,票面种类多,仅江苏当时就有近32万户企业,每年发票用量近40亿份。项目中有两个技术亮点:一是发票存储;二是多服务器均衡。以往对于不同模版的发票存储,通常是不同类型的票使用对应的表,然后对于发票明细,都是按主表和附表来做,这样做需要保持一致性,所以对数据库有较大的压力。项目中为了解决这个问题,存储采用了微结构的方式,把发票的一条记录分成三个区,发票主杆、明细主杆和微结构存储,如图1所示,这样大大降底了对数据库一致性的要求,而增加了一些应用服务器的处理量,而应用服务器的处理量可以扩充服务器来解决的,为此获得了相关技术发明专利,并且这一微结构特别是在应用服务器相对比较容易扩充的构架下,可以较广泛的得以应用。图1多应用服务器并行处理,在原来电子申报项目的中后期也有应用,但最开始是用C#的异步Socket写了一个NetEqualizer的均衡器,来提供多应用服务器的并行处理,但高峰时,稳定性不是很好;在本项目改为NGINX和F5,由于F5是硬件,每台至少20万人民币以上,只有少量客户具备,所以主推是NGINX,稳定性也经受住了考验,特别是在linux上。当时印象深刻的是早期NGINX版本,比如断点续传这样的功能也无法支持,到了1.2及以后版本才支持,为此,还专门还组织了技术攻关小组,甚至阅读和修改了部分NGINX源码来解决。之后为了进一步减少单点故障,还引入LVS.DR进行更大规模并发支持,提出了组合均衡的方案,如图2所示,并获得了相关技术发明专利。图2后期,项目的应用系统在2010年获得了在江苏省全省的推广,也是当时国内第一个全省推广网票的省份,为国税总局在2013年发布《网络发票管理办法》提供了依据。云化之路三:平台应用系统拥抱云服务2016年,徐烨组建全新团队建设一个以LED屏为主的数显终端播控云平台,并以此为基础,设计出打通行业上下游的互联网平台——iLEDCloud云平台。在这个过程中,正式首次与IAAS供应商进行合作,相对以前项目而言,在技术层面在三个方面得到提升:微服务架构、高速NIO和安全业务架构。微服务架构就是将一个平台按需切分成很多个子服务,整个平台是基于JMS总线和三级存储建立的,对JMS服务进行了定制化,提供了子服务状态监测和自动回源。基于此项能力,平台WEB前端编缉节目时,即可对关联终端设备上的数据实时可视化,大大增强了客户体验;三级存储是指本地服务器内存、局域网内高速缓存服务和数据库服务三级,针对的是任务执行效率和服务宕机的平衡,通常一次任务绑定到一个服务执行,大部分正常情况下,可以以开支最小的方式完成任务;同时在单个服务宕机时,其它服务器上的同类服务能够依据设计成本来重建这个任务并执行。图3如图3所示,在这个架构下,从原来2017年的单个服务,到现在已经有20个以上的服务,并随着平台发展还会不断的拆分或增加。微服务是面向云计算平台的必然,原来云计算平台就是允许对资源的伸缩适配,而一个平台中各个模块所需资源是不同的,这时通过这种分离成微服务,可以对每个微服务提供不同的适配资源,这是适配资源的进一步提升。高速NIO是指高效的异步网络连接及数据处理。由于需要对每个数显终端进行实时控制,同时显示内容通常是视频或图片,数据量又较大,所以高效的连接管理优其重要。在本项目中全面使用NIO,包括终端连接协议和文件数据传送的FTP,通过设置以下二个要点:一是在数据处理线程代码中禁用延时代码;二是数据处理主要是协议解析和组装,把其它耗时业务代码尽量分离或设计成异步处理。经过优化代码,在单核情况下,都能较轻松支持几千个终端。同时重写了FTP文件传输服务的绝大部分代码,使其不但支持一次一密和虚拟目录的安全要求,还能满足在单线程下高效传输和速度控制。作为互联网信息发布性平台,安全性至关重要,项目也是本地网安重点检查单位。项目首次在行业内提出了事前、事中和事后的全域安全架构,并把用户操作风险系数贯穿与平台,形成了较完整安全业务架构。对连接协议也实现了类似入侵检测(IDS)功能的防火墙,对非法协议连接可以在前置环节就可隔断其来源IP地址。平台在今年国家等保三级复评中获得了86分以上的较高评测分。至今,平台已有近3000个注册用户,上线屏量也已超1万块。牵手华为云,携手迈向“云化”新征程2019年,通过地方政府牵线与华为云进行合作,华为云对软件研发类企业的支持是比较全面的,有较丰富的研发测试工具,是目前研发测试领域“云化”的先行者。基于华为云ESC主机,我们搭建了iLEDCloud互联网测试环境,通过白名单机制,使我们上海终端设备研发云平台测试、昆山终端设备生产云平台测试和苏州云平台研发测试,可以在一个平台上实现,不但节省了资源,也提升了跨区域测试的工作效率。企业上云,是企业顺应数字经济发展潮流,加快数字化、网络化、智能化转型,提高创新能力、业务实力和发展水平的重要路径。在徐烨的三个项目经历中不难发现,从单进程多线程到多服务器,再到微服务,从同步处理至多层次异步处理,从自建服务到集成第三方服务,从机房到IAAS供应商,都能体现“云化”之路上的成长。如果将同类功能的云集成称为混合云,将行业上下游的云集成称为生态云,那么混合云和生态云就是下一步 “云化”发展的目标,徐烨也希望能与华为云等高附加值的合作伙伴一起在“云化”之路上继续携手前行。
  • [技术干货] Java设计模式-单例模式
    简单点说,就是一个应用程序中,某个类的实例对象只有一个,你没有办法去new,因为构造器是被private修饰的,一般通过getInstance()的方法来获取它们的实例。getInstance()的返回值是一个对象的引用,并不是一个新的实例,所以不要错误的理解成多个对象。单例模式实现起来也很容易,直接看demo吧public class Singleton {private static Singleton singleton;private Singleton() {}public static Singleton getInstance() {  if (singleton == null) {   singleton = new Singleton();  }  return singleton;}}按照我的习惯,我恨不得写满注释,怕你们看不懂,但是这个代码实在太简单了,所以我没写任何注释,如果这几行代码你都看不明白的话,那你可以洗洗睡了,等你睡醒了再来看我的博客说不定能看懂。上面的是最基本的写法,也叫懒汉写法(线程不安全)下面我再公布几种单例模式的写法:懒汉式写法(线程安全)public class Singleton {      private static Singleton instance;      private Singleton (){}      public static synchronized Singleton getInstance() {      if (instance == null) {          instance = new Singleton();      }      return instance;      }  }饿汉式写法public class Singleton {      private static Singleton instance = new Singleton();      private Singleton (){}      public static Singleton getInstance() {      return instance;      }  }静态内部类public class Singleton {      private static class SingletonHolder {      private static final Singleton INSTANCE = new Singleton();      }      private Singleton (){}      public static final Singleton getInstance() {      return SingletonHolder.INSTANCE;      }  }枚举public enum Singleton {      INSTANCE;      public void whateverMethod() {      }  }这种方式是Effective Java作者Josh Bloch 提倡的方式,它不仅能避免多线程同步问题,而且还能防止反序列化重新创建新的对象,可谓是很坚强的壁垒啊,不过,个人认为由于1.5中才加入enum特性,用这种方式写不免让人感觉生疏。双重校验锁public class Singleton {      private volatile static Singleton singleton;      private Singleton (){}      public static Singleton getSingleton() {      if (singleton == null) {          synchronized (Singleton.class) {          if (singleton == null) {              singleton = new Singleton();          }          }      }      return singleton;      }  }
  • [性能调优] 【gaussdb 8.0产品】内存优化问题
    【操作步骤&问题现象】1、发现DN内存不足,查看进程发现有个线程占用了一半内存,就大佬讲解下这个线程正常么。select pg_catalog.gs_wlm_readjust_user_space_with_reset_flag('0000', false);
  • [实践系列] DWS 统计信息不准触发nestloop导致查询语句执行缓慢
    sql特点是2-3张表left join,然后通过select查询结果,执行计划如下:排查当前的IO,内存,CPU使用情况,没有发现资源占用高的情况查看慢sql的线程等待状态select * from pg_thread_wait_status where query_id=’149181737656737395’;根据线程等待状态,并没有出现都在等待某个DN的情况,初步排除中间结果集偏斜到了同一个DN的情况。到相应的实例节点上,打印等待状态为none的线程堆栈信息如下:gstack 14104通过反复打印堆栈信息,发现堆栈在变化,并没有hang死,所以初步判断该问题未性能慢的问题,堆栈中有VecNestLoopRuntime,以及结合执行计划,初步判断是由于统计信息不准,优化器评估结果集较少,计划走了nestloop导致性能下降。对表执行analyze后性能并没有太大改善对sql增加hint关闭索引,让优化器强行走hashjoin,发现hint功能没有生效,原因是hint无法改变子查询中的计划通过set enable_indexscan = off;执行计划被改变,走了Hash Left Join,慢sql在3秒左右跑出结果,满足客户需求。
  • [其他] 【故障】sql长时间执行无结果,CN异常重启
        一.本案例适合什么场景?1.集群操作系统为SUSE12.32.现象可能为CN实例异常重启3.现象可能为连接CN hung4.现象可能为sql执行慢,或长时间执行无结果    二.如何确定是该问题?1.cn日志failed to join thread xxx, ret is 110, Connection timed out2.选择一条hung住的sql,查询等待视图中该sql的信息select * from pgxc_thread_wait_status where query_id = 'xxxxxxxxxxx'; --xxx为该sql的query_id,可以从pg_stat_activity查到根据等待视图,可以得到分析结果如下a.该sql关联3个线程,1个cn线程,2个dn线程b.根据ptid字段,可以判断,236774(第二行)的父进程id为294563(第三行的lwtid)c.根据wait_status字段,cn在等待dn,dn子线程等待父线程结束,父线程为none,进程卡在这里长时间不释放wait_status字段值具体含义wait node等待接收与某节点的连接上的数据synchronize quit等待stream线程组内的线程统一退出none没在等任意事件3.对卡住的线程抓堆栈 gstack 294563(等待视图lwtid字段)以下堆栈信息#1行 in __lll_lock_elision ()为os加锁,则数据库省略加锁Thread 28 (Thread 0x7f7abbb61700 (LWP 51263)):#0  0x00007f7bd5c52b7c in __lll_lock_wait () from /lib64/libpthread.so.0#1  0x00007f7bd5c55520 in __lll_lock_elision () from /lib64/libpthread.so.0#2  0x0000560c90d29e80 in WLMReserveGlobalActiveStatement() ()#3  0x0000560c90d2a051 in WLMReserveAcstatement(ParctlType) ()#4  0x0000560c90a84c6c in exec_simple_query(char const*, MessageType, StringInfoData*) ()#5  0x0000560c90a8903d in PostgresMain(int, char**, char const*, char const*) ()#6  0x0000560c9092acfe in SubPostmasterMain(int, char**) ()#7  0x0000560c9092bc85 in MainStarterThreadFunc(void*) ()#8  0x00007f7bd5c4b724 in start_thread () from /lib64/libpthread.so.0#9  0x00007f7bd598aeed in clone () from /lib64/libc.so.6Thread 27 (Thread 0x7f7abcb62700 (LWP 51257)):#0  0x00007f7bd5c52b7c in __lll_lock_wait () from /lib64/libpthread.so.0#1  0x00007f7bd5c55520 in __lll_lock_elision () from /lib64/libpthread.so.0#2  0x0000560c90d29e80 in WLMReserveGlobalActiveStatement() ()#3  0x0000560c90d2a051 in WLMReserveAcstatement(ParctlType) ()#4  0x0000560c90a84c6c in exec_simple_query(char const*, MessageType, StringInfoData*) ()#5  0x0000560c90a8903d in PostgresMain(int, char**, char const*, char const*) ()#6  0x0000560c9092acfe in SubPostmasterMain(int, char**) ()#7  0x0000560c9092bc85 in MainStarterThreadFunc(void*) ()#8  0x00007f7bd5c4b724 in start_thread () from /lib64/libpthread.so.0#9  0x00007f7bd598aeed in clone () from /lib64/libc.so.6Thread 26 (Thread 0x7f7abe5e3700 (LWP 51221)):#0  0x00007f7bd5c52b7c in __lll_lock_wait () from /lib64/libpthread.so.0#1  0x00007f7bd5c55520 in __lll_lock_elision () from /lib64/libpthread.so.0#2  0x0000560c90d29e80 in WLMReserveGlobalActiveStatement() ()#3  0x0000560c90d2a051 in WLMReserveAcstatement(ParctlType) ()#4  0x0000560c90a84c6c in exec_simple_query(char const*, MessageType, StringInfoData*) ()#5  0x0000560c90a8903d in PostgresMain(int, char**, char const*, char const*) ()#6  0x0000560c9092acfe in SubPostmasterMain(int, char**) ()#7  0x0000560c9092bc85 in MainStarterThreadFunc(void*) ()#8  0x00007f7bd5c4b724 in start_thread () from /lib64/libpthread.so.0#9  0x00007f7bd598aeed in clone () from /lib64/libc.so.64.满足以上排查条件,可以初步判断是本次案例说明的问题,可采用下文解决手段    三.问题根因以及如何解决,见详细分析https://bbs.huaweicloud.com/forum/thread-94892-1-1.html
  • [问题求助] 【arm系统】【JAVA 线程池】java线程池中的线程处于WAITING状态,不执行等待队列中的任务
    【功能模块】arm系统【操作步骤&问题现象】问题描述:我们在三台arm机器上安装了zookeeper集群(3.5.5版本),共三个节点,运行一段时间后(3小时-3天),三台中一台zookeeper节点不响应请求了(ruok、stat等请求),使用zkCli去连接也连接失败,但是进程是存活的,端口也处于监听状态。排查过程:通过远程debug去查看问题原因,发现zookeeper的执行请求的线程池中堆积了大量等待执行的任务,但是没有线程来取任务。持续观察了半个小时,等待队列中的任务数量在持续增加,但是completed tasks数量一直不增加,如下所示:java.util.concurrent.ThreadPoolExecutor@2afba2ee[Running, pool size = 128, active threads = 0, queued tasks = 903, completed tasks = 7468631]java.util.concurrent.ThreadPoolExecutor@2afba2ee[Running, pool size = 128, active threads = 0, queued tasks = 918, completed tasks = 7468631]java.util.concurrent.ThreadPoolExecutor@2afba2ee[Running, pool size = 128, active threads = 0, queued tasks = 1042, completed tasks = 7468631]线程池中的线程的jstack如下"NIOWorkerThread-105" #146 daemon prio=5 os_prio=0 tid=0x0000fffeb409c800 nid=0x463a waiting on condition [0x0000fffd944fe000]   java.lang.Thread.State: WAITING (parking)        at sun.misc.Unsafe.park(Native Method)        - parking to wait for  <0x00000000c0028cc0> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)        at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)        at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)        at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:442)        at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1074)        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1134)        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)        at java.lang.Thread.run(Thread.java:748)一直处于WAITING状态,该状态是 LinkedBlockingQueue中没有对象时会调用 Condition.await进入WAITING状态,但是当有对象进入队列时应当会调用Condition.signal唤醒,目前的问题是Condition.signal并没有唤醒我们初步怀疑是和glibc有关系,想咨询一下是否有人遇到过该问题?环境信息:系统 centos7-7.6.1810(AltArch)内核版本  Linux 4.14.0-115.el7a.0.1.aarch64 aarch64glibc版本 glibc-2.17-260.el7.aarch64jdk版本 1.8.0_241
  • [实践系列] DWS 以TPCH Q7为例,简单介绍Hang问题基本定位过程
    问题现象:构造某DN发送慢的疑似Hang场景,以TPCH Q7为例,简单介绍Hang问题基本定位过程。定位过程:执行explain (costs off) 查看Q7的执行计划。注:从Q7计划可见,DN上参与查询的有一个postgres主线程(top consumer线程)和5个stream线程,这里,5号线程是top consumer线程的子线程,11号线程,20号线程是5号线程的子线程,14号线程是11号线程的子线程,16号线程是14号线程的子线程。父子线程间,子线程作为producer向父线程发送数据,父线程充当consumer接收子线程发来的数据,从而保证分布式计划下数据在DN间的流动。2.gsql连接CN,查询视图pg_stat_activity,获取目标SQL的query_id。注:query字段最多能显示1024字节。3.连接CN,查询全局视图pgxc_thread_wait_status,与上述query相关的所有线程的层次调用关系如下图,其中,每个DN都有6个线程,其中0号线程为top consumer线程,其他线程与Step1执行计划中stream算子的层级关系一致。时刻1:时刻1时,coordinator1的状态为“wait node: datanode4, total 4”,即等待4个DN执行完成,当前等待节点是datanode4,datanode4上的top consumer线程状态为“wait node: datanode4(5), total 4”,即datanode4的0号线程在等待datanode4的5号线程,datanode4的5号线程当前状态为“wait node:datanode4(11), total 1”,即5号线程等待datanode4的11号线程,datanode4的11号线程当前状态为“flush data: datanode4(5)”,即正在向datanode4的5号线程发送数据。时刻2:时刻2时,coordinator1的状态为“wait node: datanode4, total 4”,即等待4个DN执行完成,当前等待节点是datanode4,datanode4上的top consumer线程状态为“wait node: datanode4(5), total 1”,即datanode4的0号线程在等待datanode4的5号线程,datanode4的5号线程当前状态为“flush data: datanode4(0)”,即5号线程正在向datanode4的0号线程发送数据。结论:datanode4的5号线程向其他DN的0号线程发送数据,继续多次执行Step3,观察线程状态是否有变化,当前案例中flush data: datanode4(0)持续几秒后,状态发生更新,数据有在流动,可见该疑似Hang问题只是发送端执行慢而已,与最初场景构造(internal_flush函数中强制datanode4发送数据时注入sleep(5))的预期一致。   
  • [其他] 【扩容】添加主机成功后页面出现37014 Gaussdb进程锁文件已经存在的告警
    发生版本【GaussDB(DWS)】【6.5.1】问题描述添加主机成功后页面出现37014 gaussdb进程锁文件已经存在的告警问题分析cma的启停线程在start_datanode_check逻辑,判断进程不存在之后,会检查是否有gs_ctl在运行,如果有gs_ctl运行,会sleep(2)用来让gs_ctl build在执行的时候,有足够的时间创建gs_build.pid文件。这样会造成一个问题,2s前检测到dn进程不存在。进入进程不存在的判断逻辑,DN START,但是此时有概率dn在进行build,这个时候,会sleep(2),2s之后dn进程成功启动,cma再次拉起。解决方案按如下步骤可消除告警:1、先根据告警信息找到上报告警的dn对应的目录2、把目录下的postmaster.pid文件移到其他地方3、然后在kill出问题的dn对应的进程
  • [其他] 【故障】ldapserver服务异常或者okerberos,oldap进程异常
    此文档仅限于操作系统升级后出现的故障。需要查看nss版本是否升级到了3.44或者以上,依赖需要其版本低于3.44如果是符合上述条件,需要对nss进行降级(下面以centos7.3为例)1.准备os镜像,并挂载 mount -o loop /opt/syy/CentOS-7.3-x86_64-DVD-1611.iso /mnt/2.配置yum镜像源vi /etc/yum.repos.d/CentOS-Base.repo[iso]name = isobaseurl=file:///mntgpgcheck=0enable=13.先卸载nss-pem库 该rpm在centos 7.3 不存在rpm -e --nodeps nss-pem-1.0.3-5.el7.x86_64确认镜像系统是否存在nss-pem的rpm包,若是低版本可以通过yum downgrage降级4. 通过执行命令降级nss及依赖包yum downgrade nss nss-sysinit libcurl nss-tools firefox curl nss-softokn-freebl nss-softokn nss-util
  • [其他] 【故障】某局点跑批业务出现卡住
    1先查看等待视图select * from pgxc_thread_wait_status;可以看到大部分语句的等待wait active statements说明语句占了并发但是跑不动,导致后边的语句都在排队2 show max active statements显示单cn最大并发为603 select count(*) from pg_stat_activity where state='active' and usename!='omm';可以看到当前的cn5003的活跃语句已有90个4查看cn日志可看到外表语句有锁不放,insert into 内表 select from 外表 拿不到锁,锁等待超时5 查看等待视图,发现除alter外,有些insert into select拿到锁也跑不动,在cn上等待的是None,没有下发dn   可以判定是卡在了和GDS的交互6 查看GDS日志,有大量之日志报出too many open files7 ulimit -a,可以看到max open files是640000,但是在/proc/gds进程/limits文件里,max open files仍是10248 重新登录,杀掉GDS进程重新拉起,确认进程编程640000,解决核心原因    修改limits.conf重启gds进程,gds进程未变化是登录窗口加载当前的conf配置,主要不退出都会使用已有配置,重新登录才会生效  
总条数:813 到第 页
上滑加载中