Quantcast
Channel: IT社区推荐资讯 - ITIndex.net
Viewing all 11852 articles
Browse latest View live

基础设施服务的微服务化

$
0
0

这篇文章是根据我在SFDC(SegmentFault Developer Conference)大会上的分享整理而成。

1

今天我给大家分享的题目是『基础设施服务的微服务化』。微服务这一两年非常火,今天的服务器端的分享主题应该至少90%和微服务相关。同时你会发现,云,容器等技术的发展都是在给微服务铺路,因为用户本质上需要的是服务,不是资源。但大多数和微服务相关的讨论都是分析业务应用如何微服务化,如何远程调用,如何服务治理,谈论基础设施服务的却很少,我们今天来聊聊这个。

3

讨论微服务,遇到的第一个问题就是多微的服务才能叫微服务呢?是否有个标准,比如多少行代码,多少个方法,多少个接口?

我们来看看微服务这个概念的最早定义:

4

我们不用全部仔细看完,只需看看我标出来的几个关键词:

  1. small service这个好理解,就是微服务就是小服务。
  2. independently deployable可独立部署。微服务就是将原来的共享库的依赖方式,改为远程调用的依赖方式,每个微服务都是独立部署的服务。
  3. fully automated deployment完全的自动化部署。这点往往被大家忽略,为什么微服务就要完全的自动化部署呢?因为以前的几个服务,被拆分为成百上千的服务,如果没有完全的自动化部署,基本上是不可维护的。当然,你可以说『我就是不差钱,我就招上千个人来管这些服务』:)就不叫微服务了?也能行,但这也违背了我们搞微服务的目标吧。

5

所以我们再回归到微服务这个概念。我个人认为微服务化本身包含两层意思,一层是拆,这个大家提到的多,将大的服务拆成小的服务粒度,通过远程调用解决依赖。但同时它也有另外一层意思,就是合,就是整个系统的微服务的所有组件之间应该是一个整体的分布式系统,按集群化的方式来设计,服务之间能互相感知,进行自动化协作。

我们来看一个微服务的一个例子。

6

这里面有ABCD四个服务,每个服务都依赖数据库以及缓存,对外的服务有负载均衡器,服务之间互相依赖,异步交互通过队列进行。通过这样一个简单的微服务例子,我们可以看出基础设施都有哪些。

7

那我们的问题就来了 — 基础设施服务是否需要微服务化?

8

要解答这个问题,我们先看看当前的基础设施服务的主要解决方案:

9

第一种是大的互联网公司普遍使用的一种方案。基础设施服务托管给基础设施部门,基础设施部门包含运维,DBA 等。比如开发人员需要一套 mysql 服务的时候,提出申请,基础设施部门负责搭建和运维,开发人员只需要连接 mysql 的 IP 进行使用即可。另外一种方式是托管给云厂商,是使用当前云的基础设施服务。比如QingCloud,AWS,还有阿里云等,都提供基础设施服务,比如需要一套 mysql,在控制台即可创建,然后获取到连接 IP ,这样可以省去运维基础设施服务的成本。

但是这两种方式都有一些问题:

10

  1. 开发测试流程中的基础设施服务如何部署,如何自动化?这个没法委托给基础设施部门,需要开发人员自己动手搞。但开发人员一方面也没有精力搞一套完整的自动化工具,但即便是搞了,也解决不了开发环境和线上环境异构的问题。前面有位讲师的分享也说到了这个问题,异构问题总会导致故障,没出现故障也是时候没到。
  2. 另外一个问题就是基础设施服务迁移、伸缩、故障恢复时应用如何感知?比如有个 mysql 集群,当前数据库请求量太大,扩容了从库,应用如何自动感知到这个变化,从而使用新的从库?

我们再回顾下微服务的要求:

11

当前的基础设施服务的解决方案,不能满足微服务的集群化,自动化这两点要求。我们可以得出结论:

12

基础设施服务属于微服务系统中的一部分,需要和业务服务互相感知,需要被微服务化。

这就引出了我们的另外一个问题:

13

基础设施服务如何微服务化?这个主要有以下难点:

14

基础设施服务种类多样。比如前面那个简单的微服务系统,就用到了很多基础设施服务,各种服务的有各种不同的配置方式。同时,这些服务的集群机制也是多种多样的。我们举几个例子来说明下。

15

Zookeeper 的主要配置文件是 zoo.cfg,这个配置文件中需要列出整个集群中的所有节点,以及对应的server id。另外,每个节点还有一个独立的 myid 配置文件,这个文件中写了当前节点的 server id。比如要把这个集群扩展到5个节点,首先要要算出新的节点的 server id 号,生成新的节点的myid 配置文件,同时需要变更每个节点的 zoo.cfg 配置文件,把新节点的 server id 和 IP 都写进去,然后重启服务。

16

HAproxy 的配置文件中的每个 backend 后会配置一个 server 列表。如果后端服务伸缩,就需要变更这个 server 列表。

17

Redis Cluster 的这个例子我只是想说明下, redis 并不是通过配置文件来维护集群信息的,而是通过动态命令。创建集群,增删节点,都需要调用命令进行。

18

Kafka 是通过 Zookeeper 来做服务发现的,所以如果 Zookeeper 集群变更,就需要变更它的配置文件中的 zookeeper.connect 配置项。

19

粗略的看了以上的几个例子,大家对基础设施服务的配置和集群的多样性有了初步的体验。既然要微服务化,就需要设计服务的注册发现以及配置变更方案。微服务理想中的方案是应用内部自发现,监听配置中心,自动进配置变更。但现实的状况我们前面的例子也看到了,我们也不可能等待这么多的服务逐渐都改造升级了再用,所以唯一可行的办法就是通过非侵入的方式,进行第三方的服务注册,以及配置变更。

下面我介绍一下我们 QingCloud 应用调度系统的一些实践。

21

我们在 IaaS 调度系统之上构建了应用集群的调度系统,它知道集群里的 vm 节点的变化,然后将集群的基础信息注册到我们的元信息服务 metad 中。每个 vm 节点里面都运行一个 confd 进程,监听 metad 的元信息,一旦发生变化,则变更本地的配置和服务。比如左图的这个例子,应用集群依赖一个 zookeeper 集群,二者都关联在 metad 中。如果 zookeeper 集群的节点发生变化,应用集群是可以通过 metad 感知到变化,并且通过 confd 进行配置变更。下面我分别简单介绍一下使用到的一些组件。

22

Etcd 是一个开源的分布式的一致性 kv 存储,提供元信息的持久化,同时它支持 watch 机制,可以实现变更推送。

23

Metad 是我们自己研发的一个开源的元信息服务。它的后端对接 etcd ,和 etcd 实时同步数据。我们前面也说了,当前我们的方案是通过调度系统进行服务注册。这种注册方式有一个问题就是,节点启动的时候,它不清楚自己所处的角色,也就是不知道『我是谁』。人生哲学的头一个难题就是回答『我是谁』,服务器也有这个困境。所以我们在 metad 中保存了 IP 到元信息之间的映射关系,客户端请求一个固定的接口 /self 就可以拿到自己本节点的信息,当前节点所处的集群的信息,以及当前集群依赖的其他集群的信息。它也支持 watch 机制,实现变更推送。

24

Confd 是一个开源的配置变更工具,我们在其基础上进行了二次开发,后端对接 metad。它通过监听 metad 的变更通知,同步元信息到本地缓存,然后根据模板渲染配置文件,如果发现配置不一样,则进行应用的配置变更,同时触发脚本让应用程序重新加载配置(reload 或者 restart)。下面我们通过一个例子来说明下。

25

还是一个 zookeeper 的例子,我们首先有个集群的编排配置文件,定义了其中每个节点的镜像,cpu,内存,磁盘,节点数量,以及启动,停止等 service 脚本。

26

我们给 zoo.cfg 定义了一个配置文件模板,这个模板是给 confd 用来渲染配置文件的。模板的语法是 go template 语法,如果不熟悉这个模板语法也没关系,大家可以看出这段脚本是在循环配置中心的 hosts 列表,然后生成 server id 和 IP 之间的映射配置。

27

这是那个 myid 配置文件的模板,这个很简单,我们给集群的每个几点都会分配一个 sid,这种情况,直接吧 sid 写到 myid 配置文件就好。

28

同时,我们的集群编排支持 kvm 和 docker 两种镜像,这样就可以实现 kvm 和 docker 的混排。如果应用有特殊需求 docker 镜像不能满足,比如 kernel 版本,则可以使用 kvm 镜像。当然我们这里的 docker 镜像不是标准的 docker 镜像方式,镜像默认启动的进程,也就是 init 进程必须是 confd,然后应用通过 confd 来启动。这个方式和 大家用 docker 的习惯不一样,比如 zookeeper 的镜像,习惯启动的第一个进程就是 zookeeper 服务。

那我们为什么不用 docker 默认的方式呢?

29

这也是一个理想和现实妥协的方案。理想中的 docker 应用配置,应该是静态配置通过环境变量,动态的通过配置中心。比如 jvm 的启动内存设置就是静态配置,通过环境变量传递,如果应用需要变更内存设置,直接销毁旧的容器实例,重新启动新的并传递新的环境变量即可。但现实的状况,我们前面也举了好几个例子,大多数应用的配置还都是通过配置文件,无论动态还是静态。我们为了变更应用的配置文件,就需要通过 confd,所以我们的 docker 镜像默认先启动 confd。

以上就是我们当前的实践方案。下面我们和业界的其他一些方案做一些比较。

30

Ansible/Puppet/Salt/Chef 这一系列配置变更以及自动化工具,本质上都是纯静态的配置变更工具。它们是把变量通过模板渲染成配置文件,这里的静态指的是这些变量在编写配置规则时就是确定的,所以它们的复用机制不够通用。比如有人写了一个自动部署 zookeeper 集群的 ansible 模块,但当你想用这个模块部署自己的服务的时候,会发现需要有许多变量需要修改,比如网络,等等。它们的静态模式导致的另外一个问题就是服务的依赖变更不好解决,比如前面 HAProxy 那个例子,当后端服务伸缩的时候,要变更 HAProxy 配置,还是得手动修改变量,然后重新执行配置变更脚本。所以它们只能是半人工半自动化工具,对动态的故障迁移以及伸缩,容灾也没有好的办法。

31

Kubernetes 的目标是通用的容器编排系统,做了很多通用的抽象,试图通过 DNS,虚拟 IP 这样的通用机制来解决服务间的依赖问题。比如前面那个 mysql 的例子,mysql 从库伸缩后应用如何感知?它的解决方案是 mysql slave 可以作为一个独立的服务,会分配一个 DNS name,以及一个 虚拟 IP。应用连接的时候通过 DNS 以及虚拟 IP 进行,并不需要知道后面的每个从库节点 IP。但这种方式的问题就是有些场景满足不了,比如前面的 zookeeper,集群中的每个节点都需要能和其他节点直接通信,类似的还有 elasticsearch。Kubernetes 的 elasticsearch 解决方案是给 elasticsearch 写一个插件,通过 kubernetes 提供的注册中心的接口来发现集群中的其他节点。但如果应用不支持插件就比较麻烦,比如 redis cluster,文末有个 redis cluster 运行在 k8s 上的案例,做法是把每个节点都作为一个 service,如果要扩展节点的话,必须新增 k8s 的 service 配置文件,然后节点运行之后再通过手动调用命令进行初始化。它支持全局的配置文件映射,但只是纯静态配置,不支持变更。

32

Mesos 的目标是通用的资源调度和分配系统,如果把应用要放到 Mesos 之上,应用需要通过扩展 framework 来实现,开发成本比较高。如果用通用的容器方式,也有和k8s类似的问题。

所以当前看来,我们的方案是相对可行度比较高,容易实践,对各种不同的集群应用的包容性也比较高的方案。

33

最后再介绍一下我们的新应用中心。主要基于前面的应用调度系统,给企业提供应用标准化开发平台,可以快速将应用云化,实现应用的秒级部署和弹性伸缩。同时提供计费服务以及客服平台,让企业应用快速实现商业化。当前还在邀请内测阶段。

34

那这个对我们开发者有什么意义呢?一方面我觉得可能会带来基础研发运维部门在企业中的角色转换。因为当前基础研发运维部门在企业中属于业务支撑的部门,基本上是成本部门,并不是直接生产利润的部门。但如果有了这样的平台,基础研发运维部门可以通过企业应用市场将自己的基础组件共享出来,进行售卖。比如每个大一点的互联网公司都会搞一套 mysql 的分布式的集群方案,进行自动的分库分表,如果能在应用市场中找到这样的工具,中小企业肯定也是愿意买单的。所以也可以说服务器端研发人员的春天到了。以前我们很羡慕搞客户端开发的人,自己做个 app 就可以放到应用市场去售卖,现在服务器端开发也可以了。我这里不是说我们一家就能把这个春天带来,而是说服务器端的应用标准化,已经是大势所趋,大家都在做这方面的尝试。可以做个预测,2017年,各容器编排集群,各云厂商,都会推出自己的类似的解决方案,可以期待。

我的分享就这里。

qrcode_jolestar_blog2

相关链接


  1. Etcd 架构与实现解析本人的一篇关于 etcd 的文章,想深入了解 etcd 的可以看看。
  2. Kubernetes 架构浅析本人的一篇关于 k8s 的文章,想深入了解 k8s 的可以看看。
  3. Mesos 架构以及源码浅析本人的一篇关于 mesos 的文章,想深入了解 mesos 的可以看看。
  4. kubernetes cloud plugin for elasticsearch文中提到的通过k8s api 进行节点发现的 elasticsearch 插件
  5. kubernetes 上运行 redis cluster 的例子
  6. confd我们修改版的confd仓库地址。
  7. metad仓库地址。

并发之痛 Thread,Goroutine,Actor

$
0
0

本文基于我在2月27日Gopher北京聚会演讲整理而成,进行了一些补充以及调整。投稿给《高可用架构》公众号首发。

聊这个话题之前,先梳理下两个概念,几乎所有讲并发的文章都要先讲这两个概念:

concurrent_vs_parallel

  • 并发(concurrency)并发的关注点在于任务切分。举例来说,你是一个创业公司的CEO,开始只有你一个人,你一人分饰多角,一会做产品规划,一会写代码,一会见客户,虽然你不能见客户的同时写代码,但由于你切分了任务,分配了时间片,表现出来好像是多个任务一起在执行。
  • 并行(parallelism)并行的关注点在于同时执行。还是上面的例子,你发现你自己太忙了,时间分配不过来,于是请了工程师,产品经理,市场总监,各司一职,这时候多个任务可以同时执行了。

所以总结下,并发并不要求必须并行,可以用时间片切分的方式模拟,比如单核cpu上的多任务系统,并发的要求是任务能切分成独立执行的片段。而并行关注的是同时执行,必须是多(核)cpu,要能并行的程序必须是支持并发的。本文大多数情况下不会严格区分这两个概念,默认并发就是指并行机制下的并发。

为什么并发程序这么难?


We believe that writing correct concurrent, fault-tolerant and scalable applications is too hard. Most of the time it’s because we are using the wrong tools and the wrong level of abstraction. —— Akka

Akka官方文档开篇这句话说的好,之所以写正确的并发,容错,可扩展的程序如此之难,是因为我们用了错误的工具和错误的抽象。(当然该文档本来的意思是Akka是正确的工具,但我们可以独立的看待这句话)。

那我们从最开始梳理下程序的抽象。开始我们的程序是面向过程的,数据结构+func。后来有了面向对象,对象组合了数结构和func,我们想用模拟现实世界的方式,抽象出对象,有状态和行为。但无论是面向过程的func还是面向对象的func,本质上都是代码块的组织单元,本身并没有包含代码块的并发策略的定义。于是为了解决并发的需求,引入了Thread(线程)的概念。

线程(Thread)

  1. 系统内核态,更轻量的进程
  2. 由系统内核进行调度
  3. 同一进程的多个线程可共享资源

线程的出现解决了两个问题,一个是GUI出现后急切需要并发机制来保证用户界面的响应。第二是互联网发展后带来的多用户问题。最早的CGI程序很简单,将通过脚本将原来单机版的程序包装在一个进程里,来一个用户就启动一个进程。但明显这样承载不了多少用户,并且如果进程间需要共享资源还得通过进程间的通信机制,线程的出现缓解了这个问题。

线程的使用比较简单,如果你觉得这块代码需要并发,就把它放在单独的线程里执行,由系统负责调度,具体什么时候使用线程,要用多少个线程,由调用方决定,但定义方并不清楚调用方会如何使用自己的代码,很多并发问题都是因为误用导致的,比如Go中的map以及Java的HashMap都不是并发安全的,误用在多线程环境就会导致问题。另外也带来复杂度:

  1. 竞态条件(race conditions)如果每个任务都是独立的,不需要共享任何资源,那线程也就非常简单。但世界往往是复杂的,总有一些资源需要共享,比如前面的例子,开发人员和市场人员同时需要和CEO商量一个方案,这时候CEO就成了竞态条件。
  2. 依赖关系以及执行顺序如果线程之间的任务有依赖关系,需要等待以及通知机制来进行协调。比如前面的例子,如果产品和CEO讨论的方案依赖于市场和CEO讨论的方案,这时候就需要协调机制保证顺序。

为了解决上述问题,我们引入了许多复杂机制来保证:

  • Mutex(Lock) (Go里的sync包, Java的concurrent包)通过互斥量来保护数据,但有了锁,明显就降低了并发度。
  • semaphore 通过信号量来控制并发度或者作为线程间信号(signal)通知。
  • volatile Java专门引入了volatile关键词来,来降低只读情况下的锁的使用。
  • compare-and-swap 通过硬件提供的CAS机制保证原子性(atomic),也是降低锁的成本的机制。

如果说上面两个问题只是增加了复杂度,我们通过深入学习,严谨的CodeReview,全面的并发测试(比如Go语言中单元测试的时候加上-race参数),一定程度上能解决(当然这个也是有争议的,有论文认为当前的大多数并发程序没出问题只是并发度不够,如果CPU核数继续增加,程序运行的时间更长,很难保证不出问题)。但最让人头痛的还是下面这个问题:

系统里到底需要多少线程?

这个问题我们先从硬件资源入手,考虑下线程的成本:

  • 内存(线程的栈空间)
    每个线程都需要一个栈(Stack)空间来保存挂起(suspending)时的状态。Java的栈空间(64位VM)默认是1024k,不算别的内存,只是栈空间,启动1024个线程就要1G内存。虽然可以用-Xss参数控制,但由于线程是本质上也是进程,系统假定是要长期运行的,栈空间太小会导致稍复杂的递归调用(比如复杂点的正则表达式匹配)导致栈溢出。所以调整参数治标不治本。
  • 调度成本(context-switch)
    我在个人电脑上做的一个非严格测试,模拟两个线程互相唤醒轮流挂起,线程切换成本大约6000纳秒/次。这个还没考虑栈空间大小的影响。国外一篇论文专门分析线程切换的成本,基本上得出的结论是切换成本和栈空间使用大小直接相关。

    context switch

  • CPU使用率
    我们搞并发最主要的一个目标就是我们有了多核,想提高CPU利用率,最大限度的压榨硬件资源,从这个角度考虑,我们应该用多少线程呢?
    cpu ratio

    这个我们可以通过一个公式计算出来,100/(15+5)*4=20,用20个线程最合适。但一方面网络的时间不是固定的,另外一方面,如果考虑到其他瓶颈资源呢?比如锁,比如数据库连接池,就会更复杂。

作为一个1岁多孩子的父亲,认为这个问题的难度好比你要写个给孩子喂饭的程序,需要考虑『给孩子喂多少饭合适?』,这个问题有以下回答以及策略:

  • 孩子不吃了就好了(但孩子贪玩,不吃了可能是想去玩了)
  • 孩子吃饱了就好了(废话,你怎么知道孩子吃饱了?孩子又不会说话)
  • 逐渐增量,长期观察,然后计算一个平均值(这可能是我们调整线程常用的策略,但增量增加到多少合适呢?)
  • 孩子吃吐了就别喂了(如果用逐渐增量的模式,通过外部观察,可能会到达这个边界条件。系统性能如果因为线程的增加倒退了,就别增加线程了)
  • 没控制好边界,把孩子给给撑坏了 (这熊爸爸也太恐怖了。但调整线程的时候往往不小心可能就把系统搞挂了)

通过这个例子我们可以看出,从外部系统来观察,或者以经验的方式进行计算,都是非常困难的。于是结论是:

让孩子会说话,吃饱了自己说,自己学会吃饭,自管理是最佳方案。

然并卵,计算机不会自己说话,如何自管理?

但我们从以上的讨论可以得出一个结论:

  • 线程的成本较高(内存,调度)不可能大规模创建
  • 应该由语言或者框架动态解决这个问题

线程池方案


Java1.5后,Doug Lea的Executor系列被包含在默认的JDK内,是典型的线程池方案。

线程池一定程度上控制了线程的数量,实现了线程复用,降低了线程的使用成本。但还是没有解决数量的问题,线程池初始化的时候还是要设置一个最小和最大线程数,以及任务队列的长度,自管理只是在设定范围内的动态调整。另外不同的任务可能有不同的并发需求,为了避免互相影响可能需要多个线程池,最后导致的结果就是Java的系统里充斥了大量的线程池。

新的思路


从前面的分析我们可以看出,如果线程是一直处于运行状态,我们只需设置和CPU核数相等的线程数即可,这样就可以最大化的利用CPU,并且降低切换成本以及内存使用。但如何做到这一点呢?

陈力就列,不能者止

这句话是说,能干活的代码片段就放在线程里,如果干不了活(需要等待,被阻塞等),就摘下来。通俗的说就是不要占着茅坑不拉屎,如果拉不出来,需要酝酿下,先把茅坑让出来,因为茅坑是稀缺资源。

要做到这点一般有两种方案:

  1. 异步回调方案典型如NodeJS,遇到阻塞的情况,比如网络调用,则注册一个回调方法(其实还包括了一些上下文数据对象)给IO调度器(linux下是libev,调度器在另外的线程里),当前线程就被释放了,去干别的事情了。等数据准备好,调度器会将结果传递给回调方法然后执行,执行其实不在原来发起请求的线程里了,但对用户来说无感知。但这种方式的问题就是很容易遇到callback hell,因为所有的阻塞操作都必须异步,否则系统就卡死了。还有就是异步的方式有点违反人类思维习惯,人类还是习惯同步的方式。

  2. GreenThread/Coroutine/Fiber方案这种方案其实和上面的方案本质上区别不大,关键在于回调上下文的保存以及执行机制。为了解决回调方法带来的难题,这种方案的思路是写代码的时候还是按顺序写,但遇到IO等阻塞调用时,将当前的代码片段暂停,保存上下文,让出当前线程。等IO事件回来,然后再找个线程让当前代码片段恢复上下文继续执行,写代码的时候感觉好像是同步的,仿佛在同一个线程完成的,但实际上系统可能切换了线程,但对程序无感。

GreenThread

  • 用户空间 首先是在用户空间,避免内核态和用户态的切换导致的成本。
  • 由语言或者框架层调度
  • 更小的栈空间允许创建大量实例(百万级别)

几个概念

  • Continuation 这个概念不熟悉FP编程的人可能不太熟悉,不过这里可以简单的顾名思义,可以理解为让我们的程序可以暂停,然后下次调用继续(contine)从上次暂停的地方开始的一种机制。相当于程序调用多了一种入口。
  • Coroutine 是Continuation的一种实现,一般表现为语言层面的组件或者类库。主要提供yield,resume机制。
  • Fiber 和Coroutine其实是一体两面的,主要是从系统层面描述,可以理解成Coroutine运行之后的东西就是Fiber。

Goroutine


Goroutine其实就是前面GreenThread系列解决方案的一种演进和实现。

  • 首先,它内置了Coroutine机制。因为要用户态的调度,必须有可以让代码片段可以暂停/继续的机制。
  • 其次,它内置了一个调度器,实现了Coroutine的多线程并行调度,同时通过对网络等库的封装,对用户屏蔽了调度细节。
  • 最后,提供了Channel机制,用于Goroutine之间通信,实现CSP并发模型(Communicating Sequential Processes)。因为Go的Channel是通过语法关键词提供的,对用户屏蔽了许多细节。其实Go的Channel和Java中的SynchronousQueue是一样的机制,如果有buffer其实就是ArrayBlockQueue。

Goroutine调度器

go-scheduler

这个图一般讲Goroutine调度器的地方都会引用,想要仔细了解的可以看看原博客。这里只说明几点:

  1. M代表系统线程,P代表处理器(核),G代表Goroutine。Go实现了M:N的调度,也就是说线程和Goroutine之间是多对多的关系。这点在许多GreenThread/Coroutine的调度器并没有实现。比如Java1.1版本之前的线程其实是GreenThread(这个词就来源于Java),但由于没实现多对多的调度,也就是没有真正实现并行,发挥不了多核的优势,所以后来改成基于系统内核的Thread实现了。
  2. 某个系统线程如果被阻塞,排列在该线程上的Goroutine会被迁移。当然还有其他机制,比如M空闲了,如果全局队列没有任务,可能会从其他M偷任务执行,相当于一种rebalance机制。这里不再细说,有需要看专门的分析文章。
  3. 具体的实现策略和我们前面分析的机制类似。系统启动时,会启动一个独立的后台线程(不在Goroutine的调度线程池里),启动netpoll的轮询。当有Goroutine发起网络请求时,网络库会将fd(文件描述符)和pollDesc(用于描述netpoll的结构体,包含因为读/写这个fd而阻塞的Goroutine)关联起来,然后调用runtime.gopark方法,挂起当前的Goroutine。当后台的netpoll轮询获取到epoll(linux环境下)的event,会将event中的pollDesc取出来,找到关联的阻塞Goroutine,并进行恢复。

Goroutine是银弹么?

Goroutine很大程度上降低了并发的开发成本,是不是我们所有需要并发的地方直接go func就搞定了呢?

Go通过Goroutine的调度解决了CPU利用率的问题。但遇到其他的瓶颈资源如何处理?比如带锁的共享资源,比如数据库连接等。互联网在线应用场景下,如果每个请求都扔到一个Goroutine里,当资源出现瓶颈的时候,会导致大量的Goroutine阻塞,最后用户请求超时。这时候就需要用Goroutine池来进行控流,同时问题又来了:池子里设置多少个Goroutine合适?

所以这个问题还是没有从更本上解决。

Actor模型


Actor对没接触过这个概念的人可能不太好理解,Actor的概念其实和OO里的对象类似,是一种抽象。面对对象编程对现实的抽象是对象=属性+行为(method),但当使用方调用对象行为(method)的时候,其实占用的是调用方的CPU时间片,是否并发也是由调用方决定的。这个抽象其实和现实世界是有差异的。现实世界更像Actor的抽象,互相都是通过异步消息通信的。比如你对一个美女say hi,美女是否回应,如何回应是由美女自己决定的,运行在美女自己的大脑里,并不会占用发送者的大脑。

所以Actor有以下特征:

  • Processing – actor可以做计算的,不需要占用调用方的CPU时间片,并发策略也是由自己决定。
  • Storage – actor可以保存状态
  • Communication – actor之间可以通过发送消息通讯

Actor遵循以下规则:

  • 发送消息给其他的Actor
  • 创建其他的Actor
  • 接受并处理消息,修改自己的状态

Actor的目标:

  • Actor可独立更新,实现热升级。因为Actor互相之间没有直接的耦合,是相对独立的实体,可能实现热升级。
  • 无缝弥合本地和远程调用 因为Actor使用基于消息的通讯机制,无论是和本地的Actor,还是远程Actor交互,都是通过消息,这样就弥合了本地和远程的差异。
  • 容错 Actor之间的通信是异步的,发送方只管发送,不关心超时以及错误,这些都由框架层和独立的错误处理机制接管。
  • 易扩展,天然分布式 因为Actor的通信机制弥合了本地和远程调用,本地Actor处理不过来的时候,可以在远程节点上启动Actor然后转发消息过去。

Actor的实现:

  • Erlang/OTP Actor模型的标杆,其他的实现基本上都一定程度参照了Erlang的模式。实现了热升级以及分布式。
  • Akka(Scala,Java)基于线程和异步回调模式实现。由于Java中没有Fiber,所以是基于线程的。为了避免线程被阻塞,Akka中所有的阻塞操作都需要异步化。要么是Akka提供的异步框架,要么通过Future-callback机制,转换成回调模式。实现了分布式,但还不支持热升级。
  • Quasar (Java) 为了解决Akka的阻塞回调问题,Quasar通过字节码增强的方式,在Java中实现了Coroutine/Fiber。同时通过ClassLoader的机制实现了热升级。缺点是系统启动的时候要通过javaagent机制进行字节码增强。

Golang CSP VS Actor


二者的格言都是:

Don’t communicate by sharing memory, share memory by communicating

通过消息通信的机制来避免竞态条件,但具体的抽象和实现上有些差异。

  • CSP模型里消息和Channel是主体,处理器是匿名的。
    也就是说发送方需要关心自己的消息类型以及应该写到哪个Channel,但不需要关心谁消费了它,以及有多少个消费者。Channel一般都是类型绑定的,一个Channel只写同一种类型的消息,所以CSP需要支持alt/select机制,同时监听多个Channel。Channel是同步的模式(Golang的Channel支持buffer,支持一定数量的异步),背后的逻辑是发送方非常关心消息是否被处理,CSP要保证每个消息都被正常处理了,没被处理就阻塞着。
  • Actor模型里Actor是主体,Mailbox(类似于CSP的Channel)是透明的。
    也就是说它假定发送方会关心消息发给谁消费了,但不关心消息类型以及通道。所以Mailbox是异步模式,发送者不能假定发送的消息一定被收到和处理。Actor模型必须支持强大的模式匹配机制,因为无论什么类型的消息都会通过同一个通道发送过来,需要通过模式匹配机制做分发。它背后的逻辑是现实世界本来就是异步的,不确定(non-deterministic)的,所以程序也要适应面对不确定的机制编程。自从有了并行之后,原来的确定编程思维模式已经受到了挑战,而Actor直接在模式中蕴含了这点。

从这样看来,CSP的模式比较适合Boss-Worker模式的任务分发机制,它的侵入性没那么强,可以在现有的系统中通过CSP解决某个具体的问题。它并不试图解决通信的超时容错问题,这个还是需要发起方进行处理。同时由于Channel是显式的,虽然可以通过netchan(原来Go提供的netchan机制由于过于复杂,被废弃,在讨论新的netchan)实现远程Channel,但很难做到对使用方透明。而Actor则是一种全新的抽象,使用Actor要面临整个应用架构机制和思维方式的变更。它试图要解决的问题要更广一些,比如容错,比如分布式。但Actor的问题在于以当前的调度效率,哪怕是用Goroutine这样的机制,也很难达到直接方法调用的效率。当前要像OO的『一切皆对象』一样实现一个『一切皆Actor』的语言,效率上肯定有问题。所以折中的方式是在OO的基础上,将系统的某个层面的组件抽象为Actor。

再扯一下Rust


Rust解决并发问题的思路是首先承认现实世界的资源总是有限的,想彻底避免资源共享是很难的,不试图完全避免资源共享,它认为并发的问题不在于资源共享,而在于错误的使用资源共享。比如我们前面提到的,大多数语言定义类型的时候,并不能限制调用方如何使用,只能通过文档或者标记的方式(比如Java中的@ThreadSafe ,@NotThreadSafe annotation)说明是否并发安全,但也只能仅仅做到提示的作用,不能阻止调用方误用。虽然Go提供了-race机制,可以通过运行单元测试的时候带上这个参数来检测竞态条件,但如果你的单元测试并发度不够,覆盖面不到也检测不出来。所以Rust的解决方案就是:

  • 定义类型的时候要明确指定该类型是否是并发安全的
  • 引入了变量的所有权(Ownership)概念 非并发安全的数据结构在多个线程间转移,也不一定就会导致问题,导致问题的是多个线程同时操作,也就是说是因为这个变量的所有权不明确导致的。有了所有权的概念后,变量只能由拥有所有权的作用域代码操作,而变量传递会导致所有权变更,从语言层面限制了竞态条件出现的情况。

有了这机制,Rust可以在编译期而不是运行期对竞态条件做检查和限制。虽然开发的时候增加了心智成本,但降低了调用方以及排查并发问题的心智成本,也是一种有特色的解决方案。

结论

革命尚未成功 同志任需努力

本文带大家一起回顾了并发的问题,和各种解决方案。虽然各家有各家的优势以及使用场景,但并发带来的问题还远远没到解决的程度。所以还需努力,大家也有机会啊。

最后抛个砖 构想:在Goroutine上实现Actor?

  • 分布式 解决了单机效率问题,是不是可以尝试解决下分布式效率问题?
  • 和容器集群融合 当前的自动伸缩方案基本上都是通过监控服务器或者LoadBalancer,设置一个阀值来实现的。类似于我前面提到的喂饭的例子,是基于经验的方案,但如果系统内和外部集群结合,这个事情就可以做的更细致和智能。
  • 自管理 前面的两点最终的目标都是实现一个可以自管理的系统。做过系统运维的同学都知道,我们照顾系统就像照顾孩子一样,时刻要监控系统的各种状态,接受系统的各种报警,然后排查问题,进行紧急处理。孩子有长大的一天,那能不能让系统也自己成长,做到自管理呢?虽然这个目标现在看来还比较远,但我觉得是可以期待的。

qrcode_jolestar_blog2

引用以及扩展阅读


  1. 本文的演讲视频
  2. 本文的演讲pdf
  3. CSP model paper
  4. Actor model paper
  5. Quantifying The Cost of Context Switch
  6. JCSP 在Java中实现CSP模型的库
  7. Overview of Modern Concurrency and Parallelism Concepts
  8. Golang netchan 的讨论
  9. quasar vs akka
  10. golang 官方博客的 concurrency is not parallelism
  11. go scheduler, 文中的调度器图片来源
  12. handling-1-million-requests-per-minute-with-golang 一个用Goroutine的控流实践

FAQ:


高可用架构公众号网友『闯』:有个问题 想请教一下 你说1024个线程需要1G的空间作为栈空间 到时线程和进程的地址空间都是虚拟空间 当你没有真正用到这块虚地址时 是不会把物理内存页映射到虚拟内存上的 也就是说每个线程如果调用没那么深 是不会将所有栈空间关键到内存上 也就是说1024个线程实际不会消耗那么多内存

答: 你说的是对的,java的堆以及stack的内存都是虚拟内存,实际上启动一个线程不会立刻占用那么多内存。但线程是长期运行的,stack增长后,空间并不会被回收,也就是说会逐渐增加到xss的限制。这里只是说明线程的成本。另外即便是空线程(启动后就sleep),据我的测试,1核1G的服务器,启动3万多个线程左右系统就挂掉了(需要先修改系统线程最大数限制,在/proc/sys/kernel/threads-max中),和理想中的百万级别还是有很大差距的。

阿里李纯:从架构师到CTO,成长没有一蹴而就

$
0
0
从程序员成长为架构师,需要几年?从架构师升任CTO,又需要几年?成长没有一蹴而就,鸡汤喝再多,终究是要回到现实,脚踏实地。 编者按

2016年底,已经担任CTO两年多时间的李纯走上飞机,踏上了前往美国硅谷的旅途。他参加的是由极客邦科技举办的中国技术开放日活动,此次活动聚集了国内互联网顶尖的技术人和创业者,他们会拜访硅谷企业,学习和交流经验。

对于李纯来说,此次行程属于重游故地。之前他在eBay/Paypal工作十二年,对这片土地已经熟悉得不能再熟悉,之后他回国,带领阿里人进入B+时代。李纯的每一步的发展看起来都会根据外部环境、机缘巧合的不同而有所不同,但是在技术能力成长的方面,他却一直有一条很清晰的路线。成长是漫长的,充满了点滴细节,没有一蹴而就,但是智慧和经验却可以复用。

阿里李纯

经历互联网黄金时代

我从毕业后就从事计算机软件工作到今天,技术在不断更新,新的商业机会不断出现。我们这一代可以说非常幸运地赶上了这个行业的黄金时代。

我是2002年底在互联网泡沫破裂、发展最低谷时加入的eBay。之前工作主要集中在B2B软件、电信系统和互联网技术领域,在大型公司、硅谷的startup、自己的创业公司都工作过。自我感觉无论在技术、产品、业务还是管理上都有不错的积累,但是面向C类的电商业务还是第一次接触。

我在eBay十二年的工作经历,做了4份跨度蛮大的工作。

头三年在搜索团队,加入eBay就与三个Research Lab的搜素专家、两个测试工程师,在没有业务方,没有产品经理的情况下,用了半年多的时间,开发并上线了eBay的第一代搜索引擎。这个引擎在没有做任何大的架构与技术改造情况下,支撑了eBay后来十几年的业务复杂度及体量的增长,从投入和产出比来讲我想应该是eBay最成功的项目了。

在搜素团队做了一段管理后,被调到技术平台部负责eBay的电商后台技术框架团队,干了三年,主要贡献和积累还是在架构和技术管理层面。2008年自己感到需要些变化,差点离开。

当时eBay要在上海扩大中国研发中心的规模,希望我去负责。就这样在eBay上海研发中心工作了三年,对国际企业海外研发中心的建设与发展积累了各种酸甜苦辣的经验和教训。

最后三年我又回到美国,负责Paypal的支付风控技术团队。主要工作是把通过十几年业务与技术积累,对Paypal做出巨大贡献的传统实时风控系统迁移到新一代的基于大数据的技术体系上。

无论是从工作的成就感还是在过程中学到的东西,我非常珍惜和感谢在eBay/Paypal的十二年。不过也很高兴,看到B类业务的重新兴起,有机会回到自己最感兴趣的B类互联网业务中。

中美互联网的差异

与很多在海外工作的华人一样,我一直有强烈的回国愿望,其间也回来过两次,因为家庭原因又回到美国。现在孩子已经长大,自己可以轻松上阵,所以就全身心回到国内发展了。概括的来讲,尤其是在大型公司,在美国更像是守成,在中国更多仍是创业。渴望挑战和探索未知的人都会被中国互联网发展的速度和前景所吸引。

其实中国与美国创业型公司的地域性差异已经变的越来越小,更多要看公司个体的业务模式、创始人背景及推崇的文化。

目前看,在美国特别是硅谷,技术型的创业公司会比国内多一些。这主要是硅谷有着几十年引领全世界高科技发展的历史,是全球顶尖技术人才最大的汇集地,技术的氛围和人才都比较充分有关。而中国有大量的技术转化为商业的机会,商业上成功的道路相对比较清晰,投入与产出比对投资人来说也更加合理。对有一定规模的公司,两地的差别会相对大一些。

美国的中、大型公司,即使是互联网与高科技领域的新型公司,管理体制与流程都比较成熟,每个人的工作职责和范围也是相对明确和固定的,更加强调每个人发挥自己的专业能力完成本职工作,基本上是一个萝卜一个坑。

在中国,随着互联网在C类电商及个人生活中的普遍应用,产生了一批以BAT为代表的迅速成功的互联网公司,也培养出大量的人才。这些公司可以发展的空间和机会仍然巨大,对有专业深度和广度的专家及leader的需求是非常强烈的。每个人工作的职责及可发挥的空间会更加开放,但同时你的独立思考,推动变化及拿到结果的能力和愿望会变的更为重要。

软件行业和B类技术发展现状

以ERP、CRM和SCM为主的企业软件有着比互联网技术公司更长的历史,对企业用户有着很强的影响力。但是随着以互联网为核心的公司的发展,这些传统软件公司的转型相对较慢,无论从人才及满足客户互联网化需求方面都遇到了很大挑战。

以互联网模式a成长出来的技术公司在服务B类用户时,也需要做适当的调整和改变,特别是如何满足企业级用户在流程的严密性、数据的结构性、需求的专业性等方面的要求。在我看来,目前机会很大,就是看谁能够选择传统软件和互联网技术的优势,充分利用大数据,云计算等新技术为B类用户创造新的价值,提升效率。

1688做为国内最大的B类贸易平台,确实承担了很多差异非常大的业务流程。比如说服务线下零售小店主的零售通业务,我们打造了一套链接快销品供应商,仓储与配送物流提供商,线下小店之间的供应链体系,能够帮助线下小店以最合理的价钱,最快的时间,最有效的工具采购到最适合自己客户的商品。

另外一个极端,在钢铁行业,我们把1688电商产品及供应链能力以SaaS和开发框架的模式输出给由五矿和阿里巴巴合资的第三方公司五阿哥,由他们利用自己在钢铁行业的专业能力与资源,开发了独立的钢铁电商网站。

这两块业务在上层看有着具大差别,而且一个是阿里内部业务,另一个是第三方独立公司,但是所用的底层电商与供应链技术是完全相同的,所有的数据也是完全相通的。所面临的最大挑战是配合业务的节奏,用最合理的产品与技术架构,更快地积累和完善核心供应链能力,同时在不同的行业打造适合不同用户需求的前端产品。

在大量机会和需求下做好取舍,集中经历在重点领域打深打透。即支撑业务当前需要,也要有产品和技术的良性积累。

B+时代,准备好了吗?

记得2000年左右,Gartner Group预言B2B ecommerce会从1999年的1450亿美金在2004年达到72900亿美金。在全球特别是美国出现了大量的B2B创业公司。大家当然知道后来的结果,在过去15年, C类电商蓬勃发展的时期,大量的B类电商公司都销声匿迹。

随着互联网发展到新的阶段,无论从传统企业对互联网及大数据的需求,还是在云计算,互联网底层技术的成熟度来看,目前 B类业务进入互联网化的时机已经相当成熟。做为在B2B领域的从业者,很高兴看到投资人对这个领域的认可。

当然,最后还是要看我们服务B类用户的产品与技术公司是否能够把握时机,为各行各业的企业用户带来真正的价值。另一方面,由于B类业务的复杂性和多样性,这个行业的成功更要依赖不同公司共同的推动与协同,以生态的力量和标准化的模式来完成而不是排他性的竞争。

阿里巴巴 B2B 1.0 是为用户提供的商机与信息匹配,2.0做的是B2B电商与营销, 3.0就是通过供应链服务的方式帮助中小企业实现互联网化的转型。具体做的就是在不同行业中为中小企业提供出一个灵活,方便和低成本的智能互联网供应链平台。与eBay的工作相比,C类电商主要解决的是在大体量用户下的高效与稳定。B类主要挑战是解决业务的复杂性,多样性及多系统的集成。

最初我们通过全球化互联网技术解决信息互通;机器翻译解决语音互通;CRM、流量与联盟技术解决平台买卖家用户积累;商品搜素与推荐解决客户匹配;RFQ与询盘满足商务沟通等手段提升了全球中小企业商机的建立和交流的效率。

后来阿里巴巴B2B平台完成了信息向交易的转化,建立在阿里集团互联网、大数据及电商中台的基础上在现货批发、电商卖家采购、跨境一般贸易等B类交易领域支撑了每年几千亿内贸,上百亿美元跨境B类贸易的平台。

从今年开始,我们开始全面进入B类电商贸易的深水区,也是我们认为能够为B类用户带来互联网化价值的互联网供应链层面。阿里B2B共分为三个阶段:

  • 第一阶段,建立信息网站提供信息和营销服务平台,让买家更加方便的找到所需购买的产品,并和卖家联系;
  • 第二阶段,实现线上化、产品化,支撑业务朝交易、采购平台转型,促进在平台完成业务交易;
  • 第三阶段,以数据驱动、结合供应链能力及平台化建设,建立智能供应链网络平台、为B2B业务国际化贸易铺路,探索与科技合作伙伴建立合作关系,建立B2B技术生态圈。

技术上我们主要解决三个问题。

  1. 符合企业用户特色的基于结构化数据和流程的互联互通;
  2. 基于大数据的全球中小企业信息库与智能供应链;
  3. 基于行业标准的服务、开发与开放生态体系。
技术人的学习路径

过去十几年互联网技术的应用创造了很多快速成功的业务模式,对技术的挑战主要在用快速迭代的模式支持业务的快速发展来取得市场优势,业务成功后对大流量、高并发线上交易平台(OLTP)的稳定性、可用性及高性能的支撑。

随着互联网平台数据的积累和带来的潜在价值,基于大数据相关技术也得到了迅速的发展。B类互联网业务的发展,肯定会推动新技术的出现和成功利用,可能是IoT,可能是区块链。

从工程和架构来看,可能会更加强调产品的抽象和通用性、大型系统之间的集成、标准的制定推广。作为技术人员,一方面要快速学习和了解当前技术发展的趋势和方向,同时要根据自己所在业务场景判断和选择适合的技术手段和整体架构。

每个人的发展都会根据外部环境,机缘巧合有所不同,很难有一个固定模式。不过我可以从技术能力成长的角度分享一下自己的经历。

在工作早期,我的兴趣主要放在了具体技术能力的积累。毕业后第一个工作在北大方正用C/C++在Windows 1.03操作系统上写企业排版软件。后来到美国后第一个工作做EDI软件,主要是在微软技术体系里用C++和DCOM做企业商用软件。

差不多工作了6年多,才感觉自己真正理解了这些技术背后的本质和内涵。同时这段时间,也在工作中找各种机会实践其他技术,比如Unix、CORBA、OLAP及后来的Java技术都做过。这些经验扩展了自己的技术广度,也为后来互联网时期新技术层出不限,自己可以快速学习,做出正确判断打下了一个很好的基础。

做企业商用产品对软件开发的产品化和商业化要求比较高,但后来证明,这个能力即使在非产品业务的电信及互联网公司也是非常有用的。后来也是技术兴趣的驱动,加入了美国当时发展最快的一家电信公司做OSS/BSS系统的架构师,做了很多大型、复杂系统之间的架构设计、系统集成、新技术的用研和引进等工作。自己有机会从宏观的角度去看一些技术和架构,进一步扩展了自己的技术视野。

在互联网发展的吸引下,90年代末从美国中西部来到硅谷一家比较火的互联网startup做总架构师,然后又与几个伙伴一起拿到风投,回国创业做基于互联网技术的B2B与EAI产品。这段时间,开始更加关注技术与业务的关系,如何根据业务、市场和用户的需求来选择适当的技术、产品与团队。

很高兴的是,我那几年一直坚持,即使做架构师、做管理也不要轻易放弃自己动手写程序的能力,甚至在担任自己创业公司CTO、管理近百人的技术团队时,仍然写了当时B2B集成平台中最核心的代码。

再后来就到了eBay/Paypal,有机会学习和实践用合理的架构与技术,工程师文化及管理模式来支撑互联网模式的业务。 今天来到阿里巴巴B2B技术部,我们所面临的业务模式和技术挑战与传统的互联网电商又有着新的不同,而且深深感觉到在B2B业务的下一阶段,技术的作用是至关重要的。

不敢说我们已经完全想清楚了,但是我们团队在不断的探索和尝试如何发力来支持我们的业务。 我感到最幸运的是,在这个领域工作近30年,一直有机会学习新的技术和能力,同时也有新的业务模式出现,可以利用自己过去的经验和知识做一些有意义的事情。

技术和商业仍在日新月异的进步,在互联网领域,更好的时代正在到来。因此对这个领域,对新踏入这个领域的年轻人,我仍然充满信心。

在技术人员成长方面,我感受比较深刻的有三点。

  1. 对新技术发自内心的喜爱和好奇,对自己产品和代码的尊重与自豪,是技术人员从优秀走向杰出的关键因素;
  2. 从用户需求出发找到最适合的技术(即使是非时髦技术)解决问题,比从最时髦技术出发找问题来解决对技术人员的成长帮助更大;
  3. 帮助他人成功,是自己成功的最佳路径。
结语

想象得到,谈起计算机软件和互联网的工作经历,阿里巴巴B2B事业群CTO李纯先生就不经意地流露出他的感恩和幸福感,他说他很幸运,他们这一代赶上了这个行业的黄金时代。

不可否认的是,前十年甚至前二十年,互联网的黄金时代造就了无数互联网时代的弄潮儿,他们在互联网技术领域里指点江山,挥斥方遒。如果,上个世纪初是风云际会、时势造英雄,让多少具有侠义情怀的中国人会怀揣仗剑天涯的梦想。那么,在这个世纪,全世界是一个地球村的当下,他们的梦想已然被拓展,更是在逐步完成着。

作者:李纯

编辑:Cindy

文章出处:InfoQ(订阅号ID:infoqchina)

为了解决弹幕喷子,直播平台Twitch研发了一个深度学习系统

$
0
0

从电子邮件到论坛,从论坛到微博,再从微博到现在的视频直播。当人们在网上发言的速度越来越接近口语的时候,也就给网络喷子带来了越来越多的便利。虽然从人类学会说到现在,还没有什么办法能阻止人类之间互相对骂。但网络空间不比线下,一个人用嘴骂人只能被少数人听到,而在网上却可能影响几千人几万人。在最新一季的南方公园中,甚至认为网络喷子是川普当选和第三次世界大战以及人类登上火星的主要原因。

如何阻止网络喷子成为了各大互联网公司的一个共同的课题,而美国游戏直播平台 Twitch 则为其它同行们提供了一个新鲜的思路。Twitch 今天上线了一个全新的工具 AutoMod,帮助主播们打击活跃在自己聊天室内的喷子。

AutoMod 并不是事后审查,而是将那些疑似有攻击性和歧视性的弹幕直接移入待审核列表由人来决定这些内容是否可以被放出来。根据选项,它可以过滤四类内容,分别是人身攻击、性语言、侵略词语和亵渎词语。

所有的专业喷子都会对任何使用机器过滤他们语言的行为感到不屑,因为他们总是能在第一时间找到突破屏蔽的方法。但是 Twitch 声称其工具远远不是一般的「关键词过滤列表」工作模式,而是采用了深度学习和自然语言识别系统。也就是说 AutoMod 是以整句和语意的方式在识别每一条弹幕中的「恶意」程度。Twitch 的发言人说:「除了不当的词语和短语之外,特定的表情符号的搭配和替换某些词语用的另外一些词语也会在第一时间被机器学会并过滤出来。」

根据 Twitch 的介绍,为了能够让这个拦截系统能够成功的跟上喷子的脚步,Twitch 使用了亚马逊 AWS 的机器学习平台作为后盾。亚马逊在去年到今年卖的火热的人工智能音箱 Echo 里集成的智能助手 Alexa 就是使用这一深度学习平台调教出来的。这让人看到了一丝将喷子从 Twitch 平台彻底驱逐的希望。

AutoMod 目前提供英文版,同时也在测试阿拉伯语,捷克语,法语,德语,意大利语,日语,韩语,波兰语,葡萄牙语,俄语,西班牙语和土耳其语等 12 个语言的测试版本。Twitch 主播可以在设置面板里将其打开。

不过如你所见,博大精深的汉语并不在其中。

Python连接数据库之DB-API

$
0
0

在Python中如果要连接数据库,不管是 MySQLSQL ServerPostgreSQL亦或是SQLite,使用时都是采用游标的方式,所以就不得不学习Python DB-API。

Python所有的数据库接口程序都在一定程度上遵守 Python DB-API 规范。DB-API定义了一系列必须的对象和数据库存取方式,以便为各种底层数据库系统和多种多样的数据库接口程序提供一致的访问接口。由于DB-API 为不同的数据库提供了一致的访问接口, 在不同的数据库之间移植代码成为一件轻松的事情。

Python连接数据库流程:

使用connect创建connection连接

connect 方法生成一个 connect 对象, 我们通过这个对象来访问数据库。符合标准的模块都会实现 connect 方法。connect 函数的参数如下所示:

  • user Username
  • password Password
  • host Hostname
  • database Database name
  • dsn Data source name

数据库连接参数可以以一个 DSN 字符串的形式提供,示例:connect(dsn=’host:MYDB’,user=’root’,password=’ ’)

当然,不同的数据库接口程序可能有些差异,并非都是严格按照规范实现,例如MySQLdb则使用 db 参数而不是规范推荐的 database 参数来表示要访问的数据库:

MySQLdb连接时可用参数

  • host: 数据库主机名.默认是用本地主机
  • user: 数据库登陆名.默认是当前用户
  • passwd: 数据库登陆的秘密.默认为空
  • db: 要使用的数据库名.没有默认值
  • port: MySQL服务使用的TCP端口.默认是3306
  • charset: 数据库编码

psycopg2连接时可用参数:

  • dbname – 数据库名称 (dsn连接模式)
  • database – 数据库名称
  • user – 用户名
  • password – 密码
  • host – 服务器地址 (如果不提供默认连接Unix Socket)
  • port – 连接端口 (默认5432)

其中connect对象又有如下方法:

  • close():关闭此connect对象, 关闭后无法再进行操作,除非再次创建连接
  • commit():提交当前事务,如果是支持事务的数据库执行增删改后没有commit则数据库默认回滚
  • rollback():取消当前事务
  • cursor():创建游标对象

使用cursor创建游标对象

cursor游标对象又有如下属性和方法:

常用方法:

  • close():关闭此游标对象
  • fetchone():得到结果集的下一行
  • fetchmany([size = cursor.arraysize]):得到结果集的下几行
  • fetchall():得到结果集中剩下的所有行
  • excute(sql[, args]):执行一个数据库查询或命令
  • excutemany(sql, args):执行多个数据库查询或命令

常用属性:

  • connection:创建此游标对象的数据库连接
  • arraysize:使用fetchmany()方法一次取出多少条记录,默认为1
  • lastrowid:相当于PHP的last_inset_id()

其他方法:

  • __iter__():创建一个可迭代对象(可选)
  • next():获取结果集的下一行(如果支持迭代的话)
  • nextset():移到下一个结果集(如果支持的话)
  • callproc(func[,args]):调用一个存储过程
  • setinputsizes(sizes):设置输入最大值(必须有,但具体实现是可选的)
  • setoutputsizes(sizes[,col]):设置大列 fetch 的最大缓冲区大小

其他属性:

  • description:返回游标活动状态(包含7个元素的元组):(name, type_code, display_size, internal_size, precision, scale, null_ok)只有 name 和 type_cose 是必需的
  • rowcount:最近一次 execute() 创建或影响的行数
  • messages:游标执行后数据库返回的信息元组(可选)
  • rownumber:当前结果集中游标所在行的索引(起始行号为 0)

DB-API只中的错误定义

错误类的层次关系:

StandardError
|__Warning
|__Error
|__InterfaceError
|__DatabaseError
|__DataError
|__OperationalError
|__IntegrityError
|__InternalError
|__ProgrammingError
|__NotSupportedError

其他参考文档:

The post Python连接数据库之DB-API appeared first on 标点符.

LB 负载均衡的层次结构

$
0
0

作为后端应用的开发者,我们经常开发、调试、测试完我们的应用并发布到生产环境,用户就可以直接访问到我们的应用了。但对于互联网应用,在你的应用和用户之间还隔着一层低调的或厚或薄的负载均衡层软件,它们不显山不露水默默的发挥着重要的作用,以至于我们经常忽略了它们的存在。因为负载均衡层通常不在一般开发人员的问题域内,而且它们一般都是现成且成熟的解决方案,以至于我们习惯性的忽略和认为乏善可陈。其实不然,本文就写写我对负载均衡层次结构的认知和理解。

硬负载

所谓「硬负载」就是采用硬件设备来提供负载均衡。

在七、八年前那时我在做 Java 的企业软件开发,开发出来的企业级 Java 应用程序就部署在像 Weblogic 之类的应用容器中。而这类应用容器软件又跑在 Unix 的小型机上。把硬件和软件一体打包作为企业应用解决方案卖给客户。这类应用部署的方案十分简单,层级也比较浅。为了保证可靠性,使用两套小型机上各部署一个 Weblogic Server,在应用服务前面使用像 F5 之类的硬件负载均衡器,如下图所示。

由于小型机和前面的 F5 负载均衡硬件都比较贵,所以出于可靠性、可维护性和成本的综合考虑,一般应用部署两套跑在两台小型机上,在前面共享一个 F5 做负载均衡。而一般 F5 和小型机这类硬件设备都至少是 5 个 9 的可靠性保障,所以整体的系统可靠性基本有保障。

进入互联网时代后,应用开发拥抱开源,部署使用更廉价的 PC Server 和免费开源的应用容器。负载均衡也逐步从硬负载向软负载变迁,由于互联网应用的海量特性和部署规模的急剧膨胀,前端负载均衡也开始变得丰富起来。

软负载

进入互联网公司后,我们刚开始开发应用时,业务规模小用户量还不大,机器数量也少(<10)。所以一开始的负载均衡的结构也是很简单的,类似硬负载只是把硬件换成了免费的开源软件并跑在可用性是有 3 个 9 的廉价 PC Server 上。

前面一个 LVS 后面跟着几个应用服务,后来为了方便做按域名的分流和适配切流量上线,中间又加了一层 Nginx。

这样就变成了两层软负载结构了,LVS 负责 4 层,Nginx 负责 7 层。 但 Nginx 只负责了单机内多实例的负载均衡,这里主要是因为当时 PC Server 是物理机,CPU 16/32 core,内存 32/64G 不等,为了更充分的利用资源,一台物理机上都部署了多个应用服务实例,而考虑到 Nginx 工作在 7 层的开销远高于 LVS/DR 模式,所以一般在一个 Nginx 后面挂的实例数也不会超过 10 个。

但随着业务发展和用户流量上升,机器规模也在不断扩张,导致一个网段内的 IP 都不够用了,这套负载结构又遇到了横向扩展的瓶颈,因为 LVS/DR 模式下跨不了网段。所以后来又在 LVS 和 Nginx 之间加了一层 HAProxy,负载结构就变成了下面这样。

其实加了 HAProxy 之后,它也是工作在 7 层,这样 Nginx 这层看起来就不是很有必要。但三层的负载结构能支撑更大规模的集群,而原本在 Nginx 层做了一套方便研发切流量上线的运维管理系统,所以牺牲一点性能换取现在的可维护性和将来扩展性,Nginx 这层就一直保留下来了。而且 Nginx 相比 HAProxy 不是纯粹的负载均衡器,它还能提供 cache 功能,对于某些 HTTP 请求实际只走到 Nginx 这层就可以通过缓存命中而返回。

DNS负载

随着业务发展,公司开始了多个 IDC 的建设,考虑到 IDC 级别的容灾,集群开始部署到多个 IDC。跨 IDC 的负载均衡方案可以简单通过 DNS 轮询来实现,但可控性不好。所以我们没有采用这种,而是采用一主加多子域名的方式来基于业务场景实现动态域名调度和负载。主域名下实际是一个动态流量调度器,跨多个 IDC 部署,对于 HTTP 请求基于重定向方式跳子域名,对于 TCP 方式每次建立长连接前请求分配实际连接的子域名,如下图所示。

CDN负载

最后再加上互联网应用必不可少的 CDN 将静态资源请求的负载分流,那么整个负载的层次结构就完整了。

SSL 带来的负载结构变化

随着互联网的普及,安全问题益发严重,原本早期只有银行网银等使用 HTTPS 方式访问,现在电商类网站也开始启用全站 HTTPS 了。引入 SSL 后对负载结构带来了什么影响么?SSL 属于应用层的协议,所以只能在 7 层上来做,而 HAProxy 也是支持 SSL 协议的,所以一种方式是只需简单的让 HAProxy 开启 SSL 支持完成对内解密对外加密的处理。

但 HAProxy 的作者不太赞同这种方案,因为引入 SSL 处理是有额外的性能开销的。那么在承担确定流量的情况下,假设原本需要 M 台 HAProxy,在开启了 SSL 后可能需要 M + N 台 HAProxy。随着流量增长,这种方式的横向扩展成本较高(毕竟 SSL 证书按服务器数量来收费的)。他给出的解决方案是再独立一层 SSL 代理缓存层,像下面这样。

L4 和 L7 之间独立的 SSL 代理缓存层只负责 SSL 协议的处理,把 HTTPS 转换成 HTTP,并检查本地缓存是否命中。若未命中再转发请求到后端的 L7 层应用负载均衡层。这样的好处是每个层次都可以根据流量来独立伸缩,而且 SSL 层显然可以跨多个应用共享,更节省成本。如果按这个思路来重新调整我们前面的负载均衡结构层次,将会演变成下面这样。

其实,这时我觉得应用前面的那层 Nginx 可能就显得多余了点,不是必需的。但如果现实这么演进下来很可能就会有这么一层冗余的东西存在很长一段时间,这就是理想和现实之间的差距吧。

总结

好了,本文到此为止。作为一名后台开发我其实对上面提及的各类开源软件如何配置、调优和管理并不熟悉,这属于运维开发的问题域范畴。但这并不妨碍我去了解我所开发的应用所处的整个环境是怎样的,多了解些你工作领域范围边界外的 What 和 Why,有时也能帮助我们更好的设计和解决自身问题域内的问题,别为自己设限而最终画地为牢。

本来以为负载均衡这个古老的课题已经定型了,在写本文时又看到新闻,在近日举办的第十三届网络系统设计与实现 USENIX 研讨会上,来自 Google 的工程师又分享了其自研的 Maglev 负载均衡器。刚下了论文还没看,回头看了再来写写。

参考

[1] HAProxy Documentation.  HAProxy Management Guide
[2] HAProxy Documentation.  HAProxy Starter Guide
[3] Willy Tarreau.  Making applications scalable with Load Balancing
[4] LVS wiki.  Load balancing
[5] Wikipedia.  Virtual Router Redundancy Protocol
[6] shuming.  LVS 工作模式以及工作原理

相关文章

HTTPS 常见部署问题及解决方案

$
0
0

在最近几年里,我写了很多有关 HTTPS 和 HTTP/2 的文章,涵盖了证书申请、Nginx 编译及配置、性能优化等方方面面。在这些文章的评论中,不少读者提出了各种各样的问题,我的邮箱也经常收到类似的邮件。本文用来罗列其中有代表性、且我知道解决方案的问题。

为了控制篇幅,本文尽量只给出结论和引用链接,不展开讨论,如有疑问或不同意见,欢迎留言讨论。本文会持续更新,欢迎大家贡献自己遇到的问题和解决方案。

实际上,遇到任何有关部署 HTTPS 或 HTTP/2 的问题,都推荐先用 Qualys SSL Labs's SSL Server Test跑个测试,大部分问题都能被诊断出来。

申请 Let's Encrypt 证书时,一直无法验证通过

这类问题一般是因为 Let's Encrypt 无法访问你的服务器,推荐尝试 acme.shDNS 验证模式,一般都能解决。

网站无法访问,提示 ERR_CERTIFICATE_TRANSPARENCY_REQUIRED

使用 Chrome 53 访问使用 Symantec 证书的网站,很可能会出现这个错误提示。这个问题由 Chrome 的某个 Bug 引起,目前最好的解决方案是升级到 Chrome 54+。相关链接:

浏览器提示证书有错误

首先确保网站使用的是合法 CA 签发的有效证书,其次检查 Web Server 配置中证书的完整性(一定要包含站点证书及所有中间证书)。如果缺失了中间证书,部分浏览器能够自动获取但严重影响 TLS 握手性能;部分浏览器直接报证书错误。

如果只有老旧浏览器(例如 IE8 on Windows XP)提示这个错误,多半是因为你的服务器同时部署了使用不同证书的多个 HTTPS 站点,这样,不支持 SNI(Server Name Indication)的浏览器通常会获得错误的证书,从而无法访问。

要解决浏览器不支持 SNI 带来的问题,可以将使用不同证书的 HTTPS 站点部署在不同服务器上;还可以利用 SAN(Subject Alternative Name)机制将多个域名放入同一张证书;当然你也可以直接无视这些老旧浏览器。特别地,使用不支持 SNI 的浏览器访问商业 HTTPS CDN,基本都会因为证书错误而无法使用。

有关 SNI 的更多说明,请看「 关于启用 HTTPS 的一些经验分享(二)」。

启用 HTTP/2 后网站无法访问,提示 ERR_SPDY_INADEQUATE_TRANSPORT_SECURITY

这个问题一般是由于 CipherSuite 配置有误造成的。建议对照「 Mozilla 的推荐配置CloudFlare 使用的配置」等权威配置修改 Nginx 的 ssl_ciphers配置项。

有关这个问题的具体原因,请看「 从启用 HTTP/2 导致网站无法访问说起」。

网站无法访问,提示 ERR_SSL_VERSION_OR_CIPHER_MISMATCH

出现这种错误,通常都是配置了不安全的 SSL 版本或者 CipherSuite —— 例如服务器只支持 SSLv3,或者 CipherSuite 只配置了 RC4 系列,使用 Chrome 访问就会得到这个提示。解决方案跟上一节一样。

还有一种情况会出现这种错误 —— 使用不支持 ECC 的浏览器访问只提供 ECC 证书的网站。例如在 Windows XP 中,使用 ECC 证书的网站只有 Firefox 能访问(Firefox 的 TLS 自己实现,不依赖操作系统);Android 平台中,也需要 Android 4+ 才支持 ECC 证书。如果是这种情况,有一个比较完美的解决方案,请看「 开始使用 ECC 证书」。

在 Nginx 启用 HTTP/2 后,浏览器依然使用 HTTP/1.1

Chrome 51+ 移除了对 NPN 的支持,只支持 ALPN,而浏览器和服务端都支持 NPN 或 ALPN,是用上 HTTP/2 的大前提。换句话说,如果服务端不支持 ALPN,Chrome 51+ 无法使用 HTTP/2。

OpenSSL 1.0.2 才开始支持 ALPN —— 很多主流服务器系统自带的 OpenSSL 都低于这个版本,所以推荐在编译 Web Server 时自己指定 OpenSSL 的位置。

详见「 为什么我们应该尽快支持 ALPN」。

升级到 HTTPS 后,网站部分资源不加载或提示不安全

记住一个原则:HTTPS 网站的所有外链资源(CSS、JS、图片、音频、字体文件、异步接口、表单 action 地址等等)都需要升级为 HTTPS,就不会遇到这个问题了。

详见「 关于启用 HTTPS 的一些经验分享(三)」。

本文链接: https://imququ.com/post/troubleshooting-https.html参与讨论

Docker实践,来自沪江、滴滴、蘑菇街架构师的交流分享

$
0
0
架构师小组交流会:每期选一个时下最热门的技术话题进行实践经验分享。

第一期主题:容器实践。Docker 作为当前最具颠覆性的开源技术之一,其轻量虚拟化、可移植性是CI/CD,DevOps,微服务的重要实现技术。但目前技术还不够成熟,在生产实践中会遇到不少坑。本期参与小组交流的是国内较早采用 Docker 实践的公司。

参与嘉宾:沪江架构师黄凯、滴滴架构师田智伟、蘑菇街架构师张振华、蘑菇街运维架构师向靖、七牛技术总监袁晓沛、扇贝技术总监丁彦

第一轮:自由交流
沪江黄凯:大家好,我是来自沪江的 Java 架构师,我叫黄凯。在加入沪江之前,曾在 HP 和 IBM 的云计算部门担任核心开发和架构职位。对 IaaS、Paas、SaaS,尤其是云存储有较深入的了解。2015 年加入沪江,担任架构师职位,主导的产品有:课件云存储,云转码等等。在这些项目中,我们使用 Mesos 和 Marathon 做 Docker 的编排工具,并开发了一个 Mesos Framework 做云转码的核心框架。

那么我们为什么要使用 Docker,也是机缘巧合。由于我们的服务开始的时候不是特别多,采用的就是一种普通的架构,后来随着服务的增多,发现部署和运维花的时间太长,我们想使用一些新的方式。开始的时候研究过 Openstack,后来觉得 Openstack 慢慢没落,于是我们就选中现在使用的 Docker。我们并不把 Docker 当成 VM 在用,而是使用它的原生的,在 Baremetal 上直接安装 Docker,这样运行效率比在 VM 运行 Docker 要来的快。课件云是由很多微服务组成,不光是一些存储,这种微服务是使用 Docker 部署,就相当于编排,把这些微服务部署上去。转码这一块是使用了 Mesos 框架,和 Docker 没有特别大的关系,但是转码的应用程序,比如说我们现在应用 FFmpeg,这个程序是运行在 Docker 里面的。

为什么要选择 Marathon?第一,我觉得 Mesos+Marathon 非常的容易理解。我们也研究过 Kubernetes 和其他的一些方法,发现从运维和研究的方面来说的话,Kubernetes 实在是太重而且太复杂,后来选择了Marathon。我们现在是内部服务使用,两个部门在使用转码集群,大概是 Baremetal 有 20 台的物理机。除去我们 API 的一些服务,还有一些第三方组件的服务的话,大概是有 400 多个 Docker 容器在跑。

滴滴田智伟:大家好,我是滴滴代驾事业部架构师,代驾事业部是公司最早尝试 Docker 虚拟化的事业部。目前主要方向是业务系统及部分中间件的 Docker 化,我们做的时间也不太长,半年多的时间。线上是因为我们有老的一套发布系统,集成涉及的部门比较多,所以我们基于原来的发布系统完成了预发布环境 Docker 的部署。线下环境基于 Docker+K8s 开发内部的自动化持续交付系统及开发测试环境管理。我们在做开发和测试环境的自动化,另一方面也是做环境管理的,两套环境。对于项目并行的时候发现原来很多不够用,原来很多配置是基于端口绑死的情况。现在基于开发 Kubernetes 的话,网络隔离用了一部分,然后主要是用环境变量这一部分,主要考虑是解决一个配置可以应用到在多个环境的情况,基于这个需求才用它。开发 Kubernetes 基于 Namespace,同一个服务在不同的 Namespace 下,它其实环境变量名可以是相同的,但是IP不同,而这一部分 IP 其实是由开发 Kubernetes 自己去管理的。基于环境变量获取一些配置的话,比如 IP 地址这种,就可以做到拿一份配置可以打出多套环境。

考虑业务的安全性和稳定性,线上基于纯 Docker 的方式在做。我们是基于裸的 Docker 来工作,主要是用资源隔离,没有借助调度框架,也没有自动伸缩。我们是两步走,一步是验证 Docker,其次是做开发 Kubernetes 线下使用和预研。为什么没有考虑 Mesos?刚才跟沪江的同学,我们的考虑是相反的。Mesos 侧重点更专一一点,首先不会有模块的划分,比如 Kubernetes 有 Replication controller ,Namespace 这种概念,而 Mesos 下几乎没有这种概念。我们拿 Kubernetes 主要是做一些编排的功能,而正好开发 Kubernetes 在整个发布和编排上,体系更全面一点。Mesos 最早是做资源管理,基于 Docker 做一个 Framework 接进来的话,它不是专门为编排而生。Kubernetes 首先解决我们的问题是,我们可能不需要加多份配置就可以搭多套不同的环境,它就是基于 Namespace 做一个多租户的概念,会对 Service 做一层隔离,对于动态配置,扩容这一部分暂时我们没用到,确实用到的一些场景比较少。主要是做不同环境的隔离,并没有太多使用编排细节上的东西,动态伸缩之类的目前线下没有太大必要,线上可能会用到。

蘑菇街向靖:大家好,我是子骞,来自蘑菇街的运维架构师。我们接下来会做一个 Paas 平台,想做 Docker 和结合虚拟机以及我们用到公有云产品,做成一个混合云的架构平台。我们现在 Docker 也在用,更多的是当虚拟机用,后面我们想基于 Docker 原生的方式去用,可能会涉及资源调度,服务发现的问题。除了 Docker,我们还会用到公有云,公有云更多是虚拟机的方式提供。出于混合云,想在资源层做一个抽象,对于上层业务来讲它没有关系,它是跑在 Docker 上,还是云主机上,还是 KVM 虚拟机上,那么我想在这上面做一个抽象。另外还有,刚才我也是提问滴滴架构师的问题,配置怎样和代码做隔离,这个也是我考虑的问题。因为我看 Docker 用了环境变量,通过环境变量做一些配置的参数的传递,但是在虚拟机上,特别是在物理机上,通过环境变量的方式,我还在考虑有没有安全的风险,Docker 可能是一个只读的,不会被修改的,但是对于虚拟机以及物理机来说,可能会存在被修改的风险。

蘑菇街张振华:大家好,我叫张振华,花名郭嘉,我是 14 年从思科加入蘑菇街。我们算是国内用 Docker 比较早的,我们一开始用 Docker 是 1.3.2 的版本,当时我们采用集群管理工具还是Openstack,因为当时 Kubernetes 还不是很成熟。当时也走了一些弯路,比如我们把 Docker 当成虚拟机来用,曾经在线上的规模也达到几百台虚拟机几千个容器,但是我们逐步发现不能把 Docker 当成虚拟机来使用,因此我们做了一个转型,从去年开始研究 Kubernetes,现在 Kubernetes 加 Docker 的版本开发完成了,准备逐步上线。

我们为什么选用 Kubernetes?编排工具的选择我们也是做过一番调研的,它们没有谁好谁不好这一说,只能说谁更贴切你的需求。对于我们蘑菇街来说,我们需要解决是资源利用率的问题,和运维的对接,我们需要有预发和线上环境的持续集成持续部署的过程,还有我们需要有对资源的隔离,对部署的快速迭代,包括集群管理,这些方面,我们觉得 Kubernetes 更加适合于我们。

在网络方面,我们研究过现在在开源界比较常用的一些方案,但是我们都觉得不太适合,比较 Fannel,Caico 等等,他们一般用的技术都是 Vxlan,或者是用 BGP。因为我们之前对 Openstack 的网络是比较有经验的,然后我们发现有一个项目,具体名字不记得,Neutron 和 Kubernetes 做一个对接,我们在这个项目的基础上做了 Vlan 的方案,我们的网络没有用 Vxlan 来做,而是选择 Vlan 来做,这样的话一个 Docker 它可以获得跟一个物理理同一个网络平面的 IP,我们的应用程序可以直接对外访问,因为我们内部业务有这个需求选择这个方案。虽然 Docker 内部网络和外部网络是通的,但 Docker 还是独立的一个网段,不需要一层 NAT 的转换。我们直接走二层的,是在交换机走 Chunk,本来物理机交换机的 Access 口,这样的话,一台物理机上面允许跑多个vlan的容器,比如说 A业务和 B业务要走隔离的话,通过网络的 Vlan 走隔离,它们的数据之间不会有干扰。

Load Balance 我们还没有涉及到这一块,Load Balance 我们应该会在 nginx 上做一层。因为据我了解,现在 Kubernetes 这一块 Proxy 还不是很成熟,这上面还存在一些问题,因此还不敢用 Kubernetes 现有提供的服务。服务发现和注册这一块我们还在做开发,这块会和配置管理中心打通。我们内部也有其他团队在做这些功能,所以我们会和内部的中间件团队合作。

七牛云袁晓沛:大家好,我是七牛云数据处理技术总监袁晓沛。我们的数据处理业务包括了图片和视频的实时在线及异步处理。数据处理的业务量比较大,日均请求量达到百亿级。平台采用容器技术的原因是借助容器技术快速部署,启动的特性,数据处理程序可以根据数据处理量快速地弹性伸缩。借助容器技术内核级别的资源隔离和访问控制,每个数据处理程序可以运行在一个私有的环境,不被其它程序所干扰,保证其上运行数据是安全可靠的。而且容器技术是轻量的,它以最小的资源损耗提供资源隔离和访问控制,而资源特别是计算资源在数据处理中是非常宝贵的。

我们在资源调度上采用的是 Mesos,而二层的业务调度框架则是自己自研的。七牛自身拥有近千台的物理机,容器是直接运行的物理机上,可以减少虚拟层对资源的消耗,提高资源的利用率。

在网络上,对于七牛的自定义数据处理服务直接使用的是 Host 模式,而对第三方数据处理服务则使用的是 Bridge 模式,因为这些程序是用户自己部署运行的,并不知道用户是否有开启其他的端口使用,所以使用的是 Bridge 模式,需要对外使用端口的都需要通过 NAT 进行暴露,这样服务内部使用了什么端口并不会对外界环境造成影响,对平台环境做了非常好的安全隔离。我们是使用 Consul 做注册中心,支持跨数据中心的服务发现。我们为什么自研的调度框架,而不用 Marathon。因为 Marathon 不支持跨数据中心的内部服务或外部服务的发现,而七牛有多个数据中心,影响整体的调度,其次如果选用 Marathon 的话,根据我们业务的特点,还是要再做一层对 Marathon 的包装才能作为 Dora 的调度服务,这样模块就会变多,部署运维会复杂。

扇贝丁彦:大家好,我是扇贝的技术总监丁彦,之前在暴走漫画,先后在暴走漫画和扇贝设计和主导了基于 Docker 的微服务架构系统,以及数据收集和分析系统。去年来到扇贝,这里是 Python 的开发环境。后来发现业务增长快,水平扩展一些机器,出现问题需要换个机器等等,都需要非常熟悉业务的少数开发去做。另外公司对预算控制严格,机器基本都是满负荷运作,平时也不可能多开空置的机器,已有的机器还要根据负载情况调整服务分布情况,所以这种切换服务,增删服务的操作还是比较频繁的。因此,我们用了2-3个月的时间将所有的运行环境都切换到 Docker上,这大大提高了我们的运维能力。

Docker 包装有几个好处。
第一个好处是,环境升级非常方便。因为只要pull 一下最新的镜像,启动一个 Container,环境就升级了。而如果直接基于公有云的镜像升级的话就很难,因为一台机器上跑哪些服务其实不一定是固定的,并且之前做的镜像只要有一台机器是还基于它的话,就删除不掉的,镜像数量又有上限。所以docker 非常好地解决了我们的问题。
其次是环境的颗粒度会更小,一台机器上配好几个应用的话,往往配着配着,到最后你就不太能精确地记得上面装的程序或者库是给哪个应用服务的,应用之间如果依赖有版本的冲突也很难调和。你想做些服务的迁移,把负载比较小的放一起,把负载比较大的抽出来,这个时候就非常痛苦,但你如果用 Docker 包装后就非常简单,只要在不同的机器上起不同的 Container,就可以实现这一点。
第三,我们不光用了 Docker,还加入了服务发现,刚刚讨论配置管理这些,我们一并做了。Docker 启动时候,我们自己写了一些工具,可以自定义Docker启动参数,包括配置参数,比如说,一些程序要运行的参数,我们主要用两种方式,一种方式是通过环境变量灌进去,还有一种方式让程序的启动脚本支持参数,然后拼接不同的参数灌进去,最终都是落实到Docker的启动命令上。服务发现是基于 Consul,Docker 的启动命令是从 Consul 里取的。首先 Consul有 HTTP 的 API,我们是自己写的 pip 包,只要 Include 一下这个包就可以了,Docker 的服务启动后会自动注册到 Consul。比如要在负载后加一个服务,只需要找到一台机器,启动对应的container,剩下的事情它自己会到 Consul,注册它的参数地址一系列东西,自动把它加进去。所以这些都是自动化的,如果检测那台机器/服务挂了,Health Check 也会到 Consul 里面更新。该增加机器就增加机器,该下线就下线。总体来说,我们的生产环境全部跑在 Docker 上面的,然后区分有状态和无状态两种,有状态的定死在机器上,无状态的灵活的自由切换。还有一点,如果是有状态的容器要定死在机器上的时候,我们一般来说都会采取冗余的结构,至少保证有两个在运行,一个挂了,保证整体的服务在运行。其次基于 Docker,我们还做了一套数据搜集以及分析的机制。数据搜集是基于日志来搜集的,利用 Docker 的 Log driver,把日志打到 Filter,把结果存在存储服务上。同时监控也是基于日志做的。第三部分非生产环境,比如开发环境跟测试环境都是 Docker 做的,因为我们每一个服务都做了 Image、镜像,用容器方式跑的。通过参数来决定启动方式的,我们可以在开发环境以及测试环境采用不同的参数来启动容器。 通过 Consul 来隔离的,因为 Consul 的服务发现,开发、生产、测试环境在不同的自动发现框架里不会相互影响到。目前机器在 120 台左右,基于云服务。有些基础的东西不需要依赖于 Docker,比如说申请云主机,申请的时候就可以指定它的 CPU 和内存这些服务器资源的配置。所以这部分东西还是属于 Human schedule,不是完全让编排的系统自己决定该怎么样。

编排工具我们现在在研究进一步,我刚来这工作的时候,所有的服务没有一个跑在 Docker 上面的,我现在把它迁进来。现在数据增长,已经有一些编排的瓶颈,现在在做调研,可能基于 Swarm,做自动编排的设计。

第二轮话题交流
主持人:容器多的情况下 Kubernetes 存在性能问题,各位在这方面有没有好的经验?
扇贝丁彦:我们其实也遇到了这个问题,找不到办法所以放弃了 Kubernetes。我们也是用公有云,网络直接依赖公有云的网络,有可能是因为公有云造成的,我没有试过在祼机上试过。

沪江黄凯:Kuberneters 的 Fannel 有一种模式是 Vxlan,它的封装折包是做内核里做的,效率会高一点。容器多就会效率会低是因为,在 Kubernetes 1.2 的时候,走这样的一种模式,数据先到内核态中,然后把数据拉回到用户态,用 Proxy的方式分发给各个容器当中的。其实在Kubernetes 1.3以后,它直接在iptables里设规则,相当于用户数据不用跑到用户态,在内核直接分发出去了,这种效率会非常高。所以可以研究一下Kubernetes新版本。

扇贝丁彦:我们碰到过网络方面的问题。默认的Docker engine的启动参数里面有个iptables,不知道大家有没有定制化过,如果不定制化这个参数,它默认会帮你建iptables的转发规则,并会开启内核的网络追踪的模块。一开始我们没有注意这件事情,当我们的Nginx迁到Docker的时候,Nginx服务瞬间会挂。后来查原因,是因为这些参数会开启网络追踪模块。因为我们的Nginx流量非常大,当时只有3台Linux云主机,分发Http请求的,然后会导致3台Linux宿主机,内存会被刷破,网络会出现堵塞。所以我们关掉了 iptables 参数,并采用Host的网络模型。所以它的容器拿到的IP就是Host的IP。我们一开始也想上一些Kubernetes这些东西,然后发现简单跑个模型根本跑不起来,所以一开始就放弃了这一套东西,直接搞了个裸的Docker。

主持人:关于跨数据中心容器集群的使用,大家有经验么?
沪江黄凯:我们跨数据中心主要是IP分配上的问题,我们现在也在尝试使用Calico,如果Host网络是通的话,那么它的内部网络也就通了,可以自由划Vlan,这样你就可以解决跨Data center的问题。还有一个问题就在跨Data center时,服务注册与发现的问题。这个问题也困扰我们很久了,我们现在使用Consul做服务注册与发现。虽然Consul它是官方支持跨Data center,但是我们在使用当中的话会发现注册的IP,在另外一个注册中心,它会发现的比较慢,甚至有时候出现IP冲突的时候。
我们的做法是把 Host 的 IP 地址直接用 Environment 的形式注到 Docker 镜像内部,接下 来 Docker 镜像要注册,它就会读取 app 的 IP,然后发送给 Consul,只要保证 Host 的 IP 和 Docker内部容器的 IP 能够互通的就行了。如果不能通的话,比如说完全和 Host IP 隔离,那么起码有几台机器要暴露出去,又比如说,Consul 它本身自己要暴露出去才能访问到。Host 的 IP 是容器启动之后注进去的,启动命令中把 Host 的 IP 地址加在 -e 的后面,容器在启动之后,它的环境就会有这么一个 IP。我们用 Mesos 就没这个问题,但是用 Kubernetes 就有这个问题。Mesos 会自动帮你把这些东西注入容器中去。

滴滴田智伟:其实 Kubernetes 本身也是可以解决这个问题,我们现在在做线下持续交付的时候。定义完 Service 之后,容器会同一个 Namespace 默认加一个系统环境变量。

沪江黄凯:我们试过,在 Pod 启动之后,Pod 里容器想访问 host 的 IP 地址,是没有办法做到的。

蘑菇街张振华:因为我们之前也遇到这个问题,然后我们业务方,他们可能有一些程序会获取本机 IP 地址,如果是内部的 IP 地址,他们程序可能会出现问题,于是我们当时没有用 Docker 默认的网络,而是采用 Vlan。

主持人:我们提到好多 Mesos、Kubernetes、网络,发现没有提自动伸缩,有没有项目涉及到容器的自动伸缩?
沪江黄凯:我们沪江是基于 Mesos+Marathon 做了自己的一个服务,它这个服务是干嘛的呢,就是监测,不停的监测每一个 Docker 的 CPU 和内存的利用率,一旦超过百分之多少以后,就向Marathon发一个命令,说我要扩容,它还可以支持时间点,比如 15 分钟监测一次,如果在 15 分钟发现它超过阈值了,就马上扩容出来,但是缩的话,不是适用于频繁监控,如果小于 20% 的话就会缩,一旦缩的话会影响线上用户的请求。怎么办呢?我们在缩的时候可以规定它的时间点,比如半夜里2-3点,访问量少于多少点时候把它缩掉。我们监测的是 Docker 内部的 CPU 的使用率。就是监测一个服务,它可以监控所有同一服务的 Container,比如一个服务有100个容器,那么这一百多个 CPU 利用率加起来除于一百,相当于平均的利用率。如果平均利用率超过 80%了,那说明这个集群到了扩展程度了,它会以一种比例来扩展。针对单个容器,可以设置内存的限制。我们给每一个容器呢,比如它只能用 4 个 CPU,只能用 8G 的内存,或者更小一点的内存,这些都设好,设好之后它自动扩展相同规格的容器。这么做是因为 Cgroup 有个问题,当利用率到达了启动的限制,Cgroup 会把这个容器 kill 掉。这个是不可理喻的问题,所以我们想到用 Load scale 来扩容,不让他直接死掉。

滴滴田志伟:关于自动扩容,我们线下的时候遇到一个问题,我们最早的时候是用腾讯的公有云,它限制了 NET 的模块,导致我们最初用 Cgroup 的方案去做,绑定端口。内部使用所有应用,端口是要做分配的,要不然出现端口冲突。然后遇到问题是,在这种情况下,如果要做动态扩容的话,它每次先创建一个,再杀掉一个,导致每次起来的时候就起不来了,因为端口的问题。服务启动的时候端口是随机,会出现冲突问题,因为用的是 Host 的模式。

主持人:关于自动伸缩为什么没有考虑到请求数?因为如果内存占用率如果超过一定预支,那么请求数也可能超过一定预支了。把单个容器所处理的请求数给限定了,那么它内存自然不会超,然后也不会被干掉。
沪江黄凯:我个人认为,第一,请求数很难测,你不知道请求数到多少时要扩容,还不如根据 CPU 到 80%,或者 90% 来的直观。我们的 API 也是根据 CPU 来算的。你真正是高并发的 API 的话,我也测过,最后我们能够监测到的,其实还是 CPU 和内存。

扇贝丁彦:我们扩容是根据响应时间,跟请求数类似,请求数定指标不太好定,我们是根据响应时间,比如平时的响应时间是 50 毫秒,当响应时间是 300 毫秒的时候就要扩容了。

主持人:大家对于容器有状态无状态有没有遇到什么问题?大家一般用容器的本地磁盘还是共享磁盘呢?
沪江黄凯:关于存储,我们是有一些研究的。现在容器存储问题分为两种,Kubernetes 官方支持一种理念,任何一种存储都是一个 Volume。Volume 先于 Docker 存在的,而不是 Docker 启动之后再挂载 Volume。不管是网络存储还是本地存储,全部以卷的形式,挂载在 Pod 里面或者是宿主机上,以 Driver mapper 来驱动这个 Volume,来读到你所要的内容。
还有一种情况,就是 Docker 公司主导的存储模型,任何的存储都是一种驱动。如果你想用 NFS 或者如 Ceph 这样分布式存储的话,让 Ceph 开发 Docker 的驱动,Docker run 的时候指定存储的驱动,Docker storage driver这种方式,外部的存储在容器内部它展现形式可以是目录,也可以是挂载卷、块的形式。如果用块挂载到容器中,这个容器自己格式化它,或直接读取它都是可以的。它只不过它是相当于用了一个 Driver 的形式,把你的容器和分布式存储建立一个连接而已。对于容器,如果原本绑定块或 Volume,容器出现故障的话,直接把容器杀掉,再启动挂在同样一个 块或Volume就解决了。优点是直接读取,而不是通过再转一层,效率比较高一点。所有存储都是Volume 的形式理解度比较高一点,所以我们还是赞同于用 Volume 的形式。
有状态的容器。我知道k8s的新的计划,如果你没有用 Kubernetes 最新版本的话,一般来说我们都是容器启动在固定Host 上,下次启动还是在这台 Host 上,它的存储它的内存,包括一些 log,全部是在这台 Host 上。还有一种是用最新的版本,有个 PetSet的新kind,Kubernetes 它自己会记录 Pod 在什么 Host 上启动过,不用自己去指定一定要在某一台 Host 上启动,这种方法比较智能化,但是不是特别稳定的一种方法,因为它是刚刚开发出来的新功能。

主持人:数据多副本,假设有一个节点故障的话,是建议它直接把原来的副本重新绑定还是重新起一个新的实例,通过分布式数据的迁移呢?
沪江黄凯:我个人认为还是在同一台机器上起一个新的实例,不要让它做数据迁移,因为数据迁移会占用很多资源。而且如果你的想法是说,所有的分布式的存储只是以 Volume 的形式挂载在宿主同上,这也就没什么问题了。因为存储和 Docker 是完全分开来的。如果只有一个 Volume,存储的可靠性会得不到保障,所以在 Kubernetes 新版本当中,它会建立一个Volume的kind,也相当于建立 RC kind一样,是一个 Pod,那这样由 Kubernetes 来保障这个 Volume 的高可用。

已有 0人发表留言,猛击->> 这里<<-参与讨论


ITeye推荐




如何开发一款堪比APP的微信小程序(腾讯内部团队分享)

$
0
0
一夜之间,微信小程序刷爆了行业网站和朋友圈,小程序真的能如张小龙所说让用户“即用即走”吗?

其功能能和动辄几十兆安装文件的APP相比吗?

开发小程序,是不是意味着移动应用开发的一次推倒重来,企业的运营成本会不会因此增加?

近日,笔者参加了一次腾讯自选股介绍小程序开发过程的内部沙龙,自选股小程序产品经理Poppy和首席开发工程师小K的一番海聊,从开发技术和行业走势两个方面为我们揭开了小程序的秘密。

引用
本文来之 「H5程序俱乐部」公众号
「H5程序俱乐部」是一个专注微信小程序学习交流,相关外包/招聘需求信息发布的微信公众号




今年7月,腾讯自选股团队接到微信的邀请,做一个Web+的应用测试。当时他们还不知道,这就是微信小程序的首批开发内测。而当时,其实连“小程序”这个名字也还没有确定。

三个月后,“腾讯自选股”成为第一个开发成功的微信小程序。相比于原来身量庞大的APP,它无需用户下载、安装,即可在微信内一键即达,并可实现盯盘、看盘、在线交易等APP的核心功能。自选股的用户无需离开微信,就可以边聊天边看盘乃至进行股票交易,与身处大户室的感受几乎无异。

这三个月,是小程序拨云见日、从无到有的三个月,自选股团队为探索开发一款完美的小程序奏响了先声。

揭秘一:在内容上有所取舍,更符合小程序所适配的场景

小程序的特点在于“轻”。自选股小程序的安装包只有900K,轻装的实现,首先来自于取舍的理念。

“小程序不是对APP的原样照搬。”Poppy介绍说,自选股小程序对APP中深度、专业的资讯服务做了取舍,只收录了支持个股的部分资讯。因为在微信里,用户可以通过订阅号、服务号等多种渠道收看资讯,小程序不必再做重复建设,而是主要适配交易与交流同步的应用场景。

小程序开发团队对自选股做了重新设计。围绕用户的核心需求,在自选股小程序的页面上,最终只保留了自选、行情和设置三个页卡,轻巧而清晰。

揭秘二:采用WebSocket协议实现数据实时性

显示实时行情是股票应用核心功能之一,但实时数据传输最为占用网络资源,也影响到小程序应用的流畅性和用户体验。

自选股小程序采用WebSocket完美解决了这个问题。小K说,以往数据更新多采用轮询机制,即客户端按照一定的周期频率发起数据请求,对网络资源的占用较大。自选股小程序的解决方案是采用WebSocket,当服务器有数据更新时主动PUSH,从而降低了无效的网络传输,使数据的实时性更强。

揭秘三:数据缓存加速数据呈现

自选股小程序通过数据缓存,加速页面的数据呈现。本地缓存文件最大可以达到10M。

10M缓存量是根据自选股用户的偏好来设置的。数据显示,80%用户的自选股不超过20支,一只股票的缓存数据大约300K,10M的缓存空间足够缓存30支以上的股票。这对于绝大多数用户来说已经足够了,而且实现了用少量数据支持页面的流畅呈现。




揭秘四:响应式绘图完美适配不同机型

Canvas在使用前需要设置大小以便占位。而在小程序里面,目前Canvas不支持RPX的方式,Canvas需要动态添加图形的宽高数据。

为了更快渲染Canvas,且不出现闪屏效果,自选股小程序在启动程序时即在后台记录用户所用设备的屏幕尺寸。进入Canvas绘制页时在OnLoad方法中计算Canvas大小并设置画布。这完美地解决了在小程序中实现响应式绘图的问题。

揭秘五:简洁的UI平衡美观与实用

自选股小程序的UI十分简洁。与iOS开发完全不同,从UI到整体前端处理大部分都采用CSS做渲染。对个别需要用到PNG的设计元素,对PNG做无损压缩。这让小程序在页面的美观与程序的轻灵之间找到了平衡。

揭秘六:人性化优化很重要

对于股票应用来说,任何一支股票的异动都需要马上看到变化,否则对于用户来说是致命的缺陷。开发团队认识到,小程序之轻绝不能以牺牲核心功能和用户体验为代价。因此,在自选股团队的建议下,微信团队专门开发了小程序动画支持功能。现在,自选股小程序中,股票一旦发生价格变化会自动闪烁,提醒用户重点关注,让小程序的功能完全不输APP。

揭秘七:人人可做小程序

“自选股小程序代表了目前微信小程序开发的标杆和极限。”Poppy对此十分自信。股票类应用本身是比较复杂的移动应用。自选股小程序开发成功,相当于厘定了小程序开发的边界。只要你的应用不比自选股更复杂,就一定能实现小程序应用。

微信小程序作为一个轻应用,它的优势之一在于使开发变得相对容易。自选股小程序的研发之所以走过了三个月时间,是因为他们作为微信小程序应用开发的拓荒者,和微信小程序研发团队共同经历了开发、完善底层技术的全过程,甚至客观上成为小程序开发标准的参照。

小程序到底该有多大才算“轻”,在小程序开发之初,微信团队对此也没有概念。当得知自选股小程序最终完成的安装包只有900 K后,他们将小程序安装包体量的上限定在了1024K。

揭秘八:对流量入口的争夺将再次开启

小程序规避了过去加载应用必需的扫码、下载、安装等繁复过程,更容易触发用户应用,更方便商家留存用户信息。月活量已经超过八亿用户的微信已经成为了一种实实在在的生活方式,其中集合了丰富的生活场景入口。微信小程序的出现,可以帮助O2O行业获取更多用户,是个绝对的利好。Poppy认为:“基本上,服务类的商家都适合做小程序。”

小K认为,相对APP,小程序的开发更为容易,只需一套代码就适配所有机型,视应用复杂程度,最多五六个人一个月就可以搭建出来,成本优势十分明显。

有人说,互联网APP创业的风口正在关闭。但小程序所倡导的基于微信环境的轻型应用的理念,为已陷入增速减缓的互联网移动应用带来一股清流,为服务类APP的转型发展带来了启发。

已有 0人发表留言,猛击->> 这里<<-参与讨论


ITeye推荐



快速开发平台,SpringBlade 稳定版发布

$
0
0

经过三个月的完善与修复,经过几个项目的检验,SpringBlade稳定版终于发布啦!

SpringBlade是基于多个优秀的开源项目,高度整合封装而成的快速开发平台。

鸣谢

1.JFinal
2.eova
3.hutool
4.beetl
5.beetlsql
6.dreamlu
7.kisso
8.spring-shiro-training

内置功能

  • 用户管理

  • 角色管理

  • 菜单管理

  • 字典管理

  • 部门管理

  • 附件管理

  • 参数管理

  • 连接池监视

  • 日志管理

  • 代码生成


技术选型
1、后端
* 核心框架:Spring Framework
* 安全框架:Apache Shiro
* 视图框架:Spring MVC
* 服务端验证:Blade Validator
* 任务调度:Spring Task
* 持久层框架:beetlsql
* 模板引擎:beetl
* 数据库连接池:Alibaba Druid
* 缓存框架:Ehcache
* 日志管理:SLF4J、LOGBACKUP
* 工具类:Apache Commons、FastJson、EASYPOI、BladeToolBox


2、前端
* JS框架:jQuery
* CSS框架:Twitter Bootstrap
* 客户端验证:JQuery-html5Validate
* 富文本:KindEcitor
* 数据表格:jqGrid
* 树结构控件:jQuery zTree
* 弹出层:Layer
* 日期控件: LayDate
* 图表控件:echarts

代码示例

实体类

@Table(name = "notice")
@BindID(name = "id")
@SuppressWarnings("serial")
public class Notice extends BaseModel {
    private String id;
    private Integer creater;
    private String content;
    private String title;
    private Date createTime;

    @AutoID
    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }   
    .....................

}

新增

    @ResponseBody
    @RequestMapping(KEY_SAVE)
    public AjaxResult save() {
        Notice notice = mapping(PREFIX, Notice.class);
        boolean temp = Blade.create(Notice.class).save(notice);
        if (temp) {
            return success(SAVE_SUCCESS_MSG);
        } else {
            return error(SAVE_FAIL_MSG);
        }
    }

修改

    @ResponseBody
    @RequestMapping(KEY_UPDATE)
    public AjaxResult update() {
        Notice notice = mapping(PREFIX, Notice.class);
        boolean temp = Blade.create(Notice.class).update(notice);
        if (temp) {
            return success(UPDATE_SUCCESS_MSG);
        } else {
            return error(UPDATE_FAIL_MSG);
        }
    }

删除

    @ResponseBody
    @RequestMapping(KEY_REMOVE)
    public AjaxResult remove(@RequestParam String ids) {
        int cnt = Blade.create(Notice.class).deleteByIds(ids);
        if (cnt > 0) {
            return success(DEL_SUCCESS_MSG);
        } else {
            return error(DEL_FAIL_MSG);
        }
    }

自定义sql查询

 List<Map> list = Db.selectList("select * form news where title = #{title}", Paras.create().set("title", "标题测试"));
 String editor = Db.init("otherDb").queryStr("select editor form news where newsId = #{newsId}", Paras.create().set("newsId", 123));

根据md文件执行修改操作

 int cnt = Md.update("news.update", Paras.create().set("title", "标题测试").set("id", "1"));

根据条件修改

 boolean temp = Blade.create(News.class).updateBy("editor = #{editor}", "title = #{title}", Paras.create().set("title", "测试标题").set("editor", "编辑一"));

根据条件删除

    String ids = "1,2,3,4,5";
    String[] idArr = ids.split(",");
    int cnt = Blade.create(News.class).deleteBy("status in (#{join(ids)})", Paras.create().set("ids", idArr));

通用service

   public interface NoticeService extends IService<Notice> {

    }


    @Service
    public class NoticeServiceImpl extends BaseService<Notice> implements NoticeService {

    }


    @Autowired
    NoticeService service;

    @ResponseBody
    @RequestMapping(KEY_SAVE)
    public AjaxResult save() {
        Notice notice = mapping(PREFIX, Notice.class);
        boolean temp = service.save(notice);
        if (temp) {
            return success(SAVE_SUCCESS_MSG);
        } else {
            return error(SAVE_FAIL_MSG);
        }
    }

分页封装

    @ResponseBody
    @RequestMapping(KEY_LIST)
    public Object list() {
        Object grid = paginate(LIST_SOURCE, new IQuery() {

            @Override
            public void queryBefore(AopContext ac) {
                if (ShiroKit.lacksRole(ConstShiro.ADMINISTRATOR)) {
                    String condition = "and creater = #{creater}";
                    ac.setCondition(condition);
                    ac.getParam().put("creater", ShiroKit.getUser().getId());
                }
            }

            @Override
            public void queryAfter(AopContext ac) {
                @SuppressWarnings("unchecked")
                BladePage<Map<String, Object>> page = (BladePage<Map<String, Object>>) ac.getObject();
                List<Map<String, Object>> list = page.getRows();
                for (Map<String, Object> map : list) {
                    map.put("createrName", SysCache.getDictName(102, map.get("creater")));
                }
            }
        });

        return grid;
    }

后台界面


注:前端UI为ACE-ADMIN,如果商用请购买 ACE-ADMIN的授权。

git地址: http://git.oschina.net/smallc/SpringBlade

Google 是如何做负载均衡的?

$
0
0

Google 使用的技术一般都自带光环,吸引程序员的注意,基础设施方面的东西就更是如此,年初 Google 发布了篇论文介绍内部的负载均衡器的实现,让我们有机会一睹可能是全球最好的负载均衡器。

通常情况下的负载均衡要在灵活性和性能之间做权衡,用户态软件层面有 Haproxy 和 Nginx 这样的老牌负载均衡软件,他们一般配置和使用起来都比较容易,但是由于需要数据包从网卡到内核再到软件一层层向上处理,再一层层向下转发,堆栈比较深单机性能通常都比较一般。为了提高单机性能,减少堆栈层级就有了 Linux 里华人之光的 LVS,工作在内核层的负载均衡器,性能有着数量级的提高,然而配置起来相对也比较复杂而且对网络条件要求也有特殊要求。那 Google 有什么秘密的配方来达到高性能呢?

一般来说负载均衡器本身就是后端服务横向扩展的一个接入点,对于一般站点一个负载均衡器就够了,然而应对 Google 这种级别的流量,负载均衡器本身也要能横向扩展,还要处理负载均衡器的高可用,Google 又是如何做到的呢?

以我们访问 www.google.com 为例,第一步 DNS 服务器会根据请求的位置返回一个离请求地理位置最近的 VIP 地址,先在 DNS 这一层做一个横向扩展。接下来请求达到 VIP 对应的路由器,路由器通过 ECMP 协议,可以将请求平均分配到下面对等的多个负载均衡器上,这样在路由器这一层做了个负载均衡,让后面的负载均衡器也实现了横向扩展。再往下是一个类似于 LVS 中 DR 模式的分发,负载均衡器将请求包转发给服务器同时将源地址改为客户请求时的地址,服务器响应时将响应包的源地址改为 VIP 的地址直接打给路由器而不通过负载均衡器来降低负载均衡器压力。流程图如下

对了,Google 的这个负载均衡器叫 Maglev,磁悬浮列车的意思。自然是要做到极致的性能,只看流程似乎和 LVS 中 DR 模式很类似,但内部就完全不一样了。

简单的说虽然 LVS 已经做到 Linux 内核里了,但是在 Google 看来 Linux 是性能的瓶颈,到 LVS 之前还要经过完整的 TCP/IP 协议栈以及内核的一系列 filter 模块,而这些对于转发来说是没有必要的。于是 Google 的做法就是简单粗暴的绕过内核,把 Maglev 直接架在网卡上对接网卡的输入和输出队列,来一个数据包也不需要完整的 TCP/IP 协议栈的解析,进来的包只要分析前几个字节,拿出源地址,源端口,目标地址,目标端口和协议号这个五元组对于转发来说就已经足够了。剩下的诸如 payload,序列号之类的东西统统不关心直接塞到网卡输出口给后面就行了。

前几天听美团的介绍他们的负载均衡器是用的类似的思路用 DPDK 直接在网卡上编写应用,性能相对 LVS 就有数倍的提升。看 Maglev 的实现为了榨干性能是直接写在网卡上的,都没有 DPDK 之类的封装。绕过内核就可以自己分配内存管理内存就可以进一步的压榨性能。论文中可以看到 Maglev 是直接和网卡共享内存的,这样就不需要将数据包再从网卡进行一次复制到负载均衡器中,也不需要把数据包再从负载均衡器复制到网卡,网卡入口队列,负载均衡器,网卡出口队列共享一个数据池空间,三个指针不断的移动处理数据包,可谓是在内存这里做到了极致。

当然诸如 CPU 绑定,每个 CPU 专职处理一个线程来避免 cache miss,memory contention 这种常规优化也是都有的。最终的效果就是处理一个数据包平均需要 350ns,而性能发生抖动的情况一般是由于网卡发数据包是批量的或者要等待一个 timer 的中断,而这个中断的时间是 50us 所以当流量小的时候这个延迟可能会达到 50us。(我觉得 Google 这么写其实是在炫耀自己性能好,瓶颈在网卡刷新速度上,而不在负载均衡器上)

通常的负载均衡器都是一个单点,而 Maglev 是一个集群,集群就会碰到很多的问题。严格来说负载均衡器不能算是一个无状态的服务,因为 TCP 连接本身是有状态的,一组会话内的请求包必须转发到相同的后端服务器,不然服务器端的 TCP 会话就乱套了。对于单点的负载均衡器来说很好解决,记录个转发表里面有每个数据包的五元组和它第一转发到哪台机器,来一个新的数据包查这个表就知道给谁了。而像 Maglev 这样的集群数据包是通过路由器 ECMP 随机分发的,第一个数据包是这个 Maglev node 处理,下一个就不知道去哪个 Maglev node 了。而且集群就会涉及滚动式的更新和随机的故障,这样本机的转发表也就很可能会丢失。

之前听美团的介绍,他们的做法是在多台机器之间做内存的同步每次更新都要进行一次同步来保证所有机器转发表的一致。而 Google 一帮人不愧是搞研究出身的,直接就上了一致性哈希这个大杀器。这样的话可以直接通过五元组散列到后端的一台固定服务器,这样硬生生的把有状态服务做成了无状态,如此一来 Maglev 层面个就可以随意的更新,上线下线了。顺便的一个好处就是后端增加下线服务器都只会影响到当前这台机器所处理的连接不会造成所有连接的 rehash。当然只用一个普通的一致性哈希算法也没啥意思,Google 为了自己的需求专门写了个 Maglev Hashing

论文里还介绍了很多负载均衡器运维方面的经验以及设计的过程和经验,还说了下一些新的发展方向,感兴趣的可以看一下 论文原文,当然你要翻下墙(逃

远程调试服务器的tcp流

$
0
0

  如果只是一个http业务,一般是不需要调试其TCP流的;但是现在我正在处理一个基于TCP长连接的协议,有时候有任何问题,通过TCP流都可以帮助我调试服务。

  但是这只是本地开发时常见的情况,如果要调试测试服务器乃至生产服务器接受的数据流是否正常呢?当然可以在服务器运行tcpdump,比如 tcpdump -i eth0 tcp port 抓包端口号 -w /tmp/debug.cap,然后将debug.cap从服务器scp到本地来,用wireshark详细研究。

  但是有时候调试,服务正常与否跟相应时间什么的也有关系,这种事后研究的方式就不方便了,可以直接ssh服务器,通过tcpdump输出到管道,然后管道这边通过wireshark去抓包分析,省去了scp的麻烦,也能实时调试了。

  可以使用命令 ssh fedSDE "sudo tcpdump -s 0 -U -n -i eth0 port 抓包端口号 -w -" | wireshark -k -i -来轻松做到这点。

  不过有时候会有异常,“sudo:抱歉,您必须拥有一个终端来执行 sudo”,则需要使用管理员修改/etc/sudoers,把 Defaults requiretty这一行注释掉就可以了。

从此妈妈再也不用担心我调试服务器上的流量啦!

这一年地球上发生了什么?《国家地理》杂志评选出「2016年度最佳影像」

$
0
0

还有18天,2016年就要结束咯。《国家地理》杂志从91位摄影师、107个故事、229万张摄影作品中选出了52张 “2016年度最佳摄影”

这些摄影作品来自地球上的各个角落:在莫斯科实录“网红”拍照过程,在阿拉斯加偶遇又萌又急人的“熊堵”,在南非记录下被偷猎者残忍射杀的犀牛,在塞舌尔看黑鳍礁鲨懒洋洋的集体“赖床”,在挪威俯拍冷蓝色海面上温暖的船只,在NASA中心观摩充满超现实感的“样衣试样”,或是在中国喀什的火车里,留意小孩心中的温暖……

01

Kirill Vselensky站在莫斯科某幢高楼的屋檐边缘,而Dima Balashov正在拍他。这两个24岁的年轻人是Instagram上的红人,他们去各种屋顶上以惊险的方式拍照,被称为rooftoppers(屋顶人)。


Photo by GERD LUDWIG

 

02

夜晚的暴风雨照亮了内布拉斯加州伍德河附近的天空,大约有413000只沙丘鹤飞来这里,栖息在普拉特河的浅滩上。


Photo by RANDY OLSON

 

03

一名潜水员正与一条巴哈马鼬鲨亲密接触。别太担心,实际情况并没有看上去那么危险哦——鼬鲨一般是不会攻击稳定在视线中的物体的,相反,它们会对突然出现的一切充满突袭的猎捕欲。


Photo by BRIAN SKERRY

 

04

晔晔是一只16岁的大熊猫,它正在四川卧龙大熊猫自然保护区休息。


Photo by AMI VITALE

 

05

在印度的孙德尔本斯,几个眼科护理人员正在使用测试镜架为居民进行眼科检查。他们希望可以通过这样的普及检查,使得印度目前超过800万的失明人群基数有所下降。


Photo by BRENT STIRTON

 

06

被寄生无花果树的果实诱惑着,这只婆罗洲猩猩爬上了30米的树冠。一只雄性婆罗洲猩猩的体重可以达到90公斤,它们是世界上最大的树栖动物。


Photo by TIM LAMAN

 

07

秘鲁马努国家公园里,一个马奇健格族(当地原住民)女孩正在河里嬉戏,在她的头发上趴着的是她的宠物——一只鞍背柽柳猴。


Photo by CHARLIE HAMILTON JAMES

 

08

拉马迪的瓦砾中的一个难民家庭。拉马迪是伊拉克的一个城市,因为恐怖袭击,这里到处残垣断瓦,生灵涂炭。


Photo by MOISES SAMAN

 

09

美国黄石地区的一些地方可能比一个世纪前更“野”——灰熊们的活动范围越来越大,比如这一只,正在从野牛尸体上赶开正在啃食腐肉的乌鸦——黄石公园的工作人员们故意把野牛的尸体搬离路面,以确保这样的“抢食组合”远离游客们的旅行路线。


Photo by CHARLIE HAMILTON JAMES

 

10

傍晚的暮光沐浴着希腊特尔斐的雅典娜卫城神殿。当年的朝圣者有可能是先在这里献祭,然后前往附近的阿波罗神庙求取德尔斐神谕的。


Photo by VINCENT J. MUSI AT ARCHAEOLOGICAL SITE OF DELPHI

 

11

一只非洲鳞片白腹穿山甲宝宝正扒着妈妈的背“搭便车”。它们生活在佛罗里达东海岸圣奥古斯汀的一个非营利的穿山甲保护区里。


Photo by JOEL SARTORE

 

12

在密歇根州的弗林特,因自来水受到污染,Julie、Antonio和India Abram兄妹几个刚从消防局领到了他们今天的瓶装水补给。


Photo by WAYNE LAWRENCE

 

13

穴居象龟们在一棵小小树下争抢庇荫所——如果太长时间被暴晒,如此强烈的阳光和如此荒芜的土地会令象龟们在自己的壳里……被煮熟。


Photo by THOMAS PESCHAK

 

14

一只被猎捕的公麋鹿和它珍贵的鹿角被搭在一只骡子的背上驮着——这可是一种很复古的运输方式呢。2014年,有超过72000名猎人来到美国的黄石和大提顿狩猎区捕猎。


Photo by DAVID GUTTENFELDER

 

15

Igor Voronkin在挪威斯匹次卑尔根岛的一家煤矿工作,和他的400个矿工同事一样,他也来自工作机会稀缺的乌克兰东部。


Photo by EVGENIA ARBUGAEVA

 

16

黄石大峡谷。就是像这样壮美的风景令国会在1872年想到创建黄石公园——现在看来,这依旧是革命性的一步。


Photo by MICHAEL NICHOLS

 

17

位于俄罗斯Bovanenkovo的天然气田。这片储量巨大的气田在1970年代被发现,不过,在俄罗斯总统普京将天然气列为优先发展能源之前,亚马尔半岛的天然气开发一直因为太过昂贵而停滞着。


Photo by EVGENIA ARBUGAEVA

 

18

一只美洲鳄从草丛中一个“伏地挺身”,返回到红树林根丛盘结,堪称迷宫、几乎没有破绽的庇护所。


Photo by DAVID DOUBILET AND JENNIFER HAYES

 

19

太阳落山时的台北开始充满活力。


Photo by DINA LITOVSKY

 

20

大雪纷飞中,一只浸没在黄石公园河中的野牛尸体,成为了这只狼和它两岁宝宝的盛宴。


Photo by RONAN DONOVAN

 

21

Becky Weed和她丈夫David Tyler在黄石国家公园附近养羊,他们得用一条牧羊犬来提防狼、熊和山狮。


Photo by ERIKA LARSEN

 

22

黄石公园里的大棱镜温泉奇异的颜色来自嗜热菌:一种在可以烫伤我们的热水里生长的微生物。


Photo by MICHAEL NICHOLS

 

23

Steven Donovan跳进“游泳池”。 他凭借自己的摄影技术,在冰川国家公园找到了一份靠季节吃饭的工作。


Photo by COREY ARNOLD

 

24

Kirk Odom曾经因为一名专家作证受害者睡衣上的头发与他的头发相匹配而被判有强奸罪。在监狱待了多年之后,DNA测试才证明了他的清白。


Photo by MAX AGUILERA-HELLWEG

 

25

在阿拉斯加,灰熊妈妈和它的幼崽在德纳里峰附近的观景公路上造成了“熊堵”。这条路每年夏天只向私家车开放5天。


Photo by AARON HUEY

 

26

由于各种武装团体的不断威胁,刚果民主共和国Virunga公园内的护林员接受了伏击战术等项目的军事训练。


Photo by BRENT STIRTON

 

27

在南非的Hluhluwe-Imfolozi公园,偷猎者用高口径子弹击杀了这只黑犀牛,砍走了它的角。全球现在只有不到5000只黑犀牛了。


Photo by BRENT STIRTON

 

28

为了跟踪海洋冰面的变化,2015年,这艘挪威调查船与冰块们一起漂浮了5个月,经历了一个漫长的航程:从北极的冬天一直航行到春天来临。


Photo by NICK COBBING

 

29

在约塞米蒂国家公园的一个山腰上,摄影师Stephen Wilkes在26小时内拍摄了1036张图片,创造出了这一张日夜复合的景象。


Photo by STEPHEN WILKES

 

30

一名工人正在用木锤从一艘中国货船上敲下冰冻金枪鱼,这艘船停泊在菲律宾桑托斯将军城附近。


Photo by ADAM DEAN

 

31

血滴从一只黑白兀鹫的喙滴落的瞬间。它的颈部和头部的羽毛很稀疏,这可以避免在啃食动物尸体的时候,粘连太多的血液、内脏、或者一些排泄物。


Photo by CHARLIE HAMILTON JAMES

 

32

为去火星而“盛装打扮”:太空工程师Pablo de León正在NASA的肯尼迪太空中心“浮土室”测试一件太空服的样衣。风扇鼓起沙尘,以模拟那个红色星球上的外部条件。


Photo by PHILLIP TOLEDANO

 

33

亚美尼亚的基督徒村民正在杏树下野餐,他们唱着祈求和平安定和文化延续的祷歌。一个巨大的闪光十字架立在旁边,对着土耳其,仿佛是挑衅。亚美尼亚和土耳其之间的激烈矛盾影响了四代人。


Photo by JOHN STANMEYER

 

34

章鱼的神经系统比大多数无脊椎动物都要更大更复杂,它们会思考吗?它们有意识吗?研究人员认为我们可能永远都无法知道这些问题的答案。


Photo by DAVID LIITTSCHWAGER AT FLORIDA KEYS MARINE LIFE

 

35

一半是好奇,一半是对即将到来的变化的隐约预感:今年5月的古巴哈瓦那湾,迎来了近40年来,第一艘来自美国的游轮。


Photo by DAVID GUTTENFELDER

 

36

一群银鱼正在通过古巴的红树林珊瑚礁。为了保护自己,手指大小的小银鱼聚集成大型的鱼群,迷惑捕食者。


Photo by DAVID DOUBILET AND JENNIFER HAYES

 

37

在一个南非的牧场上,一群小犀牛最近被修剪了角。与大象象牙不同,犀牛的角是可以在正确切割后生长的。牧场正把这些犀牛角储存起来,未来将被合法销售。


Photo by BRENT STIRTON

 

38

Gerd Gamanab今年67岁,在纳米比亚的炙热的阳光和尘埃中的常年劳作,损毁了他的角膜。可是如果不是因为治疗过迟,他的失明其实是可以被避免的。


Photo by BRENT STIRTON

 

39

在黄石东南部,一群三周大的小马鹿正跟着它们的妈妈走在一个4600英尺的山坡上——这可是它们经历的第一次夏季迁徙哦。


Photo by JOE RIIS

 

40

暂离首尔节奏紧张的市中心,从事推销员工作的Sungvin Hong在北汉山国家公园徒步登山后,在一块大石头上闭目养神。


Photo by LUCAS FOGLIA

 

41

夏季是属于日光浴的季节,不管你偏好穿衣服版本……还是其他版本的。慕尼黑Schwabinger Bach的一片草地,从上世纪70年代以来,一直是裸体主义者们的最爱。


Photo by SIMON ROBERTS

 

42

原住民在秘鲁的马努森林中世代猎捕和种植,但只获取足以维持生活的数量。图中吊挂着的蜘蛛猴是他们最爱的猎物,也是他们最喜欢的宠物。


Photo by CHARLIE HAMILTON JAMES

 

43

一个女孩看着3个蒙着面纱的库尔德妇女。其中两名妇女在逃离难民营之前,被迫嫁给了ISIS的成员。


Photo by YURI KOZYREV

 

44

在猎犬的帮助下,一个护林员希望可以追踪到杀死这头大象,为了象牙窃走大象头部的偷猎者。


Photo by BRENT STIRTON

 

45

中国的熊猫保育员与训练小熊猫用的猎豹标本。为了使小熊猫可以对危险的野外环境和天敌产生畏惧,保育员们需要观察小熊猫们对“猎豹”的反应,判断它们是否准备好野外生存。


Photo by AMI VITALE

 

46

在爱达荷州的霍尔堡,Leo Teton站在一个用北美野牛头骨装饰的木桩旁边,这样的木桩其实代表着Shoshone-Bannock部落与野牛之间的精神链接。


Photo by ERIKA LARSEN

 

47

一群小孩在海地萨鲁特港一条的河里嬉水。这座城市刚刚经历了飓风马修的严重侵袭,这条河上的桥和其他许多房屋、公共设施都被严重损毁。


Photo by ANDREW MCCONNELL

 

48

Isra Ali Saalad跟着她的妈妈和哥哥姐姐一起从索马里搬到了瑞典。“我们搬到这里的原因是因为它是安全的。”她的姐姐Samsam说。


Photo by ROBIN HAMMOND

 

49

一群黑白秃鹫在塞伦盖蒂啃食斑马尸体,更凶猛强壮的鸟类有优势抢夺腐肉,而其他的鸟没有什么选择,只能接受它们的“剩饭”:皮和骨头。


Photo by CHARLIE HAMILTON JAMES

 

50

在塞舌尔的阿尔达布拉环礁内,一大群黑鳍礁鲨正懒洋洋地躺在浅浅的温水里,等待海潮到来使得这里的水位再次升高。


Photo by THOMAS P. PESCHAK

 

51

随着火车离目的地喀什站越来越近,一个小旅客在慢慢一路吹进火车积下的沙子上画了一颗心。


Photo by MATTHIEU PALEY

52

以上就是国家地理杂志选出的年度最佳照片,但是似乎出现了一个小小的bug ,我们只在官网的页面上找到了51张照片,而不是正文所述的52张。

MySQL 高性能存储引擎:TokuDB初探

$
0
0

在安装MariaDB的时候了解到代替InnoDB的TokuDB,看简介非常的棒,这里对ToduDB做一个初步的整理,使用后再做更多的分享。

什么是TokuDB?

在MySQL最流行的支持全事务的引擎为INNODB。其特点是数据本身是用B-TREE来组织,数据本身即是庞大的根据主键聚簇的B-TREE索引。 所以在这点上,写入速度就会有些降低,因为要每次写入要用一次IO来做索引树的重排。特别是当数据量本身比内存大很多的情况下,CPU本身被磁盘IO纠缠的做不了其他事情了。这时我们要考虑如何减少对磁盘的IO来排解CPU的处境,常见的方法有:

  • 把INNODB 个PAGE增大(默认16KB),但增大也就带来了一些缺陷。 比如,对磁盘进行CHECKPOINT的时间将延后。
  • 把日志文件放到更快速的磁盘上,比如SSD。

TokuDB 是一个支持事务的“新”引擎,有着出色的数据压缩功能,由美国 TokuTek 公司(现在已经被 Percona 公司收购)研发。拥有出色的数据压缩功能,如果您的数据写多读少,而且数据量比较大,强烈建议您使用TokuDB,以节省空间成本,并大幅度降低存储使用量和IOPS开销,不过相应的会增加 CPU 的压力。

TokuDB 的特性

1.丰富的索引类型以及索引的快速创建

TokuDB 除了支持现有的索引类型外, 还增加了(第二)集合索引, 以满足多样性的覆盖索引的查询, 在快速创建索引方面提高了查询的效率

2.(第二)集合索引

也可以称作非主键的集合索引, 这类索引也包含了表中的所有列, 可以用于覆盖索引的查询需要, 比如以下示例, 在where 条件中直接命中 index_b 索引, 避免了从主键中再查找一次.

CREATE TABLE table (
column_a INT,
column_b INT,
column_c INT,
PRIMARY KEY index_a (column_a),
CLUSTERING KEY index_b (column_b)) ENGINE = TokuDB;

SELECT column_c
FROM table
WHERE column_b BETWEEN 10 AND 100;

见:  http://tokutek.com/2009/05/introducing_multiple_clustering_indexes/

3.索引在线创建(Hot Index Creation)

TokuDB 允许直接给表增加索引而不影响更新语句(insert, update 等)的执行。可以通过变量 tokudb_create_index_online 来控制是否开启该特性, 不过遗憾的是目前还只能通过 CREATE INDEX 语法实现在线创建, 不能通过 ALTER TABLE 实现. 这种方式比通常的创建方式慢了许多, 创建的过程可以通过 show processlist 查看。不过 tokudb 不支持在线删除索引, 删除索引的时候会对标加全局锁。

> SET tokudb_create_index_online=ON;
Query OK, 0 rows affected (0.00 sec)> CREATE INDEX index ON table (field_name);

4.在线更改列(Add, Delete, Expand, Rename)

TokuDB 可以在轻微阻塞更新或查询语句的情况下, 允许实现以下操作:

  • 增加或删除表中的列
  • 扩充字段: char, varchar, varbinary 和 int 类型的列
  • 重命名列, 不支持字段类型: TIME, ENUM, BLOB, TINYBLOB, MEDIUMBLOB, LONGBLOB

这些操作通常是以表锁级别阻塞(几秒钟时间)其他查询的执行, 当表记录下次从磁盘加载到内存的时候, 系统就会随之对记录进行修改操作(add, delete 或 expand), 如果是 rename 操作, 则会在几秒钟的停机时间内完成所有操作。

TokuDB的这些操作不同于 InnoDB, 对表进行更新后可以看到 rows affected 为 0, 即更改操作会放到后台执行, 比较快速的原因可能是由于 Fractal-tree 索引的特性, 将随机的 IO 操作替换为顺序 IO 操作, Fractal-tree的特性中, 会将这些操作广播到所有行, 不像 InnoDB, 需要 open table 并创建临时表来完成.

看看官方对该特性的一些指导说明:

  • 所有的这些操作不是立即执行, 而是放到后台中由 Fractal Tree 完成, 操作包括主键和非主键索引。也可以手工强制执行这些操作, 使用 OPTIMIZE TABLE X 命令即可, TokuDB 从1.0 开始OPTIMIZE TABLE命令也支持在线完成, 但是不会重建索引
  • 不要一次更新多列, 分开对每列进行操作
  • 避免同时对一列进行 add, delete, expand 或 drop 操作
  • 表锁的时间主要由缓存中的脏页(dirty page)决定, 脏页越多 flush 的时间就越长. 每做一次更新, MySQL 都会关闭一次表的连接以释放之前的资源
  • 避免删除的列是索引的一部分, 这类操作会特别慢, 非要删除的话可以去掉索引和该列的关联再进行删除操作
  • 扩充类的操作只支持 char, varchar, varbinary 和 int 类型的字段
  • 一次只 rename 一列, 操作多列会降级为标准的 MySQL 行为, 语法中列的属性必须要指定上, 如下:
    • ALTER TABLE table
      CHANGE column_old column_new
      DATA_TYPE REQUIRED_NESS DEFAULT
  • rename 操作还不支持字段: TIME, ENUM, BLOB, TINYBLOB, MEDIUMBLOB, LONGBLOB.
  • 不支持更新临时表;

5.数据压缩

TokuDB中所有的压缩操作都在后台执行, 高级别的压缩会降低系统的性能, 有些场景下会需要高级别的压缩. 按照官方的建议: 6核数以下的机器建议标准压缩, 反之可以使用高级别的压缩。

每个表在 create table 或 alter table 的时候通过 ROW_FORMAT 来指定压缩的算法:

CREATE TABLE table (
column_a INT NOT NULL PRIMARY KEY,
column_b INT NOT NULL) ENGINE=TokuDB
ROW_FORMAT=row_format;

ROW_FORMAT默认由变量 tokudb_row_format 控制, 默认为 tokudb_zlib, 可以的值包括:

  • tokudb_zlib: 使用 zlib 库的压缩模式,提供了中等级别的压缩比和中等级别的CPU消耗。
  • tokudb_quicklz: 使用 quicklz 库的压缩模式, 提供了轻量级的压缩比和较低基本的CPU消耗。
  • tokudb_lzma: 使用lzma库压缩模式,提供了高压缩比和高CPU消耗。
  • tokudb_uncompressed: 不使用压缩模式。

6.Read free 复制特性

得益于 Fracal Tree 索引的特性, TokuDB 的 slave 端能够以低于读IO的消耗来应用 master 端的变化, 其主要依赖 Fractal Tree 索引的特性,可以在配置里启用特性

  • insert/delete/update操作部分可以直接插入到合适的 Fractal Tree 索引中, 避免 read-modify-write 行为的开销;
  • delete/update 操作可以忽略唯一性检查带来的 IO 方面的开销

不好的是, 如果启用了 Read Free Replication 功能, Server 端需要做如下设置:

  • master:复制格式必须为 ROW, 因为 tokudb 还没有实现对 auto-increment函数进行加锁处理, 所以多个并发的插入语句可能会引起不确定的 auto-increment值, 由此造成主从两边的数据不一致.
  • slave:开启 read-only; 关闭唯一性检查(set tokudb_rpl_unique_checks=0);关闭查找(read-modify-write)功能(set tokudb_rpl_lookup_rows=0);

slave 端的设置可以在一台或多台 slave 中设置:MySQL5.5 和 MariaDB5.5中只有定义了主键的表才能使用该功能, MySQL 5.6, Percona 5.6 和 MariaDB 10.X 没有此限制

7.事务, ACID 和恢复

  • 默认情况下, TokuDB 定期检查所有打开的表, 并记录 checkpoint 期间所有的更新, 所以在系统崩溃的时候, 可以恢复表到之前的状态(ACID-compliant), 所有的已提交的事务会更新到表里,未提交的事务则进行回滚. 默认的检查周期每60s一次, 是从当前检查点的开始时间到下次检查点的开始时间, 如果 checkpoint 需要更多的信息, 下次的checkpoint 检查会立即开始, 不过这和 log 文件的频繁刷新有关. 用户也可以在任何时候手工执行 flush logs 命令来引起一次 checkpoint 检查; 在数据库正常关闭的时候, 所有开启的事务都会被忽略.
  • 管理日志的大小: TokuDB 一直保存最近的checkpoing到日志文件中, 当日志达到100M的时候, 会起一个新的日志文件; 每次checkpoint的时候, 日志中旧于当前检查点的都会被忽略, 如果检查的周期设置非常大, 日志的清理频率也会减少。 TokuDB也会为每个打开的事务维护回滚日志, 日志的大小和事务量有关, 被压缩保存到磁盘中, 当事务结束后,回滚日志会被相应清理.
  • 恢复: TokuDB自动进行恢复操作, 在崩溃后使用日志和回滚日志进行恢复, 恢复时间由日志大小(包括未压缩的回滚日志)决定.
  • 禁用写缓存: 如果要保证事务安全, 就得考虑到硬件方面的写缓存. TokuDB 在 MySQL 里也支持事务安全特性(transaction safe), 对系统而言, 数据库更新的数据不一样真的写到磁盘里, 而是缓存起来, 在系统崩溃的时候还是会出现丢数据的现象, 比如TokuDB不能保证挂载的NFS卷可以正常恢复, 所以如果要保证安全,最好关闭写缓存, 但是可能会造成性能的降低.通常情况下需要关闭磁盘的写缓存, 不过考虑到性能原因, XFS文件系统的缓存可以开启, 不过穿线错误”Disabling barriers”后,就需要关闭缓存. 一些场景下需要关闭文件系统(ext3)缓存, LVM, 软RAID 和带有 BBU(battery-backed-up) 特性的RAID卡

8.过程追踪

TokuDB 提供了追踪长时间运行语句的机制. 对 LOAD DATA 命令来说,SHOW PROCESSLIST 可以显示过程信息, 第一个是类似 “Inserted about 1000000 rows” 的状态信息, 下一个是完成百分比的信息, 比如 “Loading of data about 45% done”; 增加索引的时候, SHOW PROCESSLIST 可以显示 CREATE INDEX 和 ALTER TABLE 的过程信息, 其会显示行数的估算值, 也会显示完成的百分比; SHOW PROCESSLIST 也会显示事务的执行情况, 比如 committing 或 aborting 状态.

9.迁移到 TokuDB

可以使用传统的方式更改表的存储引擎, 比如 “ALTER TABLE … ENGINE = TokuDB” 或 mysqldump 导出再倒入, INTO OUTFILE 和 LOAD DATA INFILE 的方式也可以。

10.热备

Percona Xtrabackup 还未支持 TokuDB 的热备功能, percona 也为表示有支持的打算  http://www.percona.com/blog/2014/07/15/tokudb-tips-mysql-backups/ ;对于大表可以使用 LVM 特性进行备份,  https://launchpad.net/mylvmbackup , 或 mysdumper 进行备份。TokuDB 官方提供了一个热备插件 tokudb_backup.so, 可以进行在线备份, 详见  https://github.com/Tokutek/tokudb-backup-plugin, 不过其依赖 backup-enterprise, 无法编译出 so 动态库, 是个商业的收费版本, 见  https://www.percona.com/doc/percona-server/5.6/tokudb/tokudb_installation.html

总结

TokuDB的优点:

  • 高压缩比,默认使用zlib进行压缩,尤其是对字符串(varchar,text等)类型有非常高的压缩比,比较适合存储日志、原始数据等。官方宣称可以达到1:12。
  • 在线添加索引,不影响读写操作
  • HCADER 特性,支持在线字段增加、删除、扩展、重命名操作,(瞬间或秒级完成)
  • 支持完整的ACID特性和事务机制
  • 非常快的写入性能, Fractal-tree在事务实现上有优势,无undo log,官方称至少比innodb高9倍。
  • 支持show processlist 进度查看
  • 数据量可以扩展到几个TB;
  • 不会产生索引碎片;
  • 支持hot column addition,hot indexing,mvcc

TokuDB缺点:

  • 不支持外键(foreign key)功能,如果您的表有外键,切换到 TokuDB引擎后,此约束将被忽略。
  • TokuDB 不适大量读取的场景,因为压缩解压缩的原因。CPU占用会高2-3倍,但由于压缩后空间小,IO开销低,平均响应时间大概是2倍左右。
  • online ddl 对text,blob等类型的字段不适用
  • 没有完善的热备工具,只能通过mysqldump进行逻辑备份

适用场景:

  • 访问频率不高的数据或历史数据归档
  • 数据表非常大并且时不时还需要进行DDL操作

TokuDB的索引结构–分形树的实现

TokuDB和InnoDB最大的不同在于TokuDB采用了一种叫做Fractal Tree的索引结构,使其在随机写数据的处理上有很大提升。目前无论是SQL Server,还是MySQL的innodb,都是用的B+Tree(SQL Server用的是标准的B-Tree)的索引结构。InnoDB是以主键组织的B+Tree结构,数据按照主键顺序排列。对于顺序的自增主键有很好的性能,但是不适合随机写入,大量的随机I/O会使数据页分裂产生碎片,索引维护开销很多大。TokuDB解决随机写入的问题得益于其索引结构,Fractal Tree 和 B-Tree的差别主要在于索引树的内部节点上,B-Tree索引的内部结构只有指向父节点和子节点的指针,而Fractal Tree的内部节点不仅有指向父节点和子节点的指针,还有一块Buffer区。当数据写入时会先落到这个Buffer区上,该区是一个FIFO结构,写是一个顺序的过程,和其他缓冲区一样,满了就一次性刷写数据。所以TokuDB上插入数据基本上变成了一个顺序添加的过程。

BTree和Fractal tree的比较:

StructureInsertsPoint QueriesRange Queries
B-TreeHorribleGoodGood (young)
AppendWonderfulHorribleHorrible
Fractal TreeGoodGoodGood

Fractal tree(分形树)简介

分形树是一种写优化的磁盘索引数据结构。 在一般情况下, 分形树的写操作(Insert/Update/Delete)性能比较好,同时它还能保证读操作近似于B+树的读性能。据Percona公司测试结果显示, TokuDB分形树的写性能优于InnoDB的B+树), 读性能略低于B+树。

ft-index的磁盘存储结构

ft-index采用更大的索引页和数据页(ft-index默认为4M, InnoDB默认为16K), 这使得ft-index的数据页和索引页的压缩比更高。也就是说,在打开索引页和数据页压缩的情况下,插入等量的数据, ft-index占用的存储空间更少。ft-index支持在线修改DDL (Hot Schema Change)。 简单来讲,就是在做DDL操作的同时(例如添加索引),用户依然可以执行写入操作, 这个特点是ft-index树形结构天然支持的。 此外, ft-index还支持事务(ACID)以及事务的MVCC(Multiple Version Cocurrency Control 多版本并发控制), 支持崩溃恢复。正因为上述特点, Percona公司宣称TokuDB一方面带给客户极大的性能提升, 另一方面还降低了客户的存储使用成本。

ft-index的索引结构图如下:

灰色区域表示ft-index分形树的一个页,绿色区域表示一个键值,两格绿色区域之间表示一个儿子指针。 BlockNum表示儿子指针指向的页的偏移量。Fanout表示分形树的扇出,也就是儿子指针的个数。 NodeSize表示一个页占用的字节数。NonLeafNode表示当前页是一个非叶子节点,LeafNode表示当前页是一个叶子节点,叶子节点是最底层的存放Key-value键值对的节点, 非叶子节点不存放value。 Heigth表示树的高度, 根节点的高度为3, 根节点下一层节点的高度为2, 最底层叶子节点的高度为1。Depth表示树的深度,根节点的深度为0, 根节点的下一层节点深度为1。

分形树的树形结构非常类似于B+树, 它的树形结构由若干个节点组成(我们称之为Node或者Block,在InnoDB中,我们称之为Page或者页)。 每个节点由一组有序的键值组成。假设一个节点的键值序列为[3, 8], 那么这个键值将(-00, +00)整个区间划分为(-00, 3), [3, 8), [8, +00) 这样3个区间, 每一个区间就对应着一个儿子指针(Child指针)。 在B+树中, Child指针一般指向一个页, 而在分形树中,每一个Child指针除了需要指向一个Node的地址(BlockNum)之外,还会带有一个Message Buffer (msg_buffer), 这个Message Buffer 是一个先进先出(FIFO)的队列,用来存放Insert/Delete/Update/HotSchemaChange这样的更新操作。

按照ft-index源代码的实现, 对ft-index中分形树更为严谨的说法:

  • 节点(block或者node, 在InnoDB中我们称之为Page或者页)是由一组有序的键值组成, 第一个键值设置为null键值, 表示负无穷大。
  • 节点分为两种类型,一种是叶子节点, 一种是非叶子节点。 叶子节点的儿子指针指向的是BasementNode, 非叶子节点指向的是正常的Node 。 这里的BasementNode节点存放的是多个K-V键值对, 也就是说最后所有的查找操作都需要定位到BasementNode才能成功获取到数据(Value)。这一点也和B+树的LeafPage类似, 数据(Value)都是存放在叶子节点, 非叶子节点用来存放键值(Key)做索引。 当叶子节点加载到内存后,为了快速查找到BasementNode中的数据(Value), ft-index会把整个BasementNode中的key-value都转换为一棵弱平衡二叉树, 这棵平衡二叉树有一个很逗逼的名字,叫做 替罪羊树
  • 每个节点的键值区间对应着一个儿子指针(Child Pointer)。 非叶子节点的儿子指针携带着一个 MessageBuffer, MessageBuffer是一个FIFO队列。用来存放Insert/Delete/Update/HotSchemaChange这样的更新操作。儿子指针以及MessageBuffer都会序列化存放在Node的磁盘文件中。
  • 每个非叶子节点(Non Leaf Node)儿子指针的个数必须在[fantout/4, fantout]这个区间之内。 这里fantout是分形树(B+树也有这个概念)的一个参数,这个参数主要用来维持树的高度。当一个非叶子节点的儿子指针个数小于fantout/4 , 那么我们认为这个节点的太空虚了,需要和其他节点合并为一个节点(Node Merge), 这样能减少整个树的高度。当一个非叶子节点的儿子指针个数超过fantout, 那么我们认为这个节点太饱满了, 需要将一个节点一拆为二(Node Split)。 通过这种约束控制,理论上就能将磁盘数据维持在一个正常的相对平衡的树形结构,这样可以控制插入和查询复杂度上限。
  • 注意: 在ft-index实现中,控制树平衡的条件更加复杂, 例如除了考虑fantout之外,还要保证节点总字节数在[NodeSize/4, NodeSize]这个区间, NodeSize一般为4M ,当不在这个区间时, 需要做对应的合并(Merge)或者分裂(Split)操作。

分形树的Insert/Delete/Update实现

我们说到分形树是一种写优化的数据结构, 它的写操作性能要优于B+树的写操作性能。 那么它究竟如何做到更优的写操作性能呢?首先, 这里说的写操作性能,指的是随机写操作。 举个简单例子,假设我们在MySQL的InnoDB表中不断执行这个SQL语句: insert into sbtest set x = uuid(), 其中sbtest表中有一个唯一索引字段为x。 由于uuid()的随机性,将导致插入到sbtest表中的数据散落在各个不同的叶子节点(Leaf Node)中。 在B+树中, 大量的这种随机写操作将导致LRU-Cache中大量的热点数据页落在B+树的上层(如下图所示)。这样底层的叶子节点命中Cache的概率降低,从而造成大量的磁盘IO操作, 也就导致B+树的随机写性能瓶颈。但B+树的顺序写操作很快,因为顺序写操作充分利用了局部热点数据, 磁盘IO次数大大降低。

下面来说说分形树插入操作的流程。 为了方便后面描述,约定如下:

  • 以Insert操作为例, 假定插入的数据为(Key, Value)
  • 加载节点(Load Page),都是先判断该节点是否命中LRU-Cache。仅当缓存不命中时, ft-index才会通过seed定位到偏移量读取数据页到内存
  • 暂时不考虑崩溃日志和事务处理。

详细流程如下:

  1. 加载Root节点;
  2. 判断Root节点是否需要分裂(或合并),如果满足分裂(或者合并)条件,则分裂(或者合并)Root节点。 具体分裂Root节点的流程,感兴趣的同学可以开开脑洞。
  3. 当Root节点height>0, 也就是Root是非叶子节点时, 通过二分搜索找到Key所在的键值区间Range,将(Key, Value)包装成一条消息(Insert, Key, Value) , 放入到键值区间Range对应的Child指针的Message Buffer中。
  4. 当Root节点height=0时,即Root是叶子节点时, 将消息(Insert, Key, Value) 应用(Apply)到BasementNode上, 也就是插入(Key, Value)到BasementNode中。

这里有一个非常诡异的地方,在大量的插入(包括随机和顺序插入)情况下, Root节点会经常性的被撑饱满,这将会导致Root节点做大量的分裂操作。然后,Root节点做了大量的分裂操作之后,产生大量的height=1的节点, 然后height=1的节点被撑爆满之后,又会产生大量height=2的节点, 最终树的高度越来越高。 这个诡异的之处就隐藏了分形树写操作性能比B+树高的秘诀: 每一次插入操作都落在Root节点就马上返回了, 每次写操作并不需要搜索树形结构最底层的BasementNode, 这样会导致大量的热点数据集中落在在Root节点的上层(此时的热点数据分布图类似于上图), 从而充分利用热点数据的局部性,大大减少了磁盘IO操作。

Update/Delete操作的情况和Insert操作的情况类似, 但是需要特别注意的地方在于,由于分形树随机读性能并不如InnoDB的B+树。因此,Update/Delete操作需要细分为两种情况考虑,这两种情况测试性能可能差距巨大:

  • 覆盖式的Update/Delete (overwrite)。 也就是当key存在时, 执行Update/Delete; 当key不存在时,不做任何操作,也不需要报错。
  • 严格匹配的Update/Delete。 当key存在时, 执行update/delete ; 当key不存在时, 需要报错给上层应用方。 在这种情况下,我们需要先查询key是否存在于ft-index的basementnode中,于是Point-Query默默的拖了Update/Delete操作的性能后退。

此外,ft-index为了提升顺序写的性能,对顺序插入操作做了一些优化,例如 顺序写加速

分形树的Point-Query实现

在ft-index中, 类似select from table where id = ? (其中id是索引)的查询操作称之为Point-Query; 类似select from table where id >= ? and id <= ? (其中id是索引)的查询操作称之为Range-Query。 上文已经提到, Point-Query读操作性能并不如InnoDB的B+树, 这里详细描述Point-Query的相关流程。 (这里假设要查询的键值为Key)

  1. 加载Root节点,通过二分搜索确定Key落在Root节点的键值区间Range, 找到对应的Range的Child指针。
  2. 加载Child指针对应的的节点。 若该节点为非叶子节点,则继续沿着分形树一直往下查找,一直到叶子节点停止。 若当前节点为叶子节点,则停止查找。

查找到叶子节点后,我们并不能直接返回叶子节点中的BasementNode的Value给用户。 因为分形树的插入操作是通过消息(Message)的方式插入的, 此时需要把从Root节点到叶子节点这条路径上的所有消息依次apply到叶子节点的BasementNode。 待apply所有的消息完成之后,查找BasementNode中的key对应的value,就是用户需要查找的值。

分形树的查找流程基本和 InnoDB的B+树的查找流程类似, 区别在于分形树需要将从Root节点到叶子节点这条路径上的messge buffer都往下推,并将消息apply到BasementNode节点上。注意查找流程需要下推消息, 这可能会造成路径上的部分节点被撑饱满,但是ft-index在查询过程中并不会对叶子节点做分裂和合并操作, 因为ft-index的设计原则是: Insert/Update/Delete操作负责节点的Split和Merge, Select操作负责消息的延迟下推(Lazy Push)。 这样,分形树就将Insert/Delete/Update这类更新操作通过未来的Select操作应用到具体的数据节点,从而完成更新。

分形树的Range-Query实现

下面来介绍Range-Query的查询实现。简单来讲, 分形树的Range-Query基本等价于进行N次Point-Query操作,操作的代价也基本等价于N次Point-Query操作的代价。 由于分形树在非叶子节点的msg_buffer中存放着BasementNode的更新操作,因此我们在查找每一个Key的Value时,都需要从根节点查找到叶子节点, 然后将这条路径上的消息apply到basenmentNode的Value上。 这个流程可以用下图来表示。

但是在B+树中, 由于底层的各个叶子节点都通过指针组织成一个双向链表, 结构如下图所示。 因此,我们只需要从跟节点到叶子节点定位到第一个满足条件的Key, 然后不断在叶子节点迭代next指针,即可获取到Range-Query的所有Key-Value键值。因此,对于B+树的Range-Query操作来说,除了第一次需要从root节点遍历到叶子节点做随机写操作,后继数据读取基本可以看做是顺序IO。

通过比较分形树和B+树的Range-Query实现可以发现, 分形树的Range-Query查询代价明显比B+树代价高,因为分型树需要遍历Root节点的覆盖Range的整颗子树,而B+树只需要一次Seed到Range的起始Key,后续迭代基本等价于顺序IO。

总结

总体来说,分形树是一种写优化的数据结构,它的核心思想是利用节点的MessageBuffer缓存更新操作,充分利用数据局部性原理, 将随机写转换为顺序写,这样极大的提高了随机写的效率。Tokutek研发团队的iiBench测试结果显示: TokuDB的insert操作(随机写)的性能比InnoDB快很多,而Select操作(随机读)的性能低于InnoDB的性能,但是差距较小,同时由于TokuDB采用有4M的大页存储,使得压缩比较高。这也是Percona公司宣称TokuDB更高性能,更低成本的原因。

另外,在线更新表结构(Hot Schema Change)实现也是基于MessageBuffer来实现的, 但和Insert/Delete/Update操作不同的是, 前者的消息下推方式是广播式下推(父节点的一条消息,应用到所有的儿子节点), 后者的消息下推方式单播式下推(父节点的一条消息,应用到对应键值区间的儿子节点), 由于实现类似于Insert操作,所以不再展开描述。

TokuDB的多版本并发控制(MVCC)

在传统的关系型数据库(例如Oracle, MySQL, SQLServer)中,事务可以说是研发和讨论最核心内容。而事务最核心的性质就是ACID。

  • A表示原子性,也就是组成事务的所有子任务只有两种结果:要么随着事务的提交,所有子任务都成功执行;要么随着事务的回滚,所有子任务都撤销。
  • C表示一致性,也就是无论事务提交或者回滚,都不能破坏数据的一致性约束,这些一致性约束包括键值唯一约束、键值关联关系约束等。
  • I表示隔离性,隔离性一般是针对多个并发事务而言的,也就是在同一个时间点,t1事务和t2事务读取的数据应该是隔离的,这两个事务就好像进了同一酒店的两间房间一样,各自在各自的房间里面活动,他们相互之间并不能看到各自在干嘛。
  • D表示持久性,这个性质保证了一个事务一旦承诺用户成功提交,那么即便是后继数据库进程crash或者操作系统crash,只要磁盘数据没坏,那么下次启动数据库后,这个事务的执行结果仍然可以读取到。

TokuDB目前完全支持事务的ACID。 从实现上看, 由于TokuDB采用的 分形树作为索引,而InnoDB采用B+树作为索引结构,因而TokuDB在事务的实现上和InnoDB有很大不同。

在InnoDB中, 设计了redo和undo两种日志,redo存放页的物理修改日志,用来保证事务的持久性; undo存放事务的逻辑修改日志,它实际存放了一条记录在多个并发事务下的多个版本,用来实现事务的隔离性(MVCC)和回滚操作。由于TokuDB的分形树采用消息传递的方式来做增删改更新操作,一条消息就是事务对该记录修改的一个版本,因此,在TokuDB源码实现中,并没有额外的undo-log的概念和实现,取而代之的是一条记录多条消息的管理机制。虽然一条记录多条消息的方式可以实现事务的MVCC,却无法解决事务回滚的问题,因此TokuDB额外设计了tokudb.rollback这个日志文件来做帮助实现事务回滚。

这里主要分析TokuDB的事务隔离性的实现,也就是常提到的多版本并发控制(MVCC)。

TokuDB的事务表示

在tokudb中, 在用户执行的一个事务,具体到存储引擎层面会被拆开成许多个小事务(这种小事务记为txn)。 例如用户执行这样一个事务:

begin;
insert into hello set id = 1, value = '1'; 
commit;

对应到TokuDB存储引擎的redo-log中的记录为:

xbegin          'b': lsn=236599 xid=15,0 parentxid=0,0 crc=29e4d0a1 len=53
xbegin          'b': lsn=236600 xid=15,1 parentxid=15,0 crc=282cb1a1 len=53
enq_insert      'I': lsn=236601 filenum=13 xid=15,1 key={...} value={...} crc=a42128e5 len=58
xcommit         'C': lsn=236602 xid=15,1 crc=ec9bba3d len=37
xprepare        'P': lsn=236603 xid=15,0 xa_xid={...} crc=db091de4 len=67
xcommit         'C': lsn=236604 xid=15,0 crc=ec997b3d len=37

对应的事务树如下图所示:

对一个较为复杂一点,带有savepoint的事务例子:

begin;
insert into hello set id = 2, value = '2' ;
savepoint mark1;
insert into hello set id = 3, value = '3' ;
savepoint mark2;
commit;

对应的redo-log的记录为:

xbegin           'b': lsn=236669 xid=17,0 parentxid=0,0 crc=c01888a6 len=53
xbegin           'b': lsn=236670 xid=17,1 parentxid=17,0 crc=cf400ba6 len=53
enq_insert       'I': lsn=236671 filenum=13 xid=17,1 key={...} value={...} crc=8ce371e3 len=58
xcommit          'C': lsn=236672 xid=17,1 crc=ec4a923d len=37
xbegin           'b': lsn=236673 xid=17,2 parentxid=17,0 crc=cb7c6fa6 len=53
xbegin           'b': lsn=236674 xid=17,3 parentxid=17,2 crc=c9a4c3a6 len=53
enq_insert       'I': lsn=236675 filenum=13 xid=17,3 key={...} value={...} crc=641148e2 len=58
xcommit          'C': lsn=236676 xid=17,3 crc=ec4e143d len=37
xcommit          'C': lsn=236677 xid=17,2 crc=ec4cf43d len=37
xprepare         'P': lsn=236678 xid=17,0 xa_xid={...} crc=76e302b4 len=67
xcommit          'C': lsn=236679 xid=17,0 crc=ec42b43d len=37

这个事务组成的一棵事务树如下:

在tokudb中,使用{parent_id, child_id}这样一个二元组来记录一个txn和其他txn的依赖关系。这样从根事务到叶子几点的一组标号就可以唯一标示一个txn, 这一组标号列表称之为xids, xids我认为也可以称为事务号。 例如txn3的xids = {17, 2, 3 } , txn2的xids = {17, 2}, txn1的xids= {17, 1}, txn0的xids = {17, 0}。

于是对于事务中的每一个操作(xbegin/xcommit/enq_insert/xprepare),都有一个xids来标识这个操作所在的事务号。 TokuDB中的每一条消息(insert/delete/update消息)都会携带这样一个xids事务号。这个xids事务号,在TokuDB的实现中扮演这非常重要的角色,与之相关的功能也特别复杂。

事务管理器

事务管理器用来管理TokuDB存储引擎所有事务集合, 它主要维护着这几个信息:

  • 活跃事务列表。活跃事务列表只会记录root事务,因为根据root事务其实可以找到整棵事务树的所有child事务。 这个事务列表保存这当前时间点已经开始,但是尚未结束的所有root事务。
  • 镜像读事务列表(snapshot read transaction)。
  • 活跃事务的引用列表(referenced_xids)。这个概念有点不好理解,假设一个活跃事务开始(xbegin)时间点为begin_id, 提交(xcommit)的时间点为end_id。那么referenced_xids就是维护(begin_id, end_id)这样一个二元组,这个二元组的用处就是可以找到一个事务的整个生命周期的所有活跃事务,用处主要是用来做后文说到的full gc操作。

分形树LeafEntry

上文分形树的树形结构中说到,在做insert/delete/update这样的操作时,会把从root到leaf的所有消息都apply到LeafNode节点中。 为了后面详细描述apply的过程,先介绍下LeafNode的存储结构。

leafNode简单来说,就是由多个leafEntry组成,每个leafEntry就是一个{k, v1, v2, … }这样的键值对, 其中v1, v2 .. 表示一个key对应的值的多个版本。具体到一个key对应得leafEntry的结构详细如下图所示。

由上图看出,一个leafEntry其实就是一个栈, 这个栈底部[0~5]这一段表示已经提交(commited transaction)的事务的Value值。栈的顶部[6~9]这一段表示当前尚未提交的活跃事务(uncommited transaction)。 栈中存放的单个元素为(txid, type, len, data)这样一个四元组,表明了这个事务对应的value取值。更通用一点讲,[0, cxrs-1]这一段栈表示已经提交的事务,本来已经提交的事务不应存在于栈中,但之所以存在,就是因为有其他事务通过snapshot read的方式引用了这些事务,因此,除非所有引用[0, cxrs-1]这段事务的所有事务都提交,否则[0, cxrs-1]这段栈的事务就不会被回收。[cxrs, cxrs+pxrs-1]这一段栈表示当前活跃的尚未提交的事务列表,当这部分事务提交时,cxrs会往后移动,最终到栈顶。

MVCC实现

1)写入操作

这里我们认为写入操作包括三种,分别为insert / delete / commit 三种类型。对于insert和delete这两种类型的写入操作,只需要在LeafEntry的栈顶放置一个元素即可。 如下图所示:

对于commit操作,只需把LeafEntry的栈顶元素放到cxrs这个指针处,然后收缩栈顶指针即可。如下图所示:

2)读取操作

对读取操作而言, 数据库一般支持多个隔离级别。MySQL的InnoDB支持Read UnCommitted(RU)、Read REPEATABLE(RR)、Read Commited(RC)、SERIALIZABLE(S)。其中RU存在脏读的情况(脏读指读取到未提交的事务), RC/RR/RU存在幻读的情况(幻读一般指一个事务在更新时可能会更新到其他事务已经提交的记录)。

TokuDB同样支持上述4中隔离级别, 在源码实现时, ft-index将事务的读取操作按照事务隔离级别分成3类:

  • TXN_SNAPSHOT_NONE : 这类不需要snapshot read, SERIALIZABLE和Read Uncommited两个隔离级别属于这一类。
  • TXN_SNAPSHOT_ROOT : Read REPEATABLE隔离级别属于这类。在这种其情况下, 说明事务只需要读取到root事务对应的xid之前已经提交的记录即可。
  • TXN_SNAPSHOT_CHILD: READ COMMITTED属于这类。在这种情况下,儿子事务A需要根据自己事务的xid来找到snapshot读的版本,因为在这个事务A开启时,可能有其他事务B做了更新,并提交,那么事务A必须读取B更新之后的结果。

多版本记录回收

随着时间的推移,越来越多的老事务被提交,新事务开始执行。 在分形树中的LeafNode中commited的事务数量会越来越多,假设不想方设法把这些过期的事务记录清理掉的话,会造成BasementNode节点占用大量空间,也会造成TokuDB的数据文件存放大量无用的数据。 在TokuDB中, 清理这些过期事务的操作称之为垃圾回收(Garbage Collection)。 其实InnoDB也存在过期事务回收这么一个过程,InnoDB的同一个Key的多个版本的Value存放在undo log 页上, 当事务过期时, 后台有一个purge线程专门来复杂清理这些过期的事务,从而腾出undo log页给后面的事务使用, 这样可以控制undo log无限增长。

TokuDB存储引擎中没有类似于InnoDB的purge线程来负责清理过期事务,因为过期事务的清理都是在执行更新操作是顺便GC的。 也就是在Insert/Delete/Update这些操作执行时,都会判断以下当前的LeafEntry是否满足GC的条件, 若满足GC条件时,就删除LeafEntry中过期的事务, 重新整理LeafEntry 的内存空间。按照TokuDB源码的实现,GC分为两种类型:

  • Simple GC:在每次apply 消息到leafentry 时, 都会携带一个gc_info, 这个gc_info 中包含了oldest_referenced_xid这个字段。 那么simple_gc的意思是什么呢? simple_gc就是做一次简单的GC, 直接把commited的事务列表清理掉(记住要剩下一个commit事务的记录, 否则下次查找这条commited的记录怎么找的到? )。这就是simple_gc, 简单暴力高效。
  • Full GC:full gc的触发条件和gc流程都比较复杂, 根本意图都是要清理掉过期的已经提交的事务。这里不再展开。

总结

本文大致介绍了TokuDB事务的隔离性实现原理, 包括TokuDB的事务表示、分形树的LeafEntry的结构、MVCC的实现流程、多版本记录回收方式这些方面的内容。 TokuDB之所有没有undo log,就是因为分形树中的更新消息本身就记录了事务的记录版本。另外, TokuDB的过期事务回收也不需要像InnoDB那样专门开启一个后台线程异步回收,而是才用在更新操作执行的过程中分摊回收。总之,由于TokuDB基于分形树之上实现事务,因而各方面的思路都有大的差异,这也是TokuDB团队的创新吧。

参考资料:

The post MySQL 高性能存储引擎:TokuDB初探 appeared first on 标点符.

怎样才能拥有家居杂志里的“高级粉”房间?

$
0
0

如果用一种颜色来形容最近两年的当代生活,那一定非粉色莫属。从时装、平面设计到家居用品,无处不在的粉色主宰了流行。再没有 少女心的人,也不太可能没有被某一种粉色安利到。

粉色衣服好穿,但给家里点缀一些粉色可就没那么容易了,一不小心可能就落入俗气的 “公主风”。 如何把时髦的高级粉巧妙地融入自己的家?让我们跟着那些厉害建筑事务所的作品来学一学。

为什么大家一窝蜂地爱上了粉色呢?无疑, 粉色是一个微妙的颜色,它常常与文雅感性、温柔甜美和女性浪漫等词联系在一起。而当我们身处“创旧”当道的时代,设计界“对重塑的渴望”很大程度上激发了大家对粉色的着迷。

粉色的传统含义也被来自全世界的优秀设计师转入了新的方向中,从而拥有了更为丰富多元的含义:它可以体现甜美纯真,也可以透露冷静坚毅。撇开泡泡糖般的童话滤镜,其实粉色本身就是纯粹的、诱惑的、酷的—— 你的家可能比你想象中更适合粉色

突破了“用粉色”的心理防线,我们就来说说如何才能用好粉色。以下这些案例,正是通过粉色与不同色彩和元素的搭配,让粉色墙面或粉色家具成为家中的亮点。

粉色 + 灰色

气质灰的好处恐怕不用多说,它可以同一切色彩相搭并提升对方,是 色彩里最好的“绿叶”。地板或墙面大面积的砖石灰,与浅粉或者藕粉色的组合让整个空间看起来温馨而摩登。或者,你也可以 在灰色背景下放置一两件显眼的粉色家具,让一抹shocking pink成为点睛之笔。

粉色 + 金属色

能让原本浪漫的粉色显得更加优雅的元素,非金色莫属。粉+白+金的组合时常出现在女性向的高级服装店中,在粉色和白色构成的空间里加上金色线条的点缀。几何形态的简单组合显得梦幻又优雅,无论是大受欢迎的黄铜色还是玫瑰金,都与粉色相得益彰。

粉色 + 墨绿

除了百搭的黑白灰,其实 粉色还有一个意料之外的好基友:墨绿色。深沉浓郁的墨绿和温柔静谧的藕粉色简直是天作之合,无论是大面积粉墙+小面积绿色家具,或者反过来大面积墨绿加上粉色家具,让空间显得更平衡也更有格调。

粉色 + 工业风

男生的家中如何使用粉色而不娘? 工业感的框架和家具,就能让粉色也多一些粗犷之气。另一方面,如果你家里是无法更改的黑色窗框,也许刷上一面粉色的墙壁就能让整个房间协调起来。

高级质感粉

粉色高不高级,很大程度上也取决于对色调和材质的把控上。可以向高级时装屋取经,结合今年大热的丝绒材质,提升粉色和整个空间的质感。此外透明的粉色材质也可以在视觉上达到一种戏剧性,节制的色调也为硬朗的室内增加轻柔气质。

粉色 + 大理石

作为这两年的爆款元素, 大理石元素与粉色结合使用也是打开粉色之家的一种正确方式。但同属冷淡色系的大理石与浅粉色很容易让空间显得太冷,因此在使用面积上就不宜过大——也许一幅大理石纹路的挂画就刚刚好能点缀在粉色墙面上。

每一条流行趋势都在告诉我们,
我们正生活在一个“粉色年代”里,
你家中有没有什么美貌的粉色?


收银员招谁惹谁了,松下也推出无人收银店铺

$
0
0

最近收银员“摊上”事儿了,前脚来了个“亚马逊 Go”,后脚松下也行动了。

昨天(12 月 12 号)松下联合联合日本线下连锁零售商店 LAWSON,在后者位于日本大阪府守口市的一家店铺内,展示了一套完全自动化的自助结账机。这套系统叫做“Rejirobo”,技术来自松下。

就在一周前(12 月 6 号),亚马逊正式宣布将在西雅图第七大街与 Balnchard 街的路口,开设一家无须排队结账的实体店——亚马逊 GO。

一个是全球性电商巨头,一个是日本顶尖科技企业和线下连锁零售合作,让人不禁为收银员的未来感到担忧。

虽然两者都希望能够利用机器帮助用户自己完成收银,但在实现方式上,松下和亚马逊有着很多不同。

亚马逊方案与无人驾驶更加接近:计算机视觉、传感器、深度学习。简单点说就是:你只需要在进门的时候刷一次二维码,然后就能够随便从货架上拿自己想要的东西,放进自己包里,然后直接离开。

相比之下,松下和 LAWSON 给出的解决方案要更加“传统一些”——“收银台”依然存在,但是机器会帮助完成装袋和计价步骤。

顾客走进店里,将自己想要的商品放在篮子中,选择完毕将篮子放在收银台指定区域。

机器会抽出篮子的底板,商品装入下方的袋子,同时通过自身的 RFID 标签进行统计和计价。用户付款后直接提着袋子走出商店。

这次与松下合作的 LAWSON 同样“来头不小”,这家企业实际诞生于美国,最早成立于 1939 年。但由于一系列商业上的“变动”,如今已经成为了一家“彻头彻尾”的日本公司。

目前在全球一共拥有 12395 家线下店,除了日本国内之外还在中国的上海、重庆、大连、北京,以及印尼、泰国、菲律宾、夏威夷拥有分店。

对于这套系统,LAWSON 官方表示:

我们希望能够简化复杂的零售业。通过引入 Rejirobo 系统,我们就不再需要收银员扫描商品并将货品装袋,这会让整个线下店更加省时省力。我们也将继续重视不需要扫描的产品电子标签,比如 RFID。

松下官方的表态则更简单:

我们就是想充分利用物联网和机器人技术,打造出更好的生活方式。比如利用人工智能机器人产品,打造出线下零售店的服务和物流解决方案。

不过严格来说,无论是亚马逊 GO 还是 LAWSON 展示店,他们都没有实现完全的无人化。店内的商品进货、上架、清洁等工作还是需要真人来完成。

从这个角度来看,这两者或许不能算作“抢人类工作”。而只是帮助人类完成“无聊”的工作而已,节省下的人力则可以投入到更多线下商店中去。

这也反映出了一个趋势:遥远的未来人类或许终将远离“工作”,但至少目前,机器在很多事情上仍无法取代人工。

MVP(最小可行产品)的重要含义

$
0
0

SILY系列文章第52期:MVP 必须向用户提供价值,换句话说,也就是验证问题是否真的存在,解决方案是否真的带来了改善。

精益创业中强调要使用 MVP 来验证问题确实存在,而 MVP 其实是最多被误解的一个定义。究竟什么是 MVP?MVP 和 高保真原型的区别是什么?

@jopas,画了一张非常棒的图表,让 MVP 的概念瞬间清晰:

MVP 在创业过程中的作用,可以通过 Henrik Kniberg 画的滑板车形象的理解:

MVP 是最小可用的产品,它必须向用户提供价值,换句话说,也就是验证问题是否真的存在,解决方案是否真的带来了改善。它不是一个粗糙的demo,也不是漂亮的原型,它必须直面问题给一个基本可用的解答。

正如滑板车的例子,用户必须真实的在使用你的产品,并给予反馈。每一次迭代针对一个具体真实的问题,每一次迭代都是寻找问题的最小代价解的过程。

最近好多原型设计工具得到运用,甚至有人可以制作复杂的以假乱真的原型,通过原型来做设计迭代。这里的坑是,原型无论如何的逼真,并不是真实可工作的产品,它在运行中缺少真实的数据和功能,把玩原型的过程也缺少真实使用的上下文,无法给予方案足够客观的评价。


不定期聊一些产品设计,以及有趣话题,分享我的所见所想,欢迎关注。

Stuff I Learned Yesterday系列文章话题包括科技、产品、设计、商业和创业有关的事。

银联工作总结

$
0
0
DB2版本 v9.5.0.4
weblogic版本 10.3
aix版本 6.1.0.0
jdk版本  1.6.64
mysql:Server version: 5.5.32-enterprise-commercial-advanced MySQL Enterprise Server
 
Linux上jdk版本:sun:jdk1.6.0_37
 
linux上无法使用jps、jstat等工具:
执行这个命令即可使用:
export PATH=/usr/java/jdk1.6.0_37/bin:$PATH
 
 
weblogic启动脚本:
C:\bea\user_projects\domains\mapsDomain\bin\startWebLogic.cmd
 
 
C:\bea\user_projects\domains\mapsDomain\servers\AdminServer
 
flex编辑工具
C:\Program Files\Adobe\Flex Builder 3 Plug-in
D:\MyEclipse 6.0\eclipse
 
 
flex project 
会自动编译生成*.swf
 
生成完swf文件以后,将*.html和*.swf拷贝到
maps_mng\WebContent\com\cup\maps\portal\jpf\flex
 
 
 
 
<2010-6-4 上午10时14分06秒 CST> <Warning> <JDBC> <BEA-001129> <Received exceptio
n while creating connection for pool "mapswebDS": [jcc][t4][2043][11550][3.50.15
2] 异常 java.net.ConnectException:打开端口 60,000 上服务器 /172.17.252.84 的套
接字时出错,消息为:Connection refused: connect。 ERRORCODE=-4499, SQLSTATE=0800
1>
 
 
 
com.cup.common.dao.util.PersistenceException: Unable to resolve 'jdbc.glmondb'. Resolved 'jdbc'; - nested throwable: (javax.naming.NameNotFoundException: Unable to resolve 'jdbc.glmondb'. Resolved 'jdbc'; remaining name 'glmondb')找不到数据源.
 
原因:没配数据源
URL:jdbc:db2://172.17.252.151:60001/glmondb:currentSchema=GL_MONDB;
Driver Class Name:com.ibm.db2.jcc.DB2Driver
user=gl_monap
portNumber=60001
databaseName=glmondb
serverName=172.17.252.151
Password:glmonap
JNDI Name: jdbc/glmondb
 
 
 
log位置:
D:\bea\user_projects\domains\base_domain\appLog\cups_maps.log
 
 
flex项目改好的swf和jsp文件需要copy到如下目录:
maps_mng\WebContent\com\cup\maps\portal\jpf\monitor\
然后必须要ant build项目maps_mng,然后重启weblogic才可以显示改动地方。
 
 
ant build 脚本位置:
maps_mng\script\build.xml
 
那cvs上传的文件应该是swf还是我改的mxml文件
都上传,swf是编译出来的目标文件,mxml是源文件
 
 
 
公共参数管理代码流程:
 
入口:
CommonParaSyncMainOperBean.operEtl(String paraCom,Integer syncBatNo,Map<String, String> jmsMap)
参数:paraCom 当前类型所包含的主题域
syncBatNo 批次号
jmsMap jms传递的map,包含参数类型和是否强制同步信息
 
syncService.syncPara(Integer.toString(syncBatNo), mainPt.getTblId(), userId, mainTableData);(CommonParaSyncServiceBean.syncPara)做了下面几件事:
1、通过同步批次号、表ID、用户ID、参数数据集合同步参数数据 
2、如果没有任务(para_task),则创建;如果任务和正式表存在,进行任务状态校验
3、如果临时表中有可修改的、显示在页面上的字段,则将这些字段值复制到etlData中
4、ETL数据覆盖到TEMP
5、记载审计日志
6、更新Etl表,设置ETL表的sync_st=1
 
 
本主题域从ETL同步后是否可编辑,即可以在多渠道进行维护部分字段,如果不可以在多渠道维护,那么自动生效
CommonParaSyncMainOperBean.activateSubject
做了几件事:
对需要自动生效的任务:
1、将para_task状态改为“复核通过”
2、syncService.activateTask(task);(CommonParaSyncServiceBean.activateTask)将状态改为5(生效中),设置一些ts和userid,做一些检查;forwardOthers()-》sendQueue()发送jms(类型是:ParaConstants.JMS_SUB_SYS_SYNC-JMS子系统同步)
3、ParameterEventBean.process()接受到这个jms消息开始处理:
sucess = syncExecute.activate(requestId);
参数同步生效方法
1.同步临时表数据至正式表
2.同步成功后,执行同步至其他子系统操作
4、if(sucess==true)并且该主题域是可以自动生效自动关闭的(entry_wizd_in=2),
那么设置任务状态是:"S", "同步成功",然后执行关闭任务:syncService.closeTask(task);(CommonParaSyncServiceBean.closeTask(ParaTask task))
 
 
 
备份一张表(ixf为二进制,del为字符型)
db2 "export to ./backup/ETL_MAMGM_TRANS_CHNL_CD.ixf  of ixf select * from ETL_MAMGM_TRANS_CHNL_CD"
覆盖一张表
db2 "import from /maps/usr/ma_mgmdb/backup/ETL/ETL_MAMGM_TRANS_CHNL_CD.ixf of ixf insert into ETL_MAMGM_TRANS_CHNL_CD"
 
查询schema下所有表
list tables for schema "ZHAOWM"
select * from table fetch first 10 rows only;
select * from table where v_time = timestamp('2008-01-01-00.00.01.000000');
 
 
weblogic配置data sources时提示jdbc找不到。
解决:要把d2cc.jar拷贝到domain\lib下。
 
myeclipse有时会报找不到某一类的错误,但是实际上是能找到的。
解决:clean project
 
修改好的swf文件要放在这里:
\maps_mng\WebContent\com\cup\maps\portal\jpf\monitor\maps_monitor.swf
 
 
取路径的最后文件名并排序
sed 's/.*\///;s/.*\\//' 1  | sort >2
 
用室内CVS上的代码与研究院上的代码比较,按时间降序
 
 
PARA_SUB_AREA_INF
ENTRY_WIZD_IN: 该字段在java中使用。
0: 参数维护页面上有“任务创建”按钮;公参任务自动生效。
1: 参数维护页面上有“任务创建”按钮;公参任务执行在“录入中”状态停住。
2: 参数维护页面上没有“任务创建”按钮,只有“查询”;公参任务自动生效。
无论0还是1,在页面上手工创建任务时,都需要手工经历录入中,待复核,复核通过,同步正式表,同步成功等状态。
BAT_EFF_IN: 0:只读    1:可以新增、修改。  该字段在页面上使用
subject.as中存在该字段,如果0的话,“任务创建”按钮还是不存在的。如果是1的话,“任务创建”按钮会在的。
 
是否同步子系统:
para_tbl_attr:
ma_subsys_bmp 10位位图
每位顺序代表:联机(第一位),批量(第二位 ),通讯,管理,健康,NASA(第6位)
PUB_PARA_CD 该字段在公参同步时使用,当子表的该字段值为空时,该子表不做同步处理;当子表的该字段值为01,即有值时,该子表会同步数据。
 
表是否支持插入,更新,删除,查询
para_tbl_attr:
main_tp 4位   0表示可以做,1表示不可以做
para_tbl_attr的ini_exp字段,是页面初始化使用的字段
具体使用在:TableForm.as中(引用了ParaTable.as的initExp值,该值对应着上述字段)
 
 
字段
para_fld_attr:
readonly_bmp  两位,分别对应“新增/修改” 0表示具有这个权限,即具有新增或修改权限,1代表不具有该权限
Form_in:  一位, 1 表示 在创建参数修改任务中,在创建参数新增任务中,会显示这个字段; 0 表示 页面中不显示这个字段
SHOW_TP:  一位: 0 表示使用默认值,在CommonSyncCommand.copyUpdatableFields()中,会将TBL_MAMGM_PARA_FLD_ATTR表中配置的dft_value值,覆盖到etl表中。
LIST_IN:  1 表示在检索结果中,会显示这个字段
INQ_FLD_IN   1 表示在参数维护页面,检索时显示的条件项。   0表示该字段不在检索条件里。
COMP_TP   00 表示一般单行文字输入框, 01 表示下拉框   11 表示可以输入的下拉框  04 日期  07 时间  06 多行文本框
DRDL_VAL_TBL_NM   下拉框里面选择的内容。对应于TBL_MAMGM_DRDL_CFG表。
fld_data_tp:00:string  01:INT   02:timestamp  03:float  04:BIGDECIMAL
DFT_VALUE:    页面上新建参数任务时,该字段的默认值。
 
 
所有表的字段都会在TBL_MAMGM_PARA_FLD_ATTR中,但是并不是所有SHOW_TP为0的字段,都会被覆盖默认值,必须满足下面条件:
1、FORM_IN=1,该字段在页面上显示
2、READONLY_BMP = 10或00 (第二位是0) ,该字段可以修改
3、SHOW_TP为0
4、tmp表在etl表数据覆盖之前是没有值的。
 
 
任务提示
页面:todolist.mxml
页面初始化:ParameterFlexFacade。countTaskBySubject()。另:那个URL是在renderCountTaskList(taskGroup)方法中定义
点每个主题域链接:初始化中的链接,是取缓存access_inf表中的url。
这个表里的url,对技术参数而言是类似于parameter.jsp?subject=X;---》parameter.mxml-----> <taskView:Start> ----> 它指向Start.mxml---> 在parameter.mxml里有一个初始执行函数init()---》 调用执行 main.as里面的init()函数-----》调用startPage.init()---->调用Start.as里面的init()函数
 
 
进入主题域的参数维护页面:
1、“任务批次状态”、“任务生效状态”--->overview.mxml
"录入中"、“待复核”、“复核通过”、“复核不通过”--->ParameterFlexFacade。countTaskByStatus(),保存在response中的batchStatusCountList属性里
2、“同步正式表成功”、“同步正式表失败”。。。。--->保存在response中的effectStatusCountList属性里。
 “同步子系统成功”、“同步子系统失败”、“部分同步共享内存” 三个按钮是否存在,是在ParameterServiceBean。countTaskByStatus(String subjectId)里面做了判断。因为有些表不需要同步子系统,另外一些表不需要同步共享内存。
3、点诸如“录入中”“待复核”等链接。是在overview.as里initQueryButtons()方法中设置了一个监听器,监听函数就是queryTask(),它又调用了ParameterFlexFacade.queryTaskByStatus()方法。
4、至于随之变化的底部的按钮,是在初始化时就保存好的。在点击诸如“录入中”“待复核”等链接并调用了
queryTask(),这个函数会调用initActionButtons()函数,会将初始化保存好的状态信息与各个按钮对应的显示在底部。
5、底部的按钮的action也是在初始化时就设置好的。由ParameterFlexFacade静态调用TaskStatusHelper.init(),这个方法将每个状态对应有多少动作按钮都设置好。会保存在response的statusMap属性里。
6、response中的actionMap属性保存的是涉及流程的操作类型,供之后处理,比如:删除,提交,复核通过,复核不通过等等。
7、switchPage在flex/ParamNew/main.as中定义,函数switchPage(event : MapsEvent)中执行,参数只有三种:OVERVIEW、PARA_QUERY、PARA_EDIT
8、“检索”按钮
9、“创建参数修改任务”和“创建参数删除任务”调用ParameterFlexFacade.queryProdPara(),查询主表和子表相关内容。
10、“创建参数新增任务”不需要查询记录。
11、任务状态“录入中”、“待复核”、“复核通过”等链接下面的按钮如“任务提交”、“任务查看”、“任务信息”、“任务修改”等是保存在response的statusMap里面,
且在ParameterFlexFacade.getGrantedActionMap()函数里面设置。
查询按钮是所有任务状态链接下都有的按钮。
 
 
"创建参数新增任务"\"创建参数修改任务"\"创建参数删除任务"按钮在Query.mxml页面中,点击按钮的触发的函数分别是gotoCreateInsert()、gotoCreateUpdate()、gotoCreateDelete()。
对于修改任务gotoCreateUpdate(在Query.as中):
1、校验是否选中一条记录:getSelectedRecId
2、执行checkOper("U"),调用checkParaOperatable(mainTable.tblId, getSelectedRecId())
3、执行回调函数checkParaOperatableHandler -》 getSwitchEvent("U",recid,eventid)-> ParamNew/main.as中定义的事件switchPage,traget=ParaConstants.PAGE_PARA_FORM
4、mainFrame.selectedIndex = 2;paraEdit.initParaPage(event.data);意思是页面展示Edit.mxml,并且执行Edit.as的initParaPage函数,函数参数是ParaUtil种定义的switchEvent的data
参数中包括target=“PARA_EDIT” type=“U”  recId eventId这四个参数,
5、该initParaPage函数首先执行ParameterFlexFacade.queryProdPara()
6、执行回调函数queryParaHandler() -> shown() 多表的要加上多表 -》 showForm();表数据引入 -> reloadButtons()置入按钮
 
 
 
 
 
 
获取一开始的处理操作,即参数管理中每个表的初始进入页面中“查询”、“任务创建”。
这两个按钮是否存在的判断在:
ParameterFlexFacade.blankGrantedActionList()
1、该用户是否有这两个按钮的权限
2、该主题域是否具有可以查询,可以任务创建的功能。(TBL_MAMGM_PARA_SUB_AREA_INF.ENTRY_WIZD_IN)
3、点“任务创建”后,“创建参数新增任务”“创建参数修改任务”“创建参数删除任务”“查看参数”是由TBL_MAMGM_PARA_TBL_ATTR.MAIN_TP字段控制。位图1111表示上述四个按钮全都存在,0000表示上述四个按钮全不存在。
 
 
 
tmp表数据怎么来的?
1、从etl表读数据到一个rowset中
2、增加一些时间和人的信息
3、给特殊情况的字段赋默认值
 
 
 
商户路由表为什么单拿出来?
商户路由的etl表与tmp表表名不一致。tmp表和tbl表的表名一致。公参同步是将ETL_MAMGM_SETTLE_TRE_MCHNT_INF表(财税库银商户表,该表从商户平台来,且由商户平台发起同步命令)
的一部分内容同步到tbl_mamgm_mchnt_rout_det,另一部分内容同步到tbl_mamgm_mchnt_rout_inf(该表是主表)。
这两个表公参时特殊处理,不走优化后的公参代码。
 
 
卡号转换表没有etl表?
不是所有tmp,tbl表都有对应的etl表,etl是给公参同步时,外系统用的
 
 
公参同步的web services接口在: 
BatchSynchResultNotifyImpl。notify()
这个方法调用EJB,EJB的名字是CommonParaJmsService,它又对应了CommonParaJmsServiceBean。sendJmsRequester()来处理
 
 
查看目录下文件或文件夹得大小,并按照从大到小排序
du -sg * |sort -nr
 
 
在VI中,将字符串str1替换成str2
:g/str1/s//str2/g
 
aix中vi一文件,删除^M符号,执行如下命令:
:%s/^V^M//
:%s/^M//
^V和^M指的是Ctrl+V和Ctrl+M
 
 
公参同步任务是如何执行的?
商户平台使用web services访问接口BatchSynchResultNotifyService,而这个类BatchSynchResultNotifyImpl又用ejb的形式调用了local接口CommonParaJmsService。并由CommonParaJmsServiceBean.sendJmsRequester()
通过CommonParaSyncRequester给JMS服务队列发送消息,MsgProperty是"common_para_sync"。
 
CommonParaSyncMDB 通过JMS消息队列 接收到这个消息后,把ObjectMessage转发给CommonParaSyncEventBean,由ObjectMessage中的MsgProperty决定,把ObjectMessage中包含的两个参数,一是参数类型,一是批次号。
发给CommonParaSyncMainOperBean。operEtl来处理
 
1、正在同步的公参批次,如果由另外一页面发起强制同步的话,很容易报911,表锁问题;原因在改ETL表的状态为1时与MERGE语句使用了相同的表。
2、公参成功后,查看的是紧接着的同参数类型的一个批次是否成功,如果是待同步,则执行,如果是成功的就不会往下做了。隔着的那些待同步批次不会执行的。
 
公共参数管理页面对应的jsp:
/com/cup/maps/portal/jpf/flex/CommonParaQuery.jsp
“重新同步”命令调用ParameterFlexFacade.reSyncCommonPara(String batNo,String paraTp,boolean force)函数。
该函数调用 CommonParaJmsService.sendJmsRequesterForce()  发送jms消息,(跟商户平台的公参同步类似,不过它走了另外一个函数sendJmsRequester)
 
 
“重新同步”与“强制同步”均要走同步正式表和生效接口,它们的不同在于:
1、“强制同步”无视 还小的批次号,可以绕过之前失败的批次做同步。
2、如果该批次同步成功,公参任务表的最终状态会改成“3-强制同步成功”
 
 
研究院-电话支付-CVS
:pserver:leishen@172.17.238.150:2401/cvsout
Module:tams
 
checkout某一标签tag的cvs文件:
cvs co -r branch_tipsp_codemerge_20120530 isvr_mgm
查看标签语句
cvs status -v
 
 
 
ant在编译指定文件夹中的java类时,会将该java类引用到的所有java类同时编译。
在打war时就可以把引用到的java生成的class文件一起打入war包中。
 
 
db2在某一列创建索引时会让你选择该列是否设置成unique。
 
 
 
对于显示的查询结果,如果要有水平的滚动条,需要修改这个dataGrid的属性,
增加一个:horizontalScrollPolicy="auto" 
 
 
商户同步的参数中,也就下面表需要编辑。其它的都是自动生效的
卡bin 01010601  TBL_MAMGM_BIN+TBL_MAMGM_BIN_REGION 0000000000
机构信息(成员机构静态信息表)  01010101 TBL_MAMGM_INS_STATIC_INF 0000000000
商户类型表 01071101 TBL_MAMGM_MCHNT_TP 0000000000
交易代码表 01071401 TBL_MAMGM_TRANS_ID 0100000000
 
 
行业机构静态信息表:服务提供机构、渠道接入机构、行业商户
industry_ins_static_inf 
成员机构信息表:多渠道平台、银联总分公司、转接机构、发卡机构、收单机构
ins_static_inf
商户静态信息表:直连终端商户、渠道接入机构商户、服务提供机构商户、行业商户、虚拟商户
mchnt_static_inf
终端静态信息表:直连POS、ATM、电话终端、各种虚拟终端
term_static_inf
 
 
对于“参数同步”这个交易,tbl_mamgm_para_tbl_attr中配置了两条记录如下:
TBL_CDTBL_NMTBL_NM_CNMA_SUBSYS_BMPSUB_CDENTRY_WIZD_SEQ
0803010208030102参数同步到数据库(返回)00010000000803011
0803010108030101参数同步到数据库(发送)11000000000803010
OnlCommon.getSTMGBySubCd(subjectId,subsysId);
该函数取ENTRY_WIZD_SEQ=0的记录,由subsysId(是BAT、ONL)来得到联机或者批量的默认节点
OnlCommon.getRTMG(subjectId);
该函数取管理的默认节点(节点的意思是tbl_maps_gfs_deploy_inf这张表的一条记录,包括ip,port,openid等信息)
 
 
 
批量应用重启:
taskcom stop all
 停应用
 MPubTask &
 启动
 
 
管理数据库停止后,再开启,不影响管理应用继续使用,管理应用无需重启即可。
jdbc:db2://172.17.252.84:60032/mamgmdb
是ma_onldb/ma_onl用户建的。端口60032是这个用户在/etc/services文件设置好的。
ma_onldb@/etc>cat /etc/services |grep 60032 
DB2_ma_onldb    60032/tcp
 
 
 
 
多渠道管理有5个web service 接口,页面上可以测试。CommonParaJmsServiceBean类是第一层处理接口:
1、公参管理
http://172.17.252.85:4866/maps_service/BatchSynchResultNotifyService?wsdl
http://172.17.252.63:7001/csb/shcenter/BillDomain/MultiAcquiringSystem/ParamSyncNotiry/ParamSyncNotiryProxy?wsdl
 
http://172.17.248.158:40423/maps_service/BatchSynchResultNotifyService?wsdl
http://172.17.248.40:4867/maps_service/BatchSynchResultNotifyService?wsdl
 
 
2、改变交易规则状态交易(changeFilterAppInf)
改变指定商户的交易状态(changeMchntTransSt)
改变指定终端的交易状态(changeTermTransSt)
根据任务事件号查询的事件状态(queryTransSt)
http://172.17.252.85:4866/maps_service/TransStateAndRuleSwtService
 
3、行业机构状态查询
http://172.17.248.74:8888/MapsServicePortal/IndustryInsStateActionService?wsdl
 
4、bps接口
http://172.17.248.74:8888/MapsServicePortal/BpsServiceImplService?wsdl
对应csb地址:
http://172.17.252.63:7001/csb/shcenter/BillDomain/MultiAcquiringSystem/BpsServiceImplService/BpsServiceImplServiceProxy?wsdl
 
5、多渠道交易状态查询接口(过滤应用信息表状态、商户状态、终端状态查询) 未上线
http://172.17.248.74:8888/MapsServicePortal/TransStateActionService?wsdl
 
 
6、供mtqj调用接口
http://172.17.248.74:11000/MapsServicePortal/MjcCallActionService?wsdl
 
7、手工交易
http://172.17.248.74:11000/MapsServicePortal/MjcCallActionService?wsdl
 
 
MTQJ的webservice地址
http://172.17.252.88:10000/mjc/MtqWebService?wsdl
 
 
 
行综平台管理系统目前有1个web service 接口
csb地址:http://172.17.252.63:7001/csb/shcenter/BillDomain/IntegratedServicePlatformForIndustry/IsvrBatchParaSynchNotifyService/IsvrBatchParaSynchNotifyServiceProxy
对应的行综环境:http://172.17.248.188:7004/IsvrServicePortal/BatchParaSynchNotifyService?wsdl
 
 
csb地址:
http://172.17.252.63:7001/sbconsole
用户名/密码:weblogic/weblogic
多渠道在Projects->csb->shcenter->MultiAcquiringSystem
行综在Projects->csb->shcenter->IntegratedServicePlatformForIndustry
 
 
 
通讯重启:
1、hgcom1/nasa/bin/reload_cfg 100 300 0 shutdown
2、mtqshutdown
3、mtqstartup
4、hgcom1/nasa/bin/nasad
5、shmadmin
   5.1--- h
   5.2--- create COMALL
   5.3--- q
6、reload_cfg 100 300 0 start
7、ml
8、ps -ef |grep $USER
 
 
 
用户管理平台(权限相关):
系统权限导入:只会更新已有数据+插入新增数据。不会删除系统已有数据。
 
 
EJB3里面
@TransactionAttribute(TransactionAttributeType.NEVER)的函数中,调用了
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)的函数,子函数的事务不起作用,无法回滚
 
 
bytes[]类型的参数同步后的数据与etl表原始数据不一致,最后部分的00 00 00内容被截断了,需要修复。
修改:SqlUtil.java下面这行
fieldValue = StringUtils.defaultString(new String(rowset.getBytes(fieldCount))); //byte[]的类型特殊处理
 
 
管理系统使用DBPM
自己开发一应用程序,用modifyPasswd.sh执行,读取config.properties配置的DBPM服务器地址,通过socket的方式获得数据库密码。
然后调用调用WLST工具类,修改Domain中的JDBC数据源中设置的密码。
然后启动domain。
 
下面5个交易由之前的同步交易,改成异步交易,发送流程是:首先管理发MTQ消息给联机1,联机1通过通讯发给CUPS,cups做完后会返回结果给联机,但是由于通讯是负载均衡的,所以有可能发给了联机2,联机2通过异步邮箱134, 发送给管理,管理得到134邮箱的内容后,会更新联机交易日志表(manage_trans_log),此时管理端仍然在轮询联机日志表,找到状态是1(收到事件请求报文),2(已经事件处理完毕),99(出错)的对应event_id记录后,返回前台成功或出错信息,如果超过60秒,仍然没有找到,那么返回前台超时标志。
签到:多渠道向cups签到,激活状态。
签退:多渠道向cups签退。
申请重置密钥:通知cups,让cups给成员机构发送密钥。
重置密钥下发:通知行业机构重置密钥
线路测试:通知cups,让cups给成员/行业机构发送测试交易。
 
终端签到:
先去查联机的终端静态表,如果状态为1-冻结,直接报错,如果状态为0,接着校验交易位图等,最后更新联机终端动态表状态为0-开启。
终端状态启用冻结
只更新联机的终端静态表
 
 
 
查找主题域/表对应的下拉框的内容:
select t5.sub_cd,t5.SUB_NM_CN,t4.TBL_CD,t4.TBL_NM_CN,t1.* 
from TBL_MAMGM_DRDL_ITEM_DEF t1,TBL_MAMGM_DRDL_CFG t2,
tbl_mamgm_para_fld_attr t3,tbl_mamgm_para_tbl_attr t4,TBL_MAMGM_PARA_SUB_AREA_INF t5
where t1.DRDL_ID = t2.DRDL_ID and t2.DRDL_NM = t3.DRDL_VAL_TBL_NM
and t3.tbl_cd = t4.TBL_Cd and t4.SUB_CD = t5.SUB_CD
and t4.TBL_CD = '07010301'
and t5.SUB_CD = '070103';
 
公参同步用到的一系列表:
select * from TBL_MAMGM_PARA_SYNC_TASK;
select * from TBL_MAMGM_PARA_TASK;
select * from TBL_MAMGM_ACCESS_INF;
select * from TBL_MAMGM_PARA_SUB_AREA_INF;
select * from TBL_MAMGM_PARA_TBL_ATTR;
select * from TBL_MAMGM_PARA_FLD_ATTR;
 
 
 
取得当前时间:
select current timestamp from (values 1);
取得sequence的下一取值:(两种方法)
select nextval for sqn_mamgm_ei from (values 1);
select nextval for sqn_mamgm_ei from sysibm.dual;
values nextval for sqn_mamgm_ei;
设置管理数据库的REC_ID对应的sequence下一取值为108000003
alter sequence ma_mgmdb.sqn_mamgm_ri restart with 8000003
 
CHAR型转INTEGER
select CAST(INS_ID_CD AS INTEGER) max from etl_mamgm_ins_static_inf;
 
 
TBL_MAMGM_PARA_FLD_ATTR表中配置的字段如果少于TBL表中的字段,在创建新增参数任务、创建修改参数任务时都会报错。
具体表现为:
1、关闭记录时tmp记录删不掉。
2、修改参数任务时也没显示的字段值不对应。
 
 
下拉框配置表TBL_MAMGM_DRDL_CFG:
DRDL_TP: 2 表示用sql执行的结果,进入页面时,读数据库一次下拉框的代码
DRDL_REMARK:sql语句
SHOW_KEY_IN: 0 表示格式像“代码中文名称”    1 表示格式像“代码-代码中文名称”
DRDL_SORT_TP: 1 
 
 
 
JMS server参数配置:
Messages Maximum: -1。 JMS消息队列最大值。设为-1表示没有限制,容易引起内存不足。
Maximum Message Size:2147483647  The maximum number of bytes allowed in individual messages on this JMS server
 
 
虚拟终端确定信息表TBL_MAMGM_VIRTUAL_TERM_DET的ETL表比TBL表多一个字段CUP_BRANCH_INS_ID_CD,此时无论公参优化前后,该表都可以同步成功。
但是如果公参同步失败,需要页面上人工操作,走参数维护流程,那么将出错,
出错情况和上面所讲的TBL_MAMGM_PARA_FLD_ATTR表中配置的字段如果少于TBL表中的字段情况相同。
 
 
目前多渠道代码的问题缺陷错误:
1、TBL_MAMGM_DRDL_ITEM_DEF.drdl_id=9254名称写错:“本平手工台录入”
2、商户黑名单etl_MAMGM_MCHNT_BLKBILL没有sync_bat_no字段,无法做公参同步,报错。好在这个表联机批量都不用。
3、中奖奖项限制配置表TBL_MAMGM_PRIZE_LIMIT_CFG该表没有ETL表,但是该表是子表且pub_para_cd值为空,该表不做同步处理,公参同步时不报错。
4、子表被删除了,在页面中通过主表查询子表内容还是能看到。
5、下拉框表TBL_MAMGM_DRDL_CFG中,WINUSEFLG有2个。
 
 
java的substring问题
String ss = "1234567890123456";
System.out.println(ss.substring(1,2));//2
System.out.println(ss.substring(2,4));//34
System.out.println(ss.substring(5,8));//678
 
 
 
在参数删除时,不对字段进行校验
ParameterFlexFacade.checkParaByValidators()根据Validator进行校验
 
 
新建“链路信息表”记录时,输入“链路编号”字段,只有两位,保存到TMP表以后,该字段变成13位,原因:
TBL_MAMGM_PARA_TBL_ATTR配置表时,BEFORE_INSERT_EXP字段配置了处理代码,如下:
import com.cup.maps.parameter.util.*;
 String s=map.get("LINE_NO"); if (s.length()==2) 
{ map.put("LINE_NO",map.get("ACCESS_INS_ID_CD")+s); 
ParaExpressions.checkExistRecordForTask("01100701", map);  }
此外该表在TBL_MAMGM_PARA_VFY中有很多校验信息,具体有15条,列出如下:
无效的接入系统标识!
链路编号C开头本方监听端口应为0
链路编号A开头本方监听端口不为0
链路编号C开头对方监听端口不为0
链路编号A开头对方监听端口应为0
本方监听端口输入错误!
对方监听端口输入错误!
登录用户不能为空
登录密码不能为空
短信窗口大小不能为空
短信源发序列号不能为空
短信接入角色不能为空
检测时间间隔不能为空
单条链路超时时间不能为空
接入模式 0001 /0006,才能选支持
 
 
在管理应用上部mtq时,除了常规参数配置外,还要保证/glb/mtq/etc/mtq.ini文件中
SHMKEY_MB和MSGKEY这两个参数,在应用主机上与其他用户的mtq配置的不重复。
 
 
用winrar软件更新jar文件中的一个class,压缩进去,生成的新的jar文件,仍然可以像之前一样引用,且更新的地方也会生效。
 
假如程序A.java引用了XX.JAR包中的B.java,且B.java又引用了XXX.JAR中的内容。那么:
1、把B.java打成XX.jar包的操作,不应该将XXX.JAR打入XX.JAR中
2、在javac A.java时,classpath应该只包括XX.jar和.
3、在执行java A.java时,应该将XX.JAR和XXX.jar均包进classpath中。
例子Testjar.java中引用了tools.jar的XmlRead类,而XmlRead类又引用了dom4j-1.5-rc1.jar包的内容,下面是正确编译和执行的语句:
D:\>javac -classpath "d:/tools.jar" Testjar.java
D:\>java -classpath ".;d:/tools.jar;D:/workspace/TOOLS/lib/dom4j-1.5-rc1.jar" Testjar
 
 
 
下面两个sql,第一个取全部字段,走全表扫描,第二个sql由于取主键,走索引。两边取出的值不一定一样。
select * from ETL_MAMGM_TERM_STATIC_INF where sync_bat_no = 999 fetch first 1000 rows only with ur;
select term_id,mchnt_cd,sync_bat_no from ETL_MAMGM_TERM_STATIC_INF where sync_bat_no = 999 fetch first 1000 rows only with ur;
 
 
 
商户折扣信息表,中奖等级表,中奖基本表等按照规划是营销平台通过公参平台公参同步到多渠道,但是营销平台没有这些接口,
多渠道本身也没有用这些表。
 
 
商户黑名单和卡号黑名单这两张表是在商户维护的吗?
答:是风险平台维护。但现在他们还没有作
 
mtq.ini中有:
BEGIN GROUP
31  172.17.252.87  8113  20  S
END   GROUP
 
mtq重启以后,端口8113会被监听
netstat -an|grep 8113
查看当前用户的进程
ps -ef |grep mtq|grep $USER
BEGIN GROUP里面的配置的S要大写。
0   172.17.248.57  8100  20  S这个0的行是什么含义?
异步邮箱组连接数及发送报文个数:
mtqmng list或者ml(需要创建别名alias ml="mtqmng list")
 
 
su - iisp1onl
iisp1onl@/iisp/usr/iisp1onl>db2 connect to ISMGMDB user iisp1db using iisp1db
db2 reorg table ma_mgmdb.TBL_MAMGM_MSG_FMT_CONV_MTO
 
 
多渠道管理回归数据库82
telnet 172.17.252.82
su - ma_mgmdb
db2 list db directory
/maps/usr/ma_mgmdb>db2 connect to GMAMGMDB user ma_mgmdb using ma_mgmdb
db2 reorg table ma_mgmdb.etl_mamgm_mchnt_static_inf
db2 reorg table ma_mgmdb.tmp_mamgm_mchnt_static_inf
db2 reorg table ma_mgmdb.tbl_mamgm_mchnt_static_inf
 
 
查询db2错误代码
db2 ? sql-30082|more
 
 
 
82联机回归数据库,发生668错误
maps/usr/ma_mgmdb>db2 connect to GMAONLDB user ma_onldb using ma_onldb
db2 runstats on table ma_mgmdb.TBL_MAMGM_AUDIT_LOG2
/maps/usr/ma_mgmdb>db2 reorg table TBL_MAONL_MCHNT_STATIC_INF
 
 
 
获取前台flex发送到后台的值
OnlCommon.getSentFlied(String subjectId, Map<String, String> map) 
根据主题域ID取到参数表对象列表
OnlCommon.java     List<ParaTable> getParaTable(String subjectId)
 
 
过滤应用信息的下拉内容来源于业务参数(fml域转换配置信息表),
 
 
成员机构静态信息表在页面上做“创建参数修改任务”后,复核通过,会在同步正式表成功那里卡住,
然后在“参数刷新-参数同步到共享内存”页面做了参数刷新以后,回到参数管理页面,该参数已在同步成功栏内。
刷新共享内存及更新para_task状态的地方在:SyncExecuteBean.refreshSchemeStatus(Map<String, String> map)
这里面maps的内容是子系统subsysCd和内存编号zoneId
这个函数做了两件事:
1、更新TBL_MAMGM_PARA_TASK_SYNCSHM_STATUS状态为4-成功
2、更新TBL_MAMGM_PARA_TASK为S-同步成功或者A-部分同步到共享内存成功
 
 
同步子系统的地方:
ParaSyncServiceBean。sendMsg(ParaTask batch, Map<String, String> map)
需要的内容包括:batch里面的eventid,map里面的子系统名称、多个表名
 
 
db2取当前时间
SELECT current date FROM SYSIBM.DUAL;--取得当前年月日
SELECT current time FROM SYSIBM.DUAL;--取得当前时分秒
SELECT current timestamp FROM SYSIBM.DUAL;--取得当前年月日时分秒
select current timestamp,microsecond(current timestamp) from SYSIBM.DUAL;
select 1,to_char(current timestamp,'yyyymmdd') from sysibm.dual;--日期格式
 
axis,unix取当前时间
dateWed Mar  9 11:22:07 GMT+08:00 2011
date +%Y2011
date +%y11
date +%m03
date +%M22
date +%d09
date +%D03/09/11
date +%S07
date +%s1299669809
 
 
错误:
DB2 SQL error: SQLCODE: -20154, SQLSTATE: 23513, SQLERRMC: MA_MGMDB.VIW_MAMGM_AUDIT_LOG;2
sqlcode-20154原因:指定的视图包含一个UNION ALL查询
1、不符合任何基础基表的检查约束。
2、满足所有多个基础基表检查约束。
解释:视图VIW_MAMGM_AUDIT_LOG是由TBL_MAMGM_AUDIT_LOG1和TBL_MAMGM_AUDIT_LOG2这两个表组成的。在这两张表的create时,
没有增加CHECK (SUBMIT_MON BETWEEN 1 and 6)和 CHECK (SUBMIT_MON BETWEEN 7 and 12)语句,导致在insert viw时,db2不知道要插入哪张表。
 
 
 
db2 修改字段属性
alter table tmp_maps_gfs_fmt_grp alter trantype set data type char(6);
select current schema from sysibm.dual
db2 values current schema
 
菜单的顺序是跟access_inf表的event_id相关的。只有event_id相同的情况下,才看access_cd.
 
unix vi命令
01 G   移至最后一行行首
02 nG   移至第n行行首
03 n+   下移n行,行首
04 n-   上移n行,行首
05 n$   下移n行(1表示本行),行尾
06 0   所在行行首
07 $   所在行行尾
08 ^   所在行首字母
09 h,j,k,l 左移,下移,上移,右移
10 H    当前屏幕首行行首
11 M   屏幕显示文件的中间行行首
12 L   当前屏幕最底行行首 
 
 
 
管理系统里面不常用的两个sequence:
TBL_MAMGM_FLOW_CD的主键Sequence
public static final String TBL_MAMGM_FLOW_CD_KEY="sqn_mamgm_fck";
审计日志sequence
public static final String AUDITLOG_SEQUENCE = "sqn_mamgm_aui";
 
 
 
db2中select语句最多可以选择1012个字段,超过以后就会报sqlcode=840的错误。说选择的列太多。
ultraedit每行最多显示4096个字符
感觉db2的sql长度没啥限制一个18k的select语句也是可以被执行的。
如果select出来一个字段没有值,那么rs.getString()取出来的值是空:"",并不是null
 
我们的页面根本没有对用户的权限做限制,比如:
在url上输入:https://172.17.252.85:8889/maps/com/cup/maps/portal/jpf/flex/cacheRefresh.jsp
然后再登录的地方输入分公司的用户名和密码
页面仍然可以显示,并且刷新的功能也能完成。
 
查看aix的版本
oslevel
 
 
将System.out.println输出到文件中。
OutputStream os = new FileOutputStream("d:/output.txt");
PrintStream p = new PrintStream(os);
System.setOut(p);
System.out.println("ee");
 
从jar文件中读取资源文件
//方法一,直接读取该文件的每行内容
BufferedReader br1 = new BufferedReader(new InputStreamReader(
    ((ReadXmlFileFromJar.this.getClass().getResourceAsStream("1.txt")))));
String s1;
while((s1=br1.readLine())!=null)
System.out.println(s1);
 
 
//方法二,读取xml文件内容后组装成document对象
BufferedReader br = new BufferedReader(
new InputStreamReader(((ReadXmlFileFromJar.this.getClass()
.getResourceAsStream("1.xml")))));
String s;
while ((s = br.readLine()) != null)
System.out.println(s);
 
SAXReader saxReader = new SAXReader();
Document document;
try {
document = saxReader.read(ReadXmlFileFromJar.this.getClass()
.getResourceAsStream("1.txt"));
Element incomingForm = document.getRootElement();
String ss = document.asXML().toString();
System.out.println("ss=" + ss);
} catch (DocumentException e) {
e.printStackTrace();
}
 
 
从jar中读取资源文件
1、方法一
URL fileURL=this.getClass().getResource("/resource/res.txt");   
System.out.println(fileURL.getFile());  //file:/C:/ResourceJar.jar!/resource/res.txt
 
2、方法二
InputStream is=this.getClass().getResourceAsStream("/resource/res.txt");   
        BufferedReader br=new BufferedReader(new InputStreamReader(is));  
        String s="";  
        while((s=br.readLine())!=null)  
            System.out.println(s);  
 
 
参数查询角色功能代码 :1001999014
是指参数维护页面上那个查询按钮
 
 
下面这条sql的执行计划是:
1、首先执行4)中的子查询,IXSCAN
2、然后执行3)查询表TBL_MAPS_GFS_TASK,TBSCAN
3、对1、2的查询结果进行HSJOIN,从而获得了行号ROWNO_以及t.*
4、对查询的结果进行排序bmqid
5、选取前40行记录
 
1)SELECT ROW_NUMBER() OVER() AS ROWNO_, t.*                                             
2)FROM TBL_MAPS_GFS_TASK t                                                              
3)WHERE OPER_IN != 'd'                                                                  
4)AND (node_id in  (select NODE_ID from TBL_MAPS_GFS_DEPLOY_INF where SUBSYS_CD='BAT')) 
5)order by bmqid                                                                        
6)FETCH FIRST 40 ROWS ONLY
 
下面这条sql不同的地方就是第4)行,但是db2的执行计划就变成了:
因为node_id是索引查询,3)、4)、5)条件一起执行,IXSCAN,
然后再获得排完序的行号ROWNO_
 
1)SELECT ROW_NUMBER() OVER() AS ROWNO_, t.* 
2)FROM TBL_MAPS_GFS_TASK t 
3)WHERE OPER_IN != 'd'
4)AND (node_id in  ('21','22')) 
5)order by bmqid 
6)FETCH FIRST 40 ROWS ONLY
 
 
DB2存储主键的地方
select * from SYSIBM.SYSKEYCOLUSE;
select * fROM sysibm.SYSINDEXES;--存储索引
select * from sysibm.syscolumns;--存储字段
select * from sysibm.systables;
select * from SYSIBM.SYSTABLESPACES;
select * from sysibm.sysschemata;
 
 
 
java中读取下拉框内容:
TransMonitorFacade.getDrdp(String name, false)
 
 
数据库中DECIMAL (8,2)
表示的意思是:
小数点前的位数最多是6位,小数点后的位数一定是2位,不够的话补0
 
 
appCfg/config.properties文件中的provider_url是给管理系统自己的webservice用的EJB接口
 
 
 
 
 
ajax发送到后台的字符编码与form提交使用的字符编码不同
正确的代码:
 
javascript:GET方式
var phone = document.getElementById("phone").value;
var url = "<%=request.getContextPath()%>/upload?phone=" + (phone);
url = encodeURI(url);
req.open("GET", url, true);
req.onreadystatechange = updatePage;
req.send(null);
 
java:
String phone = request.getParameter("phone");
phone = new String(phone.getBytes( "ISO-8859-1"), "UTF-8");
//设置响应内容类别  
response.setContentType("text/html;charset=UTF-8");
response.setCharacterEncoding("UTF-8");
//传回浏览器
response.getWriter().println("i know your phonedddd d的上少时诵诗书 : "+phone);
//不需再forward
 
 
javascript:POST方式
var xmlString = document.getElementById("phone").value;
xmlString = encodeURI(xmlString);
var url = "<%=request.getContextPath()%>/uploadxml";
req.open("POST", url, true);
// Tell the server you're sending it XML
req.setRequestHeader("Content-Type", "text/xml");
// Set up a function for the server to run when it's done
req.onreadystatechange = confirmUpdate;
// Send the request
req.send(xmlString);
 
java端后台,接受XML格式 + POST方式,乱码解决:
StringBuffer xml = new StringBuffer();
String line = null;
BufferedReader  reader = request.getReader();
while((line=reader.readLine())!=null)
xml.append(line);
String temp = xml.toString();
temp =  java.net.URLDecoder.decode(temp, "UTF-8");
//设置响应内容类别  
response.setContentType("text/html;charset=UTF-8");
response.setCharacterEncoding("UTF-8");
//传回浏览器
response.getWriter().println("i know your phonedddd d的上少时诵诗书 : "+temp);
 
 
 
浏览器访问链接上有中文时,如http://localhost/import/dbpatch?ss=aaa东东东东dd,浏览器会转成如下链接:
http://localhost/import/dbpatch?ss=aaa%B6%AB%B6%AB%B6%AB%B6%ABdd
doGet方法中有两种方式获取:
1、String query = request.getQueryString();
System.out.println("query="+query);//ss=aaa%B6%AB%B6%AB%B6%AB%B6%ABdd
query = java.net.URLDecoder.decode(query, "gbk");//直接访问的servlet
System.out.println("query2="+query);//ss=aaa东东东东dd
2、String ss = new String(request.getParameter("ss").getBytes("iso8859-1"),"gbk");//说明requst.getParameter方法做了转码decode
System.out.println("@@@@@@@ss="+ss);
 
 
DB2
如果一个字段设置为NOT NULL 但是没有默认值。比如如下语句:
CREATE 
    TABLE a 
    ( 
        MSG_SPEC_TP CHARACTER(4) DEFAULT ' ' NOT NULL, 
        INS_ID_CD_CAPTURE_MD CHARACTER(1) NOT NULL, 
        INS_ID_CD_CAPTURE_EXPRESS VARCHAR(152) NOT NULL,
        RID CHARACTER(10) DEFAULT ' ' NOT NULL,
        CONSTRAINT TIX_MAMGM_MIT_PK PRIMARY KEY (MSG_SPEC_TP) 
    );
那么在INSERT记录的时候,就必须带上该列,
甚至可以在该列的VALUES里面填'',当然不能不填或者填个NULL
 
正确:INSERT INTO a(MSG_SPEC_TP,INS_ID_CD_CAPTURE_MD,INS_ID_CD_CAPTURE_EXPRESS)VALUES('5555','','');
(注:执行上述语句后,VARCHAR类型的字段值是'',而CHAR类型的字段值是' ',多一个空格,是DB2数据库自动添加的值。)
错误:INSERT INTO a(MSG_SPEC_TP,INS_ID_CD_CAPTURE_MD,INS_ID_CD_CAPTURE_EXPRESS)VALUES('5555',,'');
错误:INSERT INTO a(MSG_SPEC_TP,INS_ID_CD_CAPTURE_MD,INS_ID_CD_CAPTURE_EXPRESS)VALUES('5555',null,'');
错误:INSERT INTO a(MSG_SPEC_TP,INS_ID_CD_CAPTURE_MD)VALUES('5555','');
错误:INSERT INTO a(MSG_SPEC_TP,INS_ID_CD_CAPTURE_EXPRESS)VALUES('5555','');
 
如果这个列有默认值,那么INSERT语句就可以不出现该字段,比如上述的正确语句中就没有RID字段。
 
 
 
在FLD_ATTR中字段名配置为小写,不影响其在页面上进行录入,但是查询的时候字段值会显示不出来。
 
从cache中读取下拉框的值
List<Map<String, String>> ParameterFlexFacade.getDropdownListByFld(String fldCd)
 
 
TBL表中重复的EVENT_ID也没有关系
同步正式表的操作:ParaSyncServiceBean.activate。从batch取出的event_id是从TMP表中取得记录,然后根据记录的主键值
更新TBL中的记录。
 
 
appCfg/securityClient.properties文件详解:
defaultSSOUrl=http://172.17.249.56:6008
##maps ip
172.17.252.85=http://172.17.248.56:6008
##F5 ip
172.17.248.31=https://172.17.248.31:1215
Remote_NewSecurityEJB_Url=t3://172.17.248.56:6008
##maps system str assigned by sso
SysIdStr=6018724E9A708E13CB0156465E8E8384
isPortalLogin=false
loginClassName=com.cup.portal.security.utils.CupPortalSecurityUtil
 
 
如果Remote_NewSecurityEJB_Url这个配错了的话,重启后登陆会报如下错误:
Caused by: java.net.UnknownHostException: 172.17.258.56
        at java.net.InetAddress.getAllByName0(InetAddress.java:1275)
        at java.net.InetAddress.getAllByName(InetAddress.java:1197)
        at java.net.InetAddress.getAllByName(InetAddress.java:1119)
        at weblogic.rjvm.RJVMFinder.getDnsEntries(RJVMFinder.java:409)
        at weblogic.rjvm.RJVMFinder.findOrCreate(RJVMFinder.java:180)
        at weblogic.rjvm.ServerURL.findOrCreateRJVM(ServerURL.java:153)
        at weblogic.jndi.WLInitialContextFactoryDelegate.getInitialContext(WLInitialContextFactoryDelegate.java:352)
        ... 24 more
com.cup.newSecurity.exception.LdapBaseException: 
        at com.cup.securityClient.client.service.UserService.getLoginUserAndPrivileges(UserService.java:95)
        at com.cup.maps.portal.common.filter.SessionFilter.doFilter(SessionFilter.java:66)
        at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:42)
        at com.cup.maps.portal.common.filter.SetCharacterEncoding.doFilter(SetCharacterEncoding.java:64)
        at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:42)
        at edu.yale.its.tp.cas.client.filter.CASFilter.doFilter(CASFilter.java:221)
        at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:42)
        at weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.run(WebAppServletContext.java:3496)
        at weblogic.security.acl.internal.AuthenticatedSubject.doAs(AuthenticatedSubject.java:321)
        at weblogic.security.service.SecurityManager.runAs(Unknown Source)
        at weblogic.servlet.internal.WebAppServletContext.securedExecute(WebAppServletContext.java:2180)
        at weblogic.servlet.internal.WebAppServletContext.execute(WebAppServletContext.java:2086)
        at weblogic.servlet.internal.ServletRequestImpl.run(ServletRequestImpl.java:1406)
        at weblogic.work.ExecuteThread.execute(ExecuteThread.java:201)
        at weblogic.work.ExecuteThread.run(ExecuteThread.java:173)
 
 
 
 
java文件中:
String s = "工作就";
使用各种编码进行javac,语句如:javac -encoding GBK TestString.java
然后class文件中这三个汉字如何显示。
 
iso8859-1
String s = "\271\244\327\367\276\315";
默认编码
String s = "\u5DE5\u4F5C\u5C31";
GBK
String s = "\u5DE5\u4F5C\u5C31";
UTF-8
String s = "\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD";
 
编成class文件以后,这个字符串的长度,就是用length()函数得到的长度就比较好理解了。
用iso8859-1编码进行编译后执行length()函数得到的长度是6,gbk编码进行编译的长度是3,utf-8编码进行编译的长度也是6。
 
注:
java中byte使用1个字节(8 bit)表示,char使用2个字节(16bit位)来表示。
 
 
还可以按某种编码来执行,如下:
java -Dfile.encoding=ISO8859-1 TestString
 
 
查看哪个进程绑定哪个邮箱
mtqmng pid
 
 
管理应用上的mtq是为了异步邮箱而安装的,生产上面两台管理应用就有两台MTQ,其中mtq2没有作用。
因为第二台管理上getmsgservice这个线程在启动时,读取deploy_inf表中的管理MGM默认节点,所以会与mtq1的134邮箱绑定。
同步模块在往管理发的时候也仅仅发送31号管理应用,也即第一台管理。
 
 
在Unix下获取多个IP的方法
ifconfig -au |grep inet |grep -v inet6 |grep -v 127.0.0.1 |awk '{print $2}'
 
 
 
EVENT_ST:事件状态
0-交易已发送
1- 交易被接受
2 - 交易已处理
99-交易出错
RESP_CD:请求应答码
00 - 成功
01 - 失败
99 - 确认收到请求/应答报文
response.code:返回报文中的应答码
00 -交易成功
XX-交易已接受
其它  - 交易失败
 
记联机交易日志MANAGE_TRANS_LOG时,首先根据逻辑一得出EVENT_ST:
if response.code == 00
EVENT_ST = 2
else if response.code == XX
EVENT_ST = 1
else
EVENT_ST = 99
 
然后根据逻辑二得出RespCode:
if ("99".equals(EVENT_ST)) {
tmmtl.setRespCode("01");
} else if ("2".equals(EVENT_ST)) {
tmmtl.setRespCode("00");
} else if ("1".equals(EVENT_ST)) {
tmmtl.setRespCode("99");
}
但是,在读取异步邮箱的代码GemMsgService中,却忘记了逻辑二,
直接将response.code中的代码更新到联机交易日志MANAGE_TRANS_LOG的RESP_CD字段。
 
 
 
删除子表记录:应该在创建修改任务中,再选择新增、修改、删除子表记录。
 
 
172.17.252.85上ma_mgm用户/mgmtest目录有最大50m的限制。
 
 
可以在console中的Security Realms->myrealm->users and groups ->点用户->passwords->save,
然后修改/mapsDomain/servers/MapsServer/security/boot.properties,这样该用户的登录weblogic的密码就改好了。
但是,改完之后执行stopWL.sh的时候报错,说密码错误。要改动bin/stopWebLogic.sh把其中的password改成正确的。就可以关掉weblogic了(或者删除也可以)
 
 
反编译资源文件
native2ascii -reverse -encoding gbk MessageResources.properties MessageResources_cn.properties
 
 
查看AIX系统资源
cpu: 
vmstat(lcpu=8逻辑cpu有8个) 
prtconf( Number Of Processors: 4         ==》物理cpu有4个)
查看系统使用情况  topas
 
查看aix内存svmon -G
例:
              size       inuse        free         pin     virtual   mmode
memory      2621440     2612781        8659      640841     3284826     Ded
pg space    1048576      898467
单位是4k,memory是实际物理内存:2621440*4/1024/1024=10g,
pg space是换页空间大小:1048576*4/1024/1024=4g
 
 
aix上查看java进程所占内存
svmon -P pid
例:
svmon -P 52363278
-------------------------------------------------------------------------------
     Pid Command          Inuse      Pin     Pgsp  Virtual 64-bit Mthrd  16MB
52363278 java            132076     7764     5865   158615      Y     Y     N
进程实际使用内存Inuse:132076*4/1024 = 516M
 
 
查看AIX系统资源
prtconf
 
 
逻辑cpu
topas
bindprocessor -q
vmstat
 
物理cpu
prtconf
 
查看cpu的详细信息,如主频,是否支持SMT,是否开启了SMT等等
lsattr -El proc0
 
查看网卡相信信息,网卡ent0
netstat -v ent0
 
 
Eclipse @override报错
在JAVA 1.5和1.6中@override的用法是有些区别的,虽然改变了JRE但eclipse还是会报错。
解决办法:Windows->Preferences-->java->Compiler-->compiler compliance level设置成6.0就OK了
 
 
weblogic.xml中 weblogic-web-app 标签的 xsi:schemaLocation 属性,在myecplise下面报错如下:
Referenced file contains errors (http://www.bea.com/ns/weblogic/weblogic-web-app/1.0/weblogic-web-app.xsd).  For more information, right click on the message and select "Show Details..."tips/tamcx/WEB-INFweblogic.xmlline 1131191929944315159
解决办法,在xsi:schemaLocation属性增加一段内容,如下:
http://java.sun.com/xml/ns/javaee
 
 
myeclipse6.0.1注册码生成:
TOOLS/MyEclipseGen.java执行后,输入名字就可以生成序列号。比如:
用户名shenlei
序列号Serial:fLR8ZC-855575-69527357679415182
 
 
myeclipse中js乱码问题,我导入项目后,发现js里的中文全部变成乱码
解决办法:
window->Preferences->Myeclipse->Files and Editors->JSP(以及javascript等)把encoding改成UTF-8。
 
 
 
workshop的webservice项目无法generate wsdl文件解决:
右键项目 Targeted Runtimes,勾上:Runtimes  Oracle weblogic server v10.3
 
workshop中创建webservice工程,它的web.xml文件与weblogic.xml文件
与它export出的war包中的两个文件有所不同,需注意。
因为export出的war包中必须包括一些application启动类的配置。
 
 
行业机构静态信息表TBL_MAMGM_INDUSTRY_INS_STATIC_INF内的
INDUSTRY_INS_ST机构状态字段,0表示打开,1表示关闭
而对应联机库 TBL_MAONL_INDUSTRY_INS_DYN_INF表中的INDUSTRY_INS_ST字段 0表示关闭,1表示打开
 
 
workshop appxray编译时间过长解决:
右键工程——》properties->builders——》去掉勾选 workshop AppXRay
 
 
List<Map<String, String>> list = ms.findAllBySql(sql.toString(),
values);
这个方法竟然把我sql里面的列全变成大写字母放入MAP中
 
 
db2 创建远程节点连接
http://www.ibm.com/developerworks/cn/data/library/techarticles/0301chong/0301chong2.html 
db2 catalog tcpip node mpwrnode remote mpower.ca.ibm.com server 50000
注: “mpwrnode”是为该节点所选择的任意名称。
mpower.ca.ibm.com = 数据库服务器 的主机名。 可以使用 IP 地址来代替主机名。
50000 = 数据库服务器实例 所使用的端口。 
db2 catalog db a42ds1 at node mpwrnode
db2 connect to a42ds1 user <userid> using <password>
这样就可以再本地使用远程数据库。
例子如下:
1、db2 catalog tcpip node isvrfffffffff remote 172.17.248.188 server 60020
2、db2 catalog db ismgmdb at node isvrfffffffff
3、db2 terminate
4、db2 connect to ismgmdb user isvrdb3 using isvrdb3
 
 
 
删除catalog
db2 uncatalog node isvrfffffffff 
 
 
在91ma_mgm上建的catelog,指向联机性能库
db2 catalog tcpip node maonldb remote 172.17.252.133 server 60000
db2 catalog db maonldb at node maonldb
db2 terminate
db2 connect to maonldb user ma_onldb using ma_onldb
 
 
 
当前用户的当前实例
db2 get instance
The current database manager instance is:  ma_mgmdb
 
 
查看当前实例是否在
db2pd - -alldbpartitionnum
Database Partition 0 -- Active -- Up 129 days 07:30:50 -- Date 05/18/2012 17:02:26
 
 
 
查看活动日志使用如下命令:
db2pd -db arc -logs
 
 
 
当前实例的配置
db2 get dbm cfg
 
数据库的配置 
db2 get db cfg for DBNAME
 
修改日志文件大小:db2 update db cfg for mamgmdb using LOGFILSIZ 40960
修改主日志文件个数:db2 update db cfg for mamgmdb using LOGPRIMARY  15
修改辅助日志文件个数:db2 update db cfg for mamgmdb using LOGSECOND 0
 
DB2 数据库一旦创建就无法再修改字符集的编码方式了。
可以在创建的时候指定字符集,如下指定为GBK:
create db SRCDB using codeset GBK territory CN
 
设置在锁上等待的时间
db2 "update db cfg for DBNAME using LOCKTIMEOUT 15"
 
主机上所有实例(其实就是用户)
db2ilist
 
显示的是当前实例下catalog的DB信息
db2 list db directory
 
查看catalog中远程节点node的信息(实际就是远程数据库的信息)
db2 list node directory
 
查看表空间信息
db2 list tablespaces show detail
 
 
查看DB2 instance是启动还是停止的
 1、db2_ps
 2、db2pd -inst
 3、ps -ef | grep -i "db2sysc" | grep -i "<instance name>"
 4、db2gcf -s
 
 
通过端口来查看哪个用户建了这个数据库
vi /etc/services
该文件里面有用户以及对应的端口,如:
DB2_ma_onldb    60032/tcp
DB2_ma_onldb_1  60033/tcp
DB2_ma_onldb_2  60034/tcp
 
 
财税库银实现类查询
select a.*,b.tran_name,b.tran_type,b.tran_class from t_sub_tran a ,t_tran b where a.tran_code=b.tran_code;
 
 
预置刷新共享内存表tbl_mamgm_para_task_syncshm_status和预置同步子系统表tbl_mamgm_para_task_syncsys_status
在公参同步中,一个1000条的批次,会插入2条(联机+批量)记录。
 
 
 
 
创建参数新增任务、创建参数修改任务,创建参数删除任务
这些动作之前要校验是否可以操作:
ParameterFlexFacade.checkParaOperatable()
其中checkParaRecordSyncIn函数调用了para_tbl_attr表的sync_in_exp字段,该字段是一个表达式,其中替换以后可以验证,如果验证失败将会抛exception,比如:
throw new BizException("主表正式表记录不存在,不允许操作!");
throw new BizException("此记录是只读的,不允许修改和删除操作!");
 
 
过滤条件组信息表,修改时报:“此记录是只读的,不允许修改和删除操作!”
原因是:tbl_mamgm_para_tbl_attr中该记录的字段SYNC_IN_EXP配置了下面语句:只有6开头的过滤条件组id才可以修改。
boolean result = !"#{RULE_GRP_ID}".startsWith("6");
01030201TBL_MAMGM_FILTER_RULE_GRP_INF过滤条件组信息表
报错的地方在:ParameterFlexFacade。checkParaRecordSyncIn函数
 
 
maps_sys是表示该记录是技术参数,不能操作
这个限制是指:para_tbl_attr表中sync_in_exp字段配置的:
boolean result = "maps_sys".equalsIgnoreCase("#{REC_UPD_USR_ID}");
目前多渠道包括两张表有此限制:
TBL_MAPS_GFS_MSG_SPEC_INF报文规范类型信息表,TBL_MAMGM_ACCESS_SYS接入系统标识表
 
sync_in_exp字段配置的其它包括:
TBL_MAMGM_FILTER_RULE_GRP_INF过滤条件组信息表boolean result = !"#{RULE_GRP_ID}".startsWith("6");  不以6开头的的,就
TBL_MAMGM_FILTER_APP_INF过滤应用信息表boolean result = !"#{APP_ID}".startsWith("9");
 
 
 
批量的两张表任务表:
TBL_MABAT_BAT_TASK_CTRL
TBL_MABAT_RECNCL_TASK_INF
 
 
订单页面宽度变小后,多出一条横杆,解决办法:
1、main.css
.table_head 中去掉 
background:url(../images/table_top_back.jpg) left top repeat-x;
这样换行就不会有一条杠了
2、WebContent/com/cup/isvr/portal/jpf/orderview/index.jsp中<th>与汉字之间加上
<div nowrap="nowrap">
</div>
3、把.datashow th行的line-height:27px;删除
 
 
HTTP GET和POST的区别
1、都是明文传输,都是不安全的
2、GET是在url上追加参数,POST在浏览器的地址栏中看不见参数,它是将表单内各个字段与其内容放置在HTML HEADER内
3、POST不会被浏览器缓存
4、GET是获取指定URL上的资源,是读操作,不论对某个资源GET多少次,它的状态是不会改变的
POST的语意是对指定资源“追加/添加”数据
5、长度限制,GET不能大于2k,POST一般认为不受大小限制。
 
浏览器中get方式:request.getContentLength()=-1,http规范中没有限制get方式不可以设置cotent-length,
GET /mjc/webtrans/PBRG HTTP/1.1
HOST: 172.17.248.74:11000
Accept: */*
Content-Length: 3
 
q=a
 
webservice的war包中wsdl和xsd文件既可以放在\WEB-INF\src\com\cup目录下,
也可以放在\WEB-INF\classes\com\cup在,用ant脚本编译workshop建的webservice工程时要修改web.xml文件
 
 
<2011-12-2 下午02时21分49秒 CST> <Warning> <Socket> <BEA-000402> 
<There are: 5 active sockets, but the maximum number of socket reader threads allowed by the configuration is: 4. 
You may want to alter your configuration.> 
解决:左边菜单servers -> configuration -> tuning下,将Socket Readers:由33改成99
注:上面一行勾上Enable Native IO可显著提供weblogic性能
 
 
使用ant打包时,如果仅仅是import一个类,不在程序中使用该类的任何方法,或者new该类
就算这个类不在classpath中,也不会报错,且生成的class文件中没有import那句话。
 
 
W.java文件内容:
class W{
static{
System.out.println(org.apache.commons.net.ntp.TimeStamp.getCurrentTime());
}public static void main(String[] args){
}}
在cmd中执行情况是:成功、成功、成功、失败。
javac -cp "d:\bea\modules\com.bea.core.apache.commons.net_1.0.0.0_1-4-1.jar" W.java
java -cp ".;d:\bea\modules\com.bea.core.apache.commons.net_1.0.0.0_1-4-1.jar" W
javac -cp "D:\bea\wlserver_10.3\server\lib\weblogic.jar" W.java
java -cp "D:\bea\wlserver_10.3\server\lib\weblogic.jar" W
1、很明显weblogic.jar中没有org.apache.commons.net.ntp.TimeStamp类,为什么能编译通过
2、把weblogic.jar拷贝到比如D:\bea\wlserver_10.3\server目录下,就编译不过了。为什么?
 
 
对于db2中字段是char型的后面补了空格的情况,在java中用sql查出来时也是带空格的。
要在sql中或者resultset结果中使用trim()去掉空格。
 
 
启动多渠道管理应用时,执行分别会执行下面脚本
mapsDomain/startWL.sh
mapsDomain/startWebLogic.sh
mapsDomain/bin/startWebLogic.sh  配置DOMAIN_HOME、JAVA_OPTIONS
${DOMAIN_HOME}/bin/setDomainEnv.sh  配置WL_HOME、JAVA_VM、JAVA_HOME、USER_MEM_ARGS、PRODUCTION_MODE、DOMAIN_PRODUCTION_MODE、SERVER_NAME、JAVA_OPTIONS
${WL_HOME}/common/bin/commEnv.sh   配置BEA_HOME、WL_HOME、JAVA_HOME、JAVA_VENDOR、WEBLOGIC_CLASSPATH、PATCH_CLASSPATH、CLASSPATHSEP
 
 
现在想要做一个java的socket客户端,C的socket服务端。客户端向服务端发送的报文中头四个字节是整型,表示报文总长度,
之后才是报文内容。在C里很好做,先把长度转成网络字节序,再拷贝到四个字节的缓冲区里。但是JAVA中要怎么做呢?
答:使用DataOutputStream,用其中的writeInt方法
此方法是如下操作:>>>表示无符号右移,左移没有无符号一说,即没有<<<
out.write((v >>> 24) & 0xFF);
        out.write((v >>> 16) & 0xFF);
        out.write((v >>>  8) & 0xFF);
        out.write((v >>>  0) & 0xFF);
int v =-2;
int s = v >> 1;
System.out.println(s);//-1
s = v >>> 1;
System.out.println(s);//2147483647
//00000000 00000000 00000000 00000000表示0
//01111111 11111111 11111111 11111111表示2147483647
//10000000 00000000 00000000 00000000表示-2147483648
//10000000 00000000 00000000 00000001表示-2147483647
//11111111 11111111 11111111 11111111表示-1    //通过System.out.println(Integer.toBinaryString(-1));方法可以看到二进制码
 
 
* Java 和一些windows编程语言如c、c++、delphi所写的网络程序进行通讯时,需要进行相应的转换  
* 高、低字节之间的转换  
* windows的字节序为低字节开头  
* linux,unix的字节序为高字节开头  
* java则无论平台变化,都是高字节开头  
 
 
使用weblogic的jta全局事务
ctx = getInitialContext();//创建一个上下文环境
javax.transaction.UserTransaction ut = (javax.transaction.UserTransaction)ctx.lookup("javax.transaction.UserTransaction");
ut.begin();
...
ut.commit();
 
 
 
 
transient
java语言的关键字,变量修饰符,如果用transient声明一个实例变量,当对象存储时,它的值不需要维持。   
Java的serialization提供了一种持久化对象实例的机制。当持久化对象时,可能有一个特殊的对象数据成员,
我们不想用serialization机制来保存它。为了在一个特定对象的一个域上关闭serialization,可以在这个域前加上关键字transient。
当一个对象被串行化的时候,transient型变量的值不包括在串行化的表示中,然而非transient型的变量是被包括进去的。
 
 
如果不implements   Cloneable的话,那么调用super.clone()函数将抛出CloneNotSupportedException异常
 
 
shell脚本中获得日期
CURTIME=`date +%Y%m%d%H%M%S`
echo $CURTIME
 
 
JAVA四个方位修饰符
private--类内部 
 
default--类内部,同包无继承关系类,同包子类 
 
protected--类内部,同包无继承关系类,同包子类,不同包子类 
 
public-类内部,同包无继承关系类,同包子类,不同包子类,不同包无继承关系类
 
 
@SuppressWarnings("serial")在Java中有什么作用?
@SuppressWarnings可以抑制一些能通过编译但是存在有可能运行异常的代码会发出警告,你确定代码运行时不会出现警告提示的情况下,可以使用这个注释。
("serial") 是序列化警告,当实现了序列化接口的类上缺少serialVersionUID属性的定义时,会出现黄色警告。可以使用@SuppressWarnings将警告关闭
 
 
表清理问题
TBL_MAMGM_TABLE_CLEAN_CFG
clean_md:0-多表清理;1-清理无效数据;2-清理指定表
ma_batdb.tbl_mabat_trans_log_chk_fail勾兑差错流水表,属于2-清理指定表;共7张,清理星期几的那张表的数据
ma_onldb.tbl_maonl_trans_refund退货表,也属于2-清理指定表,共3张,每月3号清理 第(month % 3 + 1)张表。
像众多的“0-多表清理”方式的表,表号取自ma_gfsdb.TBL_MAPS_GFS_DYN_SYS_PARA
ma_batdb.tbl_mabat_elct_prod_infBAT电子产品表,属于1-清理无效数据
ma_batdb.tbl_mabat_trust_data_infBAT托管数据表,属于1-清理无效数据
 
 
批量应用绑管理库
执行/maps/usr/hg_bat1/glb/gfs/sbin/mgmbind.sh
 
 
联机批量报818错,bind管理库有问题,需要将glb/gfs/bin/MDatasync_bat进程和glb/gfs/bnd/MDatasync_mgmdb.bnd文件一同拷贝
,注意进程的可执行chmod
 
taskcom list
进程扫描管理库的TBL_MAPS_GFS_TASK表,共享内存里面去
 
HttpServlet为什么要实现serializable?
我认为主要的原因是servlet容器可能会钝化servlet,把不活跃的servlet暂时持久化到IO设备
The servlet engine is not required to keep a servlet loaded for any period of time or  
for the life of the server. Servlet engines are free to use servlets or retire them at any  
time. Therefore, you should not rely on class or instance members to store state  
information.  
When the servlet engine determines that a servlet should be destroyed (for example,  
if the engine is shut down or needs to conserve resources), the engine must allow the  
servlet to release any resources it is using and save persistent state. To do this, the  
engine calls the servlet’s destroy method.  
The servlet engine must allow any calls to the service method either to complete  
or to end with a time out (as the engine defines a time out) before the engine can  
destroy the servlet. Once the engine destroys a servlet, the engine cannot route any  
more requests to the servlet. The engine must release the servlet and make it eligible  
for garbage collection.
容器不要求每个servlet都一直维持在内存,可以钝化,servlet也支持多种类加载方式,包括反序列化。
 
 
 
 
下拉框的两表DRDL_CFG和DRDL_ITEM_DEF都不支持oper_in in ('d','D')的过滤
DRDL_CFG表:DropDownCache.queryAll()
 
DRDL_ITEM_DEF表:
DataDropDown.java的构造函数调用了DropDownBaseImpl的构造函数,再调用了DataDropDown的init(),sql=SQL_LBLCD+...
SQL_LBLCD是在DropDownBaseImpl中定义:
static final String SQL_LBLCD="SELECT A.drdl_item_key,A.drdl_item_val FROM TBL_MAMGM_DRDL_ITEM_DEF A,"
+"TBL_MAMGM_DRDL_CFG B WHERE A.drdl_id=B.drdl_id AND B.drdl_nm=";
 
 
 
查看系统使用表空间的方法:
1、连接到目标数据库
命令:db2 connect to mamgmdb user username using password(username和password需要替换为正确的值)
2、查看数据库表空间使用情况
命令:db2 list tablespaces show detail
 
查看表空间所属容器信息
db2 list tablespace containers for 1 show detail
 
3、判断数据库表空间使用率是否正常的方法:
首先判断表空间类型(Type),如果Type= System managed space,说明表空间是操作系统管理的表空间,表空间自增长,只需关注表空间所在的文件系统的利用率。
如果Type= Database managed space,说明表空间是数据库管理的表空间,表空间非自增长,需要关注Used pages与Useable pages的比值,当(Used pages/Useable pages)>80%,需要及时向系统室值班岗报告。
 
 
查看数据库是否使用了归档日志,OFF为循环日志
db2 get db cfg for gmabatdb|grep LOGRETAIN
Log retain for recovery enabled             (LOGRETAIN) = OFF
Log retain for recovery enabled             (LOGRETAIN) = RECOVERY (为归档日志)
 
 
AIX主机名:
hostname
 
主机名对应的IP
vi /etc/hosts
 
aix查看某进程打开的文件数量
procfiles -n pid
 
对某进程强制垃圾收集
procfiles -F pid
 
UdpServlet的启动日志在cup_maps_alarm.log里面
 
 
多渠道和行综也会被xss跨站脚本攻击,原因就是这次新加的titleNm值
https://172.17.248.188:7002/isvr/com/cup/isvr/portal/jpf/flex/parameter.jsp?subjectId=010911&titleNm=ddd");}alert('xss');>
https://172.17.248.188:7002/isvr/com/cup/isvr/portal/jpf/flex/parameter.jsp?subjectId=010911&titleNm=ddd");}alert(request.getParameter('subjectId'));>
 
 
 
Apache JMeter是Apache组织开发的基于Java的压力测试工具。用于对软件做压力测试
 
 
 
SQL
对于查不出结果的sql语句的ResultSet一点不同:
select * from tbl_mamgm_para_task where EVENT_ID =2rs.next() == false
select 1 from tbl_mamgm_para_task where EVENT_ID =2rs.next() == false
select sum(1) from tbl_mamgm_para_task where EVENT_ID =2rs.next() == true,且rs.getInt(1)==0
 
 
 
flex的DateField日期组件,默认是不可修改。如果需要修改增加属性:
editable="true"
 
 
weblogic热部署必须要把启动模式改成开发模式,方法是config.xml中标签<production-mode-enabled>改成false。
热部署的build.xml关键语句
 <target name="redeploy" description="redeploy ear to WebLogic on ${wls.ip}:${wls.port};">
                <wldeploy user="${user}" password="${password}" adminurl="t3://${wls.ip}:${wls.port}" debug="true" remote="true" upl
oad="true" action="redeploy" name="${map.earApp.name}" source="${dest.home}/dest/${map.earApp.name}.ear" verbose="true" />
 
        </target>
        
 
在TimerTaskStartThread类中增加了catch NoSuchEJBException{break;}的原因是:
答:在redeploy管理应用ear包的时候,增加了一个TimerTaskStartThread线程,但是原先的TimerTaskStartThread线程仍在,
只是原先线程缓存了之前的ejb对象,导致了一直报错,虽然新的TimerTaskStartThread线程使得功能无影响,
但是break出去以后就不会在nohup.out里面报错了。
 
 
 
当db2中某表被锁,当使用weblogic数据源select该表,或者java应用通过jdbc select该表,均在10秒钟后报错,一个的errorcode=-4470,
另一个的SQLCODE=-911,这个超时时间10秒设置在:
1、db2 "update db cfg for DBNAME using LOCKTIMEOUT 15"  此处15是指设置锁上等待15秒
2、重启db2实例,才能生效
 
 
 
 
AIX查看某个端口被哪个进程占用
1. netstat -Aan|grep <portnumber>
2. 如果是 tcp 连接,则 rmsock <PCB/ADDR> tcpcb,如果是 udp 连接,则 rmsock <PCB/ADDR> inpcb 
下面我们以 telnet 服务所使用的 23 号端口为例,说明该方法: 
#netstat -Aan|grep 23
f1000200019ce398 tcp 0 0 *.23 *.* LISTEN
可以看到 PCB/ADDR 为 f1000200019ce398 ,且协议类型为 tcp
#rmsock f1000200019ce398 tcpcb
The socket 0x19ce008 is being held by proccess 185006 (inetd).
命令报告该端口正在被 inetd 进程使用, PID 为 185006 。 
3. ps -ef |grep PID
 
 
windows查看端口占用命令
1、netstat -aon|findstr "80"
2、tasklist|findstr "2448" 
 
windows杀死进程命令
tskill PID或者
 
 
 
 
HttpServletResponse的getBufferSize()方法获取Web容器的以kb为单位的目前缓冲区大小
 
 
cvs上被remove和commit的文件,恢复的办法:
答:根据版本号或者标签号checkout下来,例如historyFrame.html文件已经被彻底删除:
cvs co -r maps-7760-20120724 maps_mgm/flex/comm/html-template/history/historyFrame.html
 
 
 
日切日期:
同步模块会校验:管理发给的日期 = TBL_MAPS_GFS_DYN_SYS_PARA.MAPS_SETT_DATE + 1     校验不过直接报错
 
这个字段表示当前使用哪张表:
TBL_MAPS_GFS_DYN_SYS_PARA.multi_tab_act
第一位:0表示不在日切窗口期,1表示在日切窗口
第二位:2套表使用第几张
第三位:3套表使用第几张
第四位:7套表使用第几张
 
 
 
应用启动时数据源连接池的驱动用的是mapsDomain/lib/db2jcc.jar,
启动时,weblogic会自动去mapsDomain/lib下加载所有jar包。
 
 
FAQ
Some solutions to common problems:
Exception
java.lang.IllegalStateException: Application was not properly initialized at startup, could not find Factory: javax.faces.context.FacesContextFactory
Solution
Include a listener in your web.xml:
<listener>
    <listener-class>com.sun.faces.config.ConfigureListener</listener-class>
</listener>
 
 
问题:jsf的javax.faces.application.ViewExpiredException异常
答:去掉richfaces4的jar包
 
 
 
数据库字段,前面加上函数就不走索引了
select * from TBL_MAMGM_POS_PARA_INF WHERE LOWER(mchnt_cd) LIKE '11%';
RETURN0.0 %13993.33593751.350166272E913474.07.85886144638061513993.32128906251.35012864E913474.00.00.013474.00.00.0
MA_MGMDB.TBL_MAMGM_POS_PARA_INF  TBSCAN100.0 %13993.33593751.350166272E913474.07.85886144638061513993.32128906251.35012864E913474.00.00.013474.00.00.044675.437512
 
 
 
weblogic上ssl的端口默认是7002,所以有可能7002不出现在config.xml文件中
 
 
eclipse默认启动内存在eclipse.ini文件中配置:
诸如:
-Xms128m
-Xmx512m
-Duser.language=en 
-XX:PermSize=128M 
-XX:MaxPermSize=256M
 
 
 
boolean offer(E e) 
Inserts the specified element into this queue if it is possible to do so immediately without violating capacity restrictions. When using a capacity-restricted queue, this method is generally preferable to add(E), which can fail to insert an element only by throwing an exception.
 
它们的区别就是add 方法在插入失败的时候会抛出 IllegalStateException 异常
而offer可以通过返回值来判断成功与否 
 
 
Server监听
Socket clientSocket = serverSocket.accept();
tcp        0      0  *.8886                 *.*                    LISTEN
 
已建立的链接
cp4       0      0  172.17.248.74.8886     172.17.236.133.3966    ESTABLISHED
 
 
 
 
java做webservice时获得客户端的信息
import javax.servlet.http.HttpServletRequest;
import javax.xml.ws.WebServiceContext;
import javax.xml.ws.handler.MessageContext;
 
@Resource
WebServiceContext messageContext;
 
MessageContext mc = messageContext.getMessageContext();
HttpServletRequest request = (HttpServletRequest)mc.get(MessageContext.SERVLET_REQUEST);
String remortAddress = request.getRemoteAddr();
 
/*request.getLocale()=zh_CN
request.getLocalAddr()=172.17.248.74
request.getLocalName()=host01
request.getLocalPort()=8888
remortAddress=172.17.236.133
request.getRemoteHost()=172.17.236.133
request.getRemotePort()=3823
request.getRemoteUser()=null*/
System.out.println("request.getLocale()="+request.getLocale());
System.out.println("request.getLocalAddr()="+request.getLocalAddr());
System.out.println("request.getLocalName()="+request.getLocalName());
System.out.println("request.getLocalPort()="+request.getLocalPort());
System.out.println("remortAddress="+remortAddress);
System.out.println("request.getRemoteHost()="+request.getRemoteHost());
System.out.println("request.getRemotePort()="+request.getRemotePort());
System.out.println("request.getRemoteUser()="+request.getRemoteUser());
 
 
 
j2se开启webservice服务:
String wsUrl= "http://172.17.236.133:8888/MtqWebService?wsdl";
Endpoint.publish(wsUrl, new MtqWebService());
MtqWebService是一个类,需要标注@WebService、@WebMethod。
如果想让webservice服务的方法抛出异常必须要把异常包装成SOAPException,如:
 
@WebMethod
public String callByXml(String xmlData) throws Exception{
throw new SOAPException("dqqqqq");
}
 
 
 
Exception in thread "main" javax.xml.ws.WebServiceException: org.apache.cxf.service.factory.ServiceConstructionException
at org.apache.cxf.jaxws.EndpointImpl.doPublish(EndpointImpl.java:331)
at org.apache.cxf.jaxws.EndpointImpl.publish(EndpointImpl.java:234)
at org.apache.cxf.jaxws.spi.ProviderImpl.createAndPublishEndpoint(ProviderImpl.java:112)
at javax.xml.ws.Endpoint.publish(Endpoint.java:170)
at com.sl.ws.threadpool.MtqWebAction.main(MtqWebAction.java:22)
解决:去掉jbosslib的user library
 
 
Caused by: java.security.PrivilegedActionException: com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException: 2 counts of IllegalAnnotationExceptions
Class has two properties of the same name "msg"
this problem is related to the following location:
at public java.lang.String com.sl.ws.model.Request.getMsg()
at com.sl.ws.model.Request
this problem is related to the following location:
at public java.lang.String com.sl.ws.model.Request.msg
at com.sl.ws.model.Request
Class has two properties of the same name "msgRes"
this problem is related to the following location:
at public java.lang.String com.sl.ws.model.Response.getMsgRes()
at com.sl.ws.model.Response
this problem is related to the following location:
at public java.lang.String com.sl.ws.model.Response.msgRes
at com.sl.ws.model.Response
解决:将com.sl.ws.model.Request和 com.sl.ws.model.Response类中的属性从public改成private
 
 
weblogic在console中做update、stop、delete应用时,会调用Servlet的destroy()方法。
对于某些类的静态static实例变量,要在destroy方法中做clear,否则执行update、stop、delete后,static实例变量被认为是null值。
原先的static实例变量所指的对象将永远存在,直到domain被stoped
 
 
 
java socket的连接超时时间:
Socket socket = new Socket();
socket.connect( new InetSocketAddress( "172.17.236.133", 4700 ),5000);  //比如此处设置成5s
如果端口4700在server上没有监听:
1、如果该client与server的ip在同一网关内,java较容易找到该server机器,则直接抛错:java.net.ConnectException: 远程主机拒绝 connect 操作尝试。
2、如果该client与server的ip不在同一网关内,java将会去DNS上找路由,时间较长,那么超时抛错会出现:java.net.SocketTimeoutException: connect timed out
 
 
 
由于AIX(或UNIX)系统和Windows系统对于文本文件的行末结束符(或回车换行符)的处理方式不同,
当我们将Windows格式的一个文本文件以BIN格式(而不是ASCII方式)上传至AIX上时,用vi查看该文件会发现每行的行末出现一个^M的符号。
这会导致AIX系统下对该文本文件的处理出现异常,并且在该文件是脚本的情况下,也会导致脚本执行异常。
 
 
杀死本用户下的weblogic进程
ps -fu $USER |grep weblogic|grep -v grep|awk '{print $2}'|xargs kill -9 $1
 
 
乱码
public static String getEncodedString(Object p) {
boolean isDefaultChinese = Locale.getDefault().getLanguage()
.toLowerCase().indexOf("zh") != -1;
String tmpStr = p.toString();
if (!isDefaultChinese)
try {
tmpStr = new String(tmpStr.getBytes("GBK"), "ISO8859_1");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return tmpStr;
}
 
 
网络传输中有个二进制0的概念,一个字节8位全是二进制0,在java里面表示byte b = '\0',
对于new String(byte[])以后,二进制0还会存在,只要做了trim()就去掉了。
如果把二进制0赋予整型会变化成ascii的0.
int i = '\0';
System.out.println("i="+i);//i=0
 
 
 
weblogic的web应用:
提交了重新编译的class文件,哪怕是其中一个文件,或者不相干的class文件,
原先class中static变量的值都被赋null了。
 
 
JDK5.0 java.util.concurrent包中引入对Map线程安全的实现ConcurrentHashMap
java.util.concurrent包也提供了一个线程安全的ArrayList替代者CopyOnWriteArrayList
 
 
如何讲二进制流 加入XML报文中发送?
// 将 s 进行 BASE64 编码
public static String getBASE64(String s) {
if (s == null) return null;
return (new sun.misc.BASE64Encoder()).encode( s.getBytes() );
}
 
// 将 BASE64 编码的字符串 s 进行解码
public static String getFromBASE64(String s) {
if (s == null) return null;
BASE64Decoder decoder = new BASE64Decoder();
try {
byte[] b = decoder.decodeBuffer(s);
return new String(b);
} catch (Exception e) {
return null;
}
}
只要在xsd中,将某个字段类型设置成base64Binary,jaxb能自动讲xml中的BASE64 编码的字符串解析成正确的byte[]数组。
 
 
 
 
Socketsocket = new Socket();
//socket.setSoTimeout(5000);
InetSocketAddress local = new InetSocketAddress("172.17.246.1",0);
socket.bind(local);
socket.connect( new InetSocketAddress( "145.17.236.133", 4700 ),1000);  
 
    socket.setSendBufferSize(100);
 
 
 
mian2 aix测试结论:
1、新增一个new NioSocketConnector(1),增加4个句柄的使用。只开一个NioProcessor,即只用一个cpu,只开一个select.open()
2、新增一个new NioSocketConnector(),增加了4*(4+1)个句柄。第2个4:是248.74上有4核的cpu       4+1是默认值
3、做一次connector.connector()操作,即新增一条链路的话,增加1个句柄
4、new NioSocketConnector()和new NioSocketConnector(Runtime.getRuntime().availableProcessors() + 1)是一样的。
 
 
 
 
log4j.properties、CommPacket.ini、FilePacket.ini、mtq.properties       先找mtqCfg/ ,再找appCfg/,再找当前路径下
mtqNetwork.xml、mtqService.xml   必须在mtqCfg目录下,或者mtqCfg/sysname/目录下
 
 
 
 
如何使用JDK自带的JConsole监控Weblogic
http://172.17.249.10/NewSys/OA/KnowledgeBase/ShowKb.aspx?Id=6440&Key=
 
在java启动时添加:
-Dcom.sun.management.jmxremote.port=41125 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false
在windows path中:
Jconsole
 
myeclipse6.0
今天安装完eclipse和myeclipse以后,发现启动后窗口的标题栏显示:wtp java ee(myeclipse incompatible)?
选其它的perspective(视图): MyEclipse Java Enterprise
 
 
 
官方文档指出,WebLogic 9 / WebLogic 10 的线程池是自调优的,并且在WebLogic 9的时候,
通过修改config.xml可以修改默认线程池的最小值、最大值,但是很麻烦。
到了WebLogic 10gR3,连修改config.xml的办法都给取消了。
 
但是,可以通过在启动脚本增加如下参数,可以指定默认线程池的最小值、最大值:(http连接数)
 
-Dweblogic.threadpool.MinPoolSize=100 -Dweblogic.threadpool.MaxPoolSize=500
 
 
 
 
HashMap map.get(null)   返回null
ConcurrentHashMap concurmap.get(null)   报错java.lang.NullPointerException
ConcurrentHashMap concurmap.put(Integer.valueOf(2),null);报错java.lang.NullPointerException
 
Map遍历方式
for(Map.Entry<String, String> map : formFldValues.entrySet()){
queryString += map.getKey()+" like ? and";
values.add(map.getValue());
}
 
 
xml 转 javabean方式
 
//方式一 jaxb ,无需额外lib包
/*InputStream is = null;   效率最差
try {*/
// System.out.println(REQ.class.getPackage().getName());
/*JAXBContext jc = JAXBContext.newInstance(REQ.class.getPackage()
.getName());// 包名
Unmarshaller u = jc.createUnmarshaller();
is = new ByteArrayInputStream(xmlStr.getBytes("GBK"));
REQ req = (REQ) u.unmarshal(is);*/
 
//方式二 xsream ,需xstream-1.3.1.jar    10w次 78390ms
/*XStream xs1 = new XStream(new DomDriver());
xs1.alias("REQ", REQ.class);
REQ req = (REQ) xs1.fromXML(xmlStr);*/
 
 
//方式三 dom4j,需dom4j-1.6.1.jar  10W次 54203ms
Document doc=null;
try {
doc = DocumentHelper.parseText(xmlStr);
} catch (DocumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} // 将字符串转为XML
     Element rootElt = doc.getRootElement(); // 获取根节点
      System.out.println("根节点:" + rootElt.getName()); // 拿到根节点的名称
System.out.println(rootElt.elementTextTrim("SYSTEMNAME"));
 
//方式四 stax  10w次  6125ms
static XMLInputFactory inputFactory = XMLInputFactory.newInstance();
byte[] byteArray = xml.getBytes("GBK");
ByteArrayInputStream inputStream = new ByteArrayInputStream(byteArray);
XMLStreamReader reader = inputFactory.createXMLStreamReader(inputStream);
int event = reader.getEventType();//获取节点类型,结果是以整形的方式返回的。
while (reader.hasNext()) {
switch (event) {
case XMLStreamConstants.START_DOCUMENT://表示的是文档的开通节点。
break;
case XMLStreamConstants.START_ELEMENT://开始解析开始节点   
if (reader.getLocalName().equals("SYSTEMNAME")) {//判断节点的名字
 
mr.setSystemName(reader.getElementText());
break;
}
event = reader.next();
}
 
//方式五  自解 10w次  1437ms
mr.setSystemName(sb.substring(sb.indexOf("<SYSTEMNAME>")+12,sb.indexOf("</SYSTEMNAME>")));
 
 
 
使用cxf测试了csb上webservice,证明可行:
但是csb似乎不支持使用一个url获取wsdl,原因是解析后的wsdl文件倒数第四行address location是主机名,而不是ip
如:
http://P570_F_3:7001/csb/shcenter/BillDomain/MultiAcquiringSystem/BpsServiceImplService/BpsServiceImplServiceProxy
所以需要把wsdl保存在d:/BpsServiceImplServiceProxy.wsdl,然后将上述address location替换如下:
http://172.17.252.63:7001/csb/shcenter/BillDomain/MultiAcquiringSystem/BpsServiceImplService/BpsServiceImplServiceProxy
其效果与使用应用自己的webservice一样。
http://172.17.252.85:4866/MapsServicePortal/BpsServiceImplService?wsdl
 
此外还可以把解析好的变量设置成final类型:
JaxWsDynamicClientFactory dcf = JaxWsDynamicClientFactory.newInstance();
final Client client = dcf.createClient("d:/BpsServiceImplServiceProxy.wsdl");
Object[] res = client.invoke("excuteBpsService","<CUPBPS></CUPBPS>","BPS", "MAPSQUERY");
System.out.println("Echo response: " + res[0]);
 
 
 
 
 
如果xml请求报文中无<FILECONTENT>标签,则进不去这个if中
} else if (reader.getLocalName().equals("FILECONTENT")) {//判断节点的名字
如果xml请求报文中有,且值为空,如<FILECONTENT></FILECONTENT>,则
String s = reader.getElementText();
System.out.println((s==null));//false
System.out.println((s.equals("")));      //true
 
byte[] b = s.getBytes();
System.out.println((b==null));//false
System.out.println((b.length));//0
 
 
 
log4j级别依次下降
  // Field descriptor #56 Lorg/apache/log4j/Level;
  public static final org.apache.log4j.Level OFF;
  
  // Field descriptor #56 Lorg/apache/log4j/Level;
  public static final org.apache.log4j.Level FATAL;
  
  // Field descriptor #56 Lorg/apache/log4j/Level;
  public static final org.apache.log4j.Level ERROR;
  
  // Field descriptor #56 Lorg/apache/log4j/Level;
  public static final org.apache.log4j.Level WARN;
  
  // Field descriptor #56 Lorg/apache/log4j/Level;
  public static final org.apache.log4j.Level INFO;
  
  // Field descriptor #56 Lorg/apache/log4j/Level;
  public static final org.apache.log4j.Level DEBUG;
  
  // Field descriptor #56 Lorg/apache/log4j/Level;
  public static final org.apache.log4j.Level TRACE;
  
  // Field descriptor #56 Lorg/apache/log4j/Level;
  public static final org.apache.log4j.Level ALL;
 
 
 
 
持卡人管理upjas配置文件
$HOME/upjas/upjas-minimal/server/default/cup-deploy/mtqCfg
 
domain启动时脚本,以及nohup.out文件位置
$HOME/upjas/upjas-minimal/bin
 
 
 
java使用udp
客户端:
DatagramPacket packet = new DatagramPacket(msg.getBytes(), Integer
.valueOf(msg.length()), address, Integer.valueOf(port));
DatagramSocket socket = new DatagramSocket();
socket.send(packet);
 
//发送以后socket记下了本机使用的临时端口:socket.getLocalPort()
//所以之后可以监听端口等待了
byte[] message = new byte[256];
DatagramPacket recpacket = new DatagramPacket(message, message.length);
socket.setSoTimeout(10 * 1000);
socket.receive(recpacket);
 
//从udp包中获取数据是这样的:
String recmsg = new String(recpacket.getData(),0,recpacket.getLength());
System.out.println("client:"+recmsg);
 
 
服务端:
DatagramSocket socket = new DatagramSocket(Integer.valueOf(port));  //监听一端口
byte rb[] = new byte[1024];//申请一块内存
DatagramPacket pac = new DatagramPacket(rb, rb.length);//装成udp包
socket.receive(pac);//阻塞读,一旦收到内容,往udp包里面写信息,如:客户端ip、port;真实数据写入内存rb中
 
//使用接收时用的udp包中的客户端ip和port,将信息返回到客户端
String message = "toclient";
DatagramPacket recpacket = new DatagramPacket(message.getBytes(),message.length(), pac.getAddress(), pac.getPort());
socket.send(recpacket);// 发送回去
 
//另一种方式,原路返回客户端
pac.setData(message.getBytes());
socket.send(pac);// 发送回去
 
 
实践证明如果主机网卡上有两个ip(逻辑ip),那么下面代码,未绑定一个ip时,udp服务将在两个ip的端口上监听,udp客户端可以往两个ip的这个端口发消息
DatagramSocket socket = new DatagramSocket(Integer.valueOf(port));
 
且可以绑定两个ip的一个端口2次,下面的两个ip在一块网卡上。
String ip = "172.17.236.134";
InetAddress serveraddress = InetAddress.getByName(ip);
DatagramSocket socket = new DatagramSocket(Integer.valueOf(port),serveraddress);
String ip = "172.17.236.133";
InetAddress serveraddress = InetAddress.getByName(ip);
DatagramSocket socket = new DatagramSocket(Integer.valueOf(port),serveraddress);
 
 
如果ip是null或者“”,那么返回值是127.0.0.1的地址,
InetAddress serveraddress = InetAddress.getByName(ip);
---->  impl.loopbackAddress();
 
 
AIX5.3上如何查IP配置及子网掩码!
smitty tcpip选中你要看的网卡,回车.看完后按ESC+0退出就可以了.
 
查看网卡信息
lsdev -Cc adapter|grep ent
 
ifconfig -a 查出有几个网络接口,因为可能装有多个网卡。假设有ent0、ent1
lscfg -v -l ent0,就可以查到这块网卡的包括子网掩码、所在插槽位置等多个信息。
 
 
count(*)和order by一起会报错?
select count(*) from TBL_MAMGM_DRDL_CFG order by drdl_id;
 
 
 
从javaEE5开始,jpa规范脱离了EJB规范,好处是J2SE环境也可以使用jpa持久化层了。
 
 
eclipse生成javadoc
Project -> Genetate JavaDoc
如果项目编码不是GBK而是UTF-8,那么在Extra javadoc options写上:
-encoding UTF-8
-charset UTF-8
 
 
 
ApplicationInfoUtil的属性是无法通过管理页面刷新获得更新的,要改?
 
 
为什么API里FileReference有load()方法和data属性却不能使用?
FileReference的load()方法和data属性需要使用flashplayer 10的版本,
要添加playerglobal.swc,在你所用的sdk包下面,我这里的路径是sdk3.5.0.12683/frameworks/libs/player/10/playglobal.swc
 
 
flex builder3 默认要求flash player 最低要9,需要改成10.0,修改方法如下: 
右键点击项目,在项目属性中找 flex compile, 修改 html wrapper,把9.0.24改为10.0.0
 
 
flex工程ParaCommon报如下错误:'isNaN' is marked as extern, but '__AS3__.vec:Vector$int' is not?
右键工程-》Flex Library Compiler -》 Additional compiler arguments ->-target-player=10
so I went back to my application project to see if I had any special compiler settings, and remembered I had :
-target-player=10
 
 
 
Facade类的方法抛出BizExcpetion前台也获取不了。
 
 
@Column放在setPageImport上竟然获取不了数据库的值,只有放在getPageImport才正确。
 
 
 
flash10开始,FileReference增加了一个save方法,参数为(data:Object, defaultFileName:String = null),在调用save方法时,只需将文件内容传给data,
浏览器会自动打开一个保存对话框,让用户选择保存目录。有两个要注意的地方,1、save方法flash10及以上才有,客户端flash版本需跟上,
且代码编译环境也要在10以上,eclipse环境下,选中项目,右键properties,flex compiler选项,将required flash player version 设为10.0.0或以上,
否则将找不到save方法。2、save方法只能通过用户交互来调用。怎么理解用户交互,例如,点击一个下载按钮这算是用户交互,
而一般的回调方法则不是用户交互。如下载一张图片,如果图片还没加载进来,我们经常是先要进行加载,然后监听事件,然后在回调函数里进行处理,
如果将save方法写在回调函数里面,将会报错:Error #2176: 某些动作(如显示弹出窗口的动作)只能通过用户交互来调用。
所以很多时候我们必须采用双按钮,一个用来加载数据,一个用来下载数据。
 
 
点“模版文件下载”按钮没反应:
解决:eclipse环境下,选中项目,右键properties,flex compiler选项,将required flash player version 设为10.0.0或以上,
 
 
treemap是自然顺序(默认自然顺序,是指如果key是int型就是按数字大小,如果key是string则按照字母顺序排列,如果实现了Comparator接口即可按照想要的顺序了),
linkedmap是插入顺序,ListOrderedMap,LRUMap等都是有一定规则的顺序的map...
 
 
 
PrepardStatement语句中占位符?不能在select的字段中,只能在where条件后?
 
 
 
 
持续insert时候,db2报如下错误:ERRORCODE=-805,SQLSTATE=51002
 
问题的根本是因为程序里有很多游标没有关闭
问题解决了,谢谢你的提醒!!
pstmt.executeUpdate(); 
pstmt.close();//加上这一行
就可以了。
 
 
 
新增菜单无法通过刷新管理缓存立刻可见?
原因:tbl_mamgm_access_inf表中的access_cd字段值最后多了一个空格
 
 
 
 
同步子系统失败了以后竟然到了同步成功这一状态???
 
 
 
 
flex3中datagrid组件中某个单元格可编辑时,如何在键盘输入值之后触发事件函数获得值?
有两个事件可以itemEditEnd、itemFocusOut。
<mx:DataGrid id="defindInfoGrid" editable="true" itemEditEnd="valueVaildate(event)"/>
 
public function valueVaildate(event : DataGridEvent) : void
{
//第几列
Logger.info("event.columnIndex1 :"+event.columnIndex);
 
//dataField值
 var dataField:String = event.currentTarget.columns[event.columnIndex].dataField;;
 Logger.info("dataField :"+dataField);
 
//编辑前值
var oldValue:String=event.itemRenderer.data[dataField];//对已知的dataField:event.itemRenderer.data.FIELD_DESC
Logger.info("oldValue :"+oldValue);
 
 var cols:DataGridColumn=defindInfoGrid.columns[event.columnIndex];
//编辑后新的值
  var newValue:String=defindInfoGrid.itemEditorInstance[cols.editorDataField];
  Logger.info("newValue :"+newValue);
}
 
 
 
 
db2查询sql时报如下错
 09:06:16  [SELECT - 0 row(s), 0.000 secs]  
 [Error Code: -968, SQL State: 57011]  DB2 SQL error: SQLCODE: -968, SQLSTATE: 57011, SQLERRMC: null
增加你的system temp tablespace所在文件系统大小,或者database temp tablespace空间利用率
 
 
 
在weblogic中,如果有多个war、war包应用,默认的部署顺序都是100,改变方法是修改config.xml中的<deployment-order>98</deployment-order>项
  <app-deployment>
    <name>mjc</name>
    <target>MapsServer</target>
    <module-type>war</module-type>
    <source-path>/GGZF/usr/mapsweb/shenlei/dest/mjc.war</source-path>
    <deployment-order>98</deployment-order>
    <security-dd-model>DDOnly</security-dd-model>
  </app-deployment>
或者在console中,点deployment中的某一项应用。
 
 
 
 
页面新增参数,点保存时报“当前用户没有此操作权限!”
原因:TBL_MAMGM_PARA_SUB_AREA_INF表中的ACCESS_CD没写对
 
 
参数维护时,创建新增任务,点保存,报“用户没有权限”错误
原因:subject表上access_url填写错误。
 
 
使用ThreadLocal以空间换时间解决SimpleDateFormat线程安全问题,同时提高了每次new SimpleDateFormat的效率
class DateUtil2 {
 
private static final String DATE_FORMAT = "yyyy-MM-dd";
 
private static ThreadLocal<DateFormat> threadLocal = new ThreadLocal<DateFormat>() {
protected synchronized DateFormat initialValue() {
System.out.println("initial");
return new SimpleDateFormat(DATE_FORMAT);
}
};
 
public static DateFormat getDateFormat() {
return threadLocal.get();
}
 
public static String format(Date date) throws ParseException {
return getDateFormat().format(date);
}
 
public static Date parse(String textDate) throws ParseException {
return getDateFormat().parse(textDate);
}
}
 
 
 
PreparedStatement中进行模糊查询:
String = "select * from tbl_mamgm_comm_line_cfg where line_no like ?"
PreparedStatement ps = conn.prepareStatement(sql);
ps.setObject(1, "%000HCSN0001A1%");
ResultSet rs = ps.executeQuery();
 
 
java.util.zip
GZIPOutputStream类用于压缩 
GZIPInputStream类用于解压缩 
 
 
 
2012 年餐饮业收入23,283 亿元,同比增长13.6%。其中限额以上餐饮业收入7,799 亿元,同比增长12.9%
限额以上餐饮业是指年主营业务收入200 万元及以上的餐饮业企业 (单位)
 
 
sleep三秒
TimeUnit.SECONDS.sleep(3);
 
 
poi中设置单元格为文本格式:
HSSFCellStyle cellStyle2 = demoWorkBook.createCellStyle();
            HSSFDataFormat format = demoWorkBook.createDataFormat();
            cellStyle2.setDataFormat(format.getFormat("@"));
            cell.setCellStyle(cellStyle2);
            
 
excel 2003  工作表最大有2^16=65536行,2^8=256列
 
excel 2007 和excel 2010最大有2^20=1048576行,2^14=16384列
 
 
ibm jdk gc(xml格式) 查看工具ga441.jar
Used Tenured(After)   gc过后老年代使用的内存大小
Free Tenured(After)   gc过后年老代未使用内存大小
Total Tenured(After)  gc过后老年代总大小
Free Tenured(Before)  gc之前年老代未使用内存大小
Total Tenured(Before) gc之前老年代总大小
Free Nursery(After)    gc之后年轻代未使用内存大小
Total Nursery(After)   gc之后年轻代总大小
Free Nursery(Before)   gc之前年轻代未使用内存大小
Total Nursery(Before)  gc之前年轻代总大小
 
分配失败(AF)导致的垃圾收集的verbosegc输出
 
compact压缩
如果未设置虚拟机参数-Xnocompactgc并且以下几个条件任何一个为true,那么就会发生堆压缩动作: 
· 设置了虚拟机参数-Xcompactgc 
· 清理阶段结束之后,还是无法满足分配需求 
· 调用System.gc()并且在最后一次分配失败发生或者并发标识收集之前发生了压缩动作 
· TLH消耗了至少一半的存储,并且TLH的平均大小低于1000字节 
· 堆的空闲空间小于5% 
· 堆的空闲空间小于128KB 
 
其实IBM的gc的停止比我们想象中要短的多。STW(stop total world)只有在下面这些条件才执行:
1.到达heap limited或者allocation fail
2.System.gc方法被调用
3.Concurrent mark 完成所有的工作
 
调大nursery尺寸会导致垃圾回收的停顿时间加长。
 
对于1GB的堆,如果进行了压缩动作,垃圾收集的暂停时间可能增加到40秒。
增量压缩技术就是将压缩动作分散到多次垃圾收集周期中,以减少暂停时间。 
-Xpartialcompactgc,表示每次垃圾收集都使用增量压缩,除非必须进行完整的压缩动作 
 
 
使用ibm的HeapAnalyzer查看aix的dump文件(jdk有个工具:jmap -dump:live,format=b,file=d:\java.dump pid),内存映射--------ha445.jar
heapdump.20130605.160859.24969368.0004.phd
 
使用ibm的Thread and Monitor Dump Analyzer for java查看aix的core文件(通过kill -3 pid获得),查看线程、内存等完整信息--------jca432.jar
javacore.20130604.171533.10027244.0011.txt
 
java -Xmx1000m -jar jca432.jar
 
jmap 的用途是为了展示java进程的内存映射信息,或者堆内存详情
使用命令:
jmap pid 打印内存使用的摘要信息
jmap -histo:live pid     展示class的内存情况,展示的信息为编号,实例数,字节,类名
jmap -heap pid           展示pid的整体堆信息
jmap -dump:live,format=b,file=d:\java.dump pid导出的文件可以供分析用,比如jhat或者mat、ha445.jar,以便查找内存溢出原因
 
 
Jstat是Sun JDK中自带的监控工具,利用了JVM内建的指令对Java应用程序的资源和性能进行实时的命令行的监控,包括了对Heap size和垃圾回收状况的监控等等
jstat -gcutil 7432 5000 10每隔5000ms采样一次,一共采样10次
C:\Documents and Settings\沈雷>jstat -gcutil 7432 5000 10
  S0     S1     E      O      P     YGC     YGCT    FGC    FGCT     GCT
  0.00   0.00   0.00   1.41   3.13      0    0.000     3    0.887    0.887
  0.00   0.00   0.00   1.41   3.13      0    0.000     3    0.887    0.887
  0.00   0.00   0.00   1.41   3.13      0    0.000     3    0.887    0.887
  0.00   0.00   0.00   1.41   3.13      0    0.000     3    0.887    0.887
  0.00   0.00   0.00   1.41   3.13      0    0.000     3    0.887    0.887
  0.00   0.00   0.00   1.41   3.13      0    0.000     3    0.887    0.887
  0.00   0.00   0.00   1.41   3.13      0    0.000     3    0.887    0.887
  0.00   0.00   0.00   1.41   3.13      0    0.000     3    0.887    0.887
  0.00   0.00   0.00   1.41   3.13      0    0.000     3    0.887    0.887
  0.00   0.00   0.00   1.41   3.13      0    0.000     3    0.887    0.887
 
S0:年轻代中第一个survivor(幸存区)已使用的占当前容量百分比
S1:年轻代中第二个survivor(幸存区)已使用的占当前容量百分比
E:年轻代中Eden(伊甸园)已使用的占当前容量百分比
O:old代已使用的占当前容量百分比
P:perm代已使用的占当前容量百分比
YGC:从应用程序启动到采样时年轻代中gc次数
YGCT:从应用程序启动到采样时年轻代中gc所用时间(s)
FGC:从应用程序启动到采样时old代(全gc)gc次数
FGCT:从应用程序启动到采样时old代(全gc)gc所用时间(s)
GCT:从应用程序启动到采样时gc用的总时间(s)
 
如果FGC 过多,有必要调整下jvm参数。
 
 
 
 
F5负载均衡器简单的理解就是咱们通常称之四层交换机或七层交换机。同时也叫IP应用交换机
 
 
下载文件的按钮连点两次,页面上只会提示一个文件下载框,是第二次点击生成的文件
 
下载文件的文件保存框是resposne全部write完,还是开始写的时候就弹出来? 开始写
 
weblogic支持的最大http请求设置?
无法修改,可以通过在启动脚本增加如下参数,可以指定默认线程池的最小值、最大值:(http连接数)
-Dweblogic.threadpool.MinPoolSize=100 -Dweblogic.threadpool.MaxPoolSize=500
 
 
weblogic的http连接超时时间?
ueue: ‘billproxyqueue’ has been busy for “727″ seconds working on the request “Http Request: /bill/y
nQueryPublic.go”, which is more than the configured time (StuckThreadMaxTime) of “600″ seconds.>
一看明显是连接超时, 导致的错误.
1、程序问题,是不是程序中没有关闭连接
2、Configuration -》 Tuning  -》 Stuck Thread Max Time: 600
如果程序没问题,则是weblogic的StuckThreadMaxTime设置过小而引起的,
一般weblogic server 的StuckThreadMaxTime默认参数是600s,即10分钟,如果并发量过大,
而导致等待处理过多,导致系统不停的增加线程,造成线程阻塞,
你可以把该参数设置大点这个是稍微调大StuckThreadMaxTime的参数即可.
3、看线程数设置,可适当增加线程数,这个在WLS控制台中可以调整
 
 
java程序模拟发起http请求到多渠道时,需要设置cookie值:
bke_isvr=dLpbR0XCzYryDZtPBhBLZwpQLn51sQ234hC1rlpqv6ThVJMJTK8W!1476132340
否则管理会将链接到sso时返回一个登陆页面给java模拟程序。
 
 
jsp文件,weblogic编译的servlet结果。
路径:项目/com/maps/index.jsp
编译好的路径:isvrDomain/servers/IsvrServer/tmp/_WL_user/isvr_mngApp/dioh2x/jsp_servlet/_com/_map
该servlet class的类名:out.println("========"+this.getClass().getName());
结果:========jsp_servlet._com._maps.__index 
 
 
 
javac -verbose
java -verbose
 
 
DBPM服务端部在172.17.248.74   $HOME/shenlei/dbpm_j下
 
 
360在提交时会访问servlet两次:
https://172.17.248.181:7002/isvr/FileDownLoad?subjectId=080701&STAT_DT_STAT=20130617&STAT_DT_END=20130617
 
 
设置下载文件的大小:
response.setHeader("content-length", String.valueOf(filelen));
 
 
HTTP头的一些信息:
System.out.println("*******************************begin****************************************");
System.out.println("Protocol: " + request.getProtocol() );
System.out.println("Scheme: " + request.getScheme() );
System.out.println("Server Name: " + request.getServerName()  );
System.out.println("Server Port: " + request.getServerPort() );
System.out.println("Protocol: " + request.getProtocol() );
System.out.println("Server Info: " + getServletConfig().getServletContext().getServerInfo()); 
System.out.println("Remote Addr: " + request.getRemoteAddr() );
System.out.println("Remote Host: " + request.getRemoteHost() );
System.out.println("Character Encoding: " + request.getCharacterEncoding() );
System.out.println("Content Length: " + request.getContentLength() );
System.out.println("Content Type: "+ request.getContentType() );
System.out.println("Auth Type: " + request.getAuthType() );
System.out.println("HTTP Method: " + request.getMethod() );
System.out.println("Path Info: " + request.getPathInfo() );
System.out.println("Path Trans: " + request.getPathTranslated() );
System.out.println("Query String: " + request.getQueryString() );
System.out.println("Remote User: " + request.getRemoteUser() );
System.out.println("Session Id: " + request.getRequestedSessionId() );
System.out.println("Request URI: " + request.getRequestURI() );
System.out.println("Servlet Path: " + request.getServletPath() );
System.out.println("Accept: " + request.getHeader("Accept"));
System.out.println("Host: " + request.getHeader("Host") );
System.out.println("Referer : " + request.getHeader("Referer") );
System.out.println("Accept-Language : " + request.getHeader("Accept-Language"));
System.out.println("Accept-Encoding : " + request.getHeader("Accept-Encoding") );
System.out.println("User-Agent : " + request.getHeader("User-Agent") );
System.out.println("Connection : " + request.getHeader("Connection") );
System.out.println("Cookie : " + request.getHeader("Cookie") );
System.out.println("Created : " + request.getSession().getCreationTime() );
System.out.println("LastAccessed : " + request.getSession().getLastAccessedTime() );
System.out.println("*******************************end****************************************");
 
 
jsp中文乱码三句话:
<%@ page language="java" import="java.util.*" pageEncoding="gb2312"%>  
<%@page contentType="text/html;charset=gb2312"%>  
<%request.setCharacterEncoding("gb2312");%>  
 
在filter中设置request.setCharacterEncoding("gb2312");只支持post提交的信息,对于GET方式的提交在jsp中显示的方法是:
1、new String(request.getParameter("titleNm").getBytes("ISO8859-1"),"UTF-8"));
2、或者在/upjas/upjas-minimal/server/default/deploy/jbossweb.sar/server.xml中设置:
< Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" URIEncoding="GBK" />
 
upjas页面乱码修改了:
SetCharacterEncoding
web.xml
 
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
if (ignore || request.getCharacterEncoding() == null) {
String encoding = selectEncoding(request);
if (encoding != null) {
request.setCharacterEncoding(encoding);
}
}
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse resp = (HttpServletResponse) response;
String tmpUrl = req.getRequestURI();
String queryString = req.getQueryString();
if (!StringUtil.isEmpty(queryString)&&queryString.contains("titleNm")) {
queryString = new String(queryString.getBytes("ISO8859-1"), "UTF-8");
tmpUrl = tmpUrl.substring(5)+"?"+queryString;
req.getRequestDispatcher(tmpUrl).forward(req, resp);
return;
}
chain.doFilter(request, response);
}
 
 
jboss上查看ejb和数据源是否部署成功:
http://localhost:端口/jmx-console/ 
左边菜单的jboss链接,然后选 service=JNDIView, 点击 list 下面的 invoke 看一看现在 jboss 的 jndi 里面都有哪些对象
直接看最下面的 global 部分就可以了,看看有没 有定义的Namespace
如果有,那就说明部署成功了,调用应该就没有问题了
 
 
http头增加了Content-Type:application/x-www-form-urlencoded;charset=UTF-8,而不是Content-Typeapplication/x-www-form-urlencoded时,
jboss能自动转换字符,而在filter中设置request.setCharacterEncoding(encoding);不起作用。
 
 
 
 
spring加载配置文件 
1、把applicationContext.xml直接放在WEB-INF/classes下,spring会采用默认的加载方式
2、采用在web.xml中配置ContextLoaderListenera或ContextLoaderServlet指定加载路径方式。
3 通过ClassPathXmlApplicationContext或XmlWebApplicationContext代码动态加载!
 
 
 
对 HTTP 304 的理解:
304 的标准解释是:Not Modified 客户端有缓冲的文档并发出了一个条件性的请求(一般是提供If-Modified-Since头表示客户只想比指定日期更新的文档)。
服务器告诉客户,原来缓冲的文档还可以继续使用。看下面的http请求,里面的If-Modified-Since
GET /test/bar.emf HTTP/1.1
Accept: image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/x-ms-application, application/x-ms-xbap, application/vnd.ms-xpsdocument, application/xaml+xml, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*
Accept-Language: zh-cn
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)
Accept-Encoding: gzip, deflate
If-Modified-Since: Fri, 28 Jun 2013 08:24:04 GMT
If-None-Match: W/"3952-1372407844254"
Connection: Keep-Alive
Host: 172.17.236.121:8080
 
 
apache反向代理:
修改Apache2.2\conf\httpd.conf配置
1.先去掉下面两行的注释
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so
2.然后在最后增加
<VirtualHost localhost:80>#此处localhost:80为当前apache服务的 ip:port
ProxyPass / http://www.baidu.com
ProxyPassReverse / http://www.baidu.com
</VirtualHost>
 
那么浏览器访问http://localhost/img/bdlogo.gif , apache会将请求转发到:http://www.baidu.com/img/bdlogo.gif
 
 
例如使用apache作为域名www.test.com代理服务器,让其暴露在公网上,即DNS解析到本机器上,真正提供web服务器的是另一台位于同一内网的机器上,假设起IP是192.168.100.22,那么只需要如下配置就可以了。
ProxyPass / http://192.168.100.22/
ProxyPassReverse / http://192.168.100.22/
ProxyPass 很好理解,就是把所有来自客户端对http://www.test.com的请求转发给http://192.168.100.22上进行处 理,ProxyPassReverse 的配置总是和ProxyPass 一致,但用途很让人费解。似乎去掉它很能很好的工作,事实真的是这样么,其实不然,如果响应中有302重定向,ProxyPassReverse就派上用 场。举例说明,假设用户访问http://www.test.com/exam.php,通过转发交给http://192.168.100.22 /exam.php处理,假定exam.php处理的结果是实现redirect到login.php(使用相对路径,即省略了域名信息),如果没有配置 反向代理,客户端收到的请求响应是重定向操作,并且重定向目的url为http://192.168.100.22/login.php ,而这个地址只是代理服务器能访问到的,可想而知,客户端肯定是打不开的,反之如果配置了反向代理,则会在转交HTTP重定向应答到客户端之前调整它为 http://www.test.com/login.php,即是在原请求之后追加上了redirect的路径。当客户端再次请求http: //www.test.com/login.php,代理服务器再次工作把其转发到http://192.168.100.22/login.php。
客户端到服务器称之为正向代理,那服务器到客户端就叫反向代理。
 
 
apache利用mod_cache缓存图片:
在httpd.conf中打开mod_cache,然后:
1、内存:
<IfModule mod_cache.c>  
LoadModule mem_cache_module modules/mod_mem_cache.so  
<IfModule mod_mem_cache.c>  
CacheEnable mem /images  
MCacheSize 4096  
MCacheRemovalAlgorithm LRU  
MCacheMaxObjectCount 100  
MCacheMinObjectSize 1  
MCacheMaxObjectSize 2048  
CacheMaxExpire 864000  
CacheDefaultExpire 86400  
CacheDisable /php  
</IfModule>  
</IfModule>  
2、硬盘:
<IfModule mod_cache.c>
LoadModule disk_cache_module modules/mod_disk_cache.so
CacheDefaultExpire: 3600                     #指定快取的预设过期秒数;默认值是一小时 (3600)。
CacheMaxExpire: 86400                        #指定快取最大的过期秒数;默认值是一天 (86400)。
<IfModule mod_disk_cache.c>
CacheRoot d:/cachetest
#CacheSize 256
CacheEnable disk /
CacheDirLevels 4
#CacheMaxFileSize 64000
#CacheMinFileSize 1
#CacheGcDaily 23:59
CacheDirLength 3
</IfModule>
 
 
如何知道已经安装上的unix系统是否有cc编译器?
cc -v
 
cc 1.c 
没有指定可执行文件的名字,系统会自动生成可执行文件a.out。这个可执行文件的名字是系统自动生成的。默认情况下就是a.out
 
可执行文件的名字管理?
cc -o 1 1.c
 
编译多个c语言源程序文件
cc -o 2 1.c 2.c
cc -o 2 1.o 2.c
 
系统会编译源程序代码文件,并生成对应的目标文件.o。但是不会把目标文件链接成可执行文件,即使存在main函数的情况下
cc -c 1.c
会生成1.o
 
 
SERVER系统(例如WINDOWS 2003或者2008)安装邮件服务器
XP系统不支持安装微软的Exchange邮件服务器(Exchange要求开启IIS+ASP+SMTP+NNTP服务,关键是还要求局域网内有电脑安装域控,XP只能装IIS服务),
某些第三方邮件服务器软件(Web方式的)可以支持
 
 
 
在向eclipse的jar包中导入了javadoc后,编写程序的过程中使用jar包中的方法时Eclipse会自动显示其注释说明,可以大大提高开发人员的效率。
在向eclipse的jar包中导入了source后,Eclipse将可以显示类的源代码,并且同时具有了导入javadoc的显示功能。
 
 
 
使用eclipse的时候,突然发现eclipse中按Alt+/ 后,代码智能感应不能出现?
解决:
从eclipse进入Window-Preferences-General-Keys。找到Content Assist,会发现快捷键是“ctrl+space”,这与windows系统的默认中英输入法切换快捷键冲突了,
需要修改,先Remove Binding,然后改为“alt+.”就可以了。它可以帮你联想到所有的类供你选择。
另:“word completion”的快捷键使用“alt+/”,它可以自动帮你补全类名。
 
 
在eclipse中打开jsp文件时出现An error has occurred.see error log for more details错误?
解决:进入打开cmd(命令提示符)Eclipes目录下,输入eclipse.exe -clean           待Eclipse启动后,即可打开编辑jsp页面
 
 
ejb以jar形式在jboss中发布后,jar包中的类可以直接被同时发布的war包中new出。
 
 
JBOSS5中ejb Stateless bean的开发:
Stateless的属性:mappedName不能与实现的类名相同,否则会报下面的错。name属性随便。
Caused by: org.jboss.aop.DispatcherConnectException: EJB container is not completely started, or is stopped.
 
如果不设置mappedName的话,客户端调用使用lookup("CompanySessionBean/remote"),
本地(ejb中调用ejb)使用remote和local都可以,不过使用remote费时:
lookup("CompanySessionBean/local")或者lookup("CompanySessionBean/remote")
 
 
在客户端中访问stateless bean时需要Properties,且使用Company/remote标志,如:
Properties prop = new Properties();
prop.setProperty(Context.INITIAL_CONTEXT_FACTORY,
"org.jnp.interfaces.NamingContextFactory");
prop.setProperty(Context.PROVIDER_URL, url);
prop.setProperty(Context.URL_PKG_PREFIXES,
"org.jboss.naming:org.jnp.interfaces");
InitialContext ctx = new InitialContext(prop);
DepartmentRemote dr = (DepartmentRemote)ctx.lookup("DepartmentRemote");
System.out.println(dr.getDepName("Company"));
 
在ejb中访问ejb不需要如此麻烦,不需要Properties和/remote:
InitialContext ctx = new InitialContext();
CompanyRemote companyRemote = (CompanyRemote) ctx.lookup("CompanyRemote");
System.out.println(companyRemote.getName());
 
 
--原子服务(函数),用于组装用于组装原子交易的基本单位,本表定义了原子服务的函数名、所属动态链接库等参数供联机处理时定位实际的业务处理函数
select * from TBL_MAPS_GFS_ATOM_SVR_INF;
select * from TBL_MAPS_GFS_ATOM_TRANS_SVC_RELATED;--配置每个流程服务处理的原子交易列表
select * from TBL_MAPS_GFS_FLOW_SVC_ATOM_TRANS_RELATED;--记录需要属于指定的原子交易
select * from TBL_MAPS_GFS_FLOW_SVC_INF;--邮箱号
 
 
--多渠道平台向外部系统的原发请求交易,根据交易信息源代码、采用的报文规范类型、商户代码等参数查找外部交易码及其对应的报文格式转换相关信息
select * from TBL_MAMGM_MSG_FMT_CONV_MTO;
select * from TBL_MAPS_GFS_FMT_GRP;--平台打解包格式转换组编号
 
 
jboss热部署,在deploy中web部署的context.xml中修改如下:
<Context cookies="true" crossContext="true" antiResourceLocking="false " antiJARLocking="false ">
 
 
操作系统通过文件系统管理文件及数据,磁盘或分区需要创建文件系统后才能为操作系统使用,创建文件系统的过程又称为格式化。
 
cpu 4.2g的意思是:每秒能处理4.2*1000*1000*1000次指令。
DDRIII1333的速度读取大概在8到9G左右,写的速度大概在7到8G左右。
普通硬盘的读取速度大概是100M/S左右,而固态硬盘的读取速度则是250M/S
 
 
关闭employee表的约束性检查
db2 set integrity for employee off
 
oracle中建立延迟约束,提交时才做约束检查
ALTER TABLE MV_T ADD CONSTRAINT UN_MV_T_NAME UNIQUE (NAME) DEFERRABLE;
 
db2 import数据时出错:
SQL3120W  The field value in row "22370" and column "1" cannot be converted to 
an INTEGER value, but the target column is not nullable.  The row was not 
loaded.
解决:如果字段值里面含回车换行的,如果以del形式export之后,import导入时都会出现这个问题。换成ixf二进制格式就没有问题了。导入速度还快。
 
 
有没有在vi 编辑文件过程中刷新命令(请高手赐教)?
解决:使用“:e”可以刷新
 
 
函数原型
void *memcpy(void *dest, const void *src, size_t n);
 
 
 
pcap抓包文件使用Wireshark打开
 
 
SimpleDateFormat的毫秒级表示S:yyyy-MM-dd hh:mm:ss SSS
 
 
jdk自带工具jvisualvm来查看线程
 
new ExecutorFilter()中调用了init(executor, MANAGEABLE_EXECUTOR),然后调用initEventTypes(IoEventType... eventTypes),由于eventTypes为null,因此eventTypes = DEFAULT_EVENT_SET默认所有的IoEventType。
 
 
list.remove()会影响list中后面的取值。
 
jboss服务器上临时tmp目录:
/maps/usr/ma_mgm/shenlei/upjas/upjas-minimal/server/default/tmp/4sh702j-fmwloa-hkaiefdh-1-hkaigw6d-al/maps.war/com/cup/maps/portal/jpf/flex
 
 
aix上解压zip文件
/usr/java6_64/bin/jar -xvf upjas.zip
 
 
export CVSROOT=:pserver:leishen@172.17.249.63/cvsnew2
cvs login
cvs update -r V[1][0][1] UPJAS
 
 
 
F5负载均衡获取客户端真实ip?
首先需要在F5上配置X-Forwarded-For,然后可以通过获取"x-forwarded-for";来获取客户端的IP地址。
具体步骤:
1:Local Traffic-Profiles-Http-改“Insert XForwarded For”为Enable
2:Local Traffic-Virtual servers-点击需要改动的VS-将Type选项更改为Standard-将HTTP Profile 选项更改为Http
 
 
final_str = new String(final_str.getBytes("iso8859-1"), "gbk");
getbytes:表示编码,是指将内存中utf-16(unicode)编码的char,通过计算得到以iso8859-1表示的字节数组,
就是把一个字符char(2位)转换成若干位的过程(比如utf-8,有可能是1或者2或者3位)
newString中的gbk表示解码,是指将字节数组按照gbk的编码方式,如2个字节为一位,按照固定算法,转换成utf-16表示的char
 
 
 
 
e.printStace()没有打到server.log中的原因是不能存在两个log4j.properties。
 
 
[org.xml.sax.SAXParseException: cvc-elt.1: Cannot find the declaration of element 'Msg'.]
at javax.xml.bind.helpers.AbstractUnmarshallerImpl.createUnmarshalException(AbstractUnmarshallerImpl.java:315)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.createUnmarshalException(UnmarshallerImpl.java:505)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:206)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(UnmarshallerImpl.java:173)
at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:137)
at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:184)
at jaxb.Testunmarshallerxml.unmarshallerXml(Testunmarshallerxml.java:82)
at jaxb.Testunmarshallerxml.main(Testunmarshallerxml.java:45)
解决:
 
 
[org.xml.sax.SAXParseException: Premature end of file.]
at javax.xml.bind.helpers.AbstractUnmarshallerImpl.createUnmarshalException(AbstractUnmarshallerImpl.java:315)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.createUnmarshalException(UnmarshallerImpl.java:505)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:206)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(UnmarshallerImpl.java:173)
at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:137)
at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:184)
at jaxb.Testunmarshallerxml.unmarshallerXml(Testunmarshallerxml.java:82)
at jaxb.Testunmarshallerxml.main(Testunmarshallerxml.java:45)
解决:u.unmarshal(fisNetwork);传入的输入流InputStream已至流的末尾。
 
 
 
在dbvisualize里面直接修改db2的某个字段,如果字符串中含有||那么dbvisualize在保存时会自动计算值,但是写sql执行则不会。
 
 
 
用32位还是64位JDK编译出来的Class文件没区别
 
linux上中文显示乱码?
执行 locale -a 查看系统是否已安装utf-8字符集
执行 export LANG=zh_CNexport LC_ALL=zh_CN.utf8设置本地语言环境为utf-8
如果终端(如SecureCRT)编辑脚本时出现乱码,请设置 Menu | Options | Session Options... | Appearence | Character 为utf-8
 
2、LC_CTYPE
用于字符分类和字符串处理,控制所有字符的处理方式,包括字符编码,字符是单字节还是多字节,如何打印等。是最重要的一个环境变量。
 
项目中log4j在英文版linux下输出中文日志为乱码?
由于log4j配置文件中没有设置编码格式(encoding),所以log4j就使用系统默认编码。导致乱码。
解决方法是设置编码格式UTF-8,方法为:
log4j.appender.syslog.encoding=UTF-8
(syslog为你的logger名称)这样就可以了
 
 
没有泛型数组一说
Pair<String>[] stringPairs=new Pair<String>[10];
这种写法编译器会指定一个Cannot create a generic array of Pair<String>的错误
 
 
org.apache.commons.codec.binary.Hex
.encodeHexString()
.decodeHex()
 
 
使用AES加密时,当密钥大于128时,代码会抛出java.security.InvalidKeyException: Illegal key size or default parameters
Illegal key size or default parameters是指密钥长度是受限制的,java运行时环境读到的是受限的policy文件。文件位于${java_home}/jre/lib/security
这种限制是因为美国对软件出口的控制。
解决办法:
去掉这种限制需要下载Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files.网址如下。
下载包的readme.txt 有安装说明。就是替换${java_home}/jre/lib/security/ 下面的local_policy.jar和US_export_policy.jar
jdk 5: http://www.oracle.com/technetwork/java/javasebusiness/downloads/java-archive-downloads-java-plat-419418.html#jce_policy-1.5.0-oth-JPR
jdk6: http://www.oracle.com/technetwork/java/javase/downloads/jce-6-download-429243.html
 
 
数字签名算法是非对称加密算法和消息摘要算法的结合体。要求能够验证数据完整性、认证数据来源、抗否认。
 
 
S6209: [函数/调用]EventGetIntTransIdInf获取内部交易码信息失败,ilRc = [100]!
TBL_MAMGM_EVENT_SVC_CFG少参数
 
 
252.86有的浏览器无法访问,原因是86上不支持TLS1.0协议,把server.xml改掉之后就正常了
<Connector protocol="HTTP/1.1" SSLEnabled="true" ^M
           port="11009" address="${jboss.bind.address}"^M
           scheme="https" secure="true" clientAuth="false" ^M
           keystoreFile="${jboss.server.home.dir}/conf/server.keystore" keystorePass="123456" keystoreType="jks" ^M
           sslProtocol = "SSL" />
     
     
upjas,jms的MDB默认有15个线程在处理,该池不会增大
解决:在default\deploy\hornetq\jms-ds.xml文件中<max-pool-size>20</max-pool-size>
指定了jms的线程池大小
 
 
代码表两个:
TBL_MAMGM_FILTER_APP_CATA
TBL_MAMGM_FILTER_RULE_GRP_CATA
 
TBL_MAMGM_FILTER_APP_INF 过滤应用信息表
TBL_MAMGM_FILTER_APP_DET 过滤应用确定表,定义了包含多个过滤条件组
 
TBL_MAMGM_FILTER_RULE_GRP_INF  RULE_TP 'S'-唯一过滤条件 'R'-范围过滤条件; BLKBILL_IN ‘W’-白名单 'B'-黑名单
TBL_MAMGM_FILTER_RULE_DET 定义了每个过滤条件组的具体取值
 
根据内部交易类型获取控制规则 控制规则检查 
 
 
银行卡共有三个磁道:
一磁道 只读 信息量79位
二磁道 只读 信息量40位
三磁道 读写 信息量107位
国内银联卡的磁道格式说明:
磁道1. “%” + “99(2N)” + “16位卡号(19A)” + “^” + “凸字姓名(26A)” + “^” + “expiry_date YYMM(4N)” + “101或者501(PRMCD.SERV-CODE)” + “CARD.PVV
(5N)” + “0000000000(10N)” + “CVV(3A)” + “00(2N)”+”?”&#61664;共78位数
 
磁道2. “;” + “16位卡号(19A)” + “=” + “expiry_date YYMM(4N)” + “106(3N,服务代码)” + “PVV(5N)” + “00(2N)” + “CVV(3A)” + “?”&#61664;共39位数
 
磁道3. “;” + “99(2N)” + “16位卡号(19A)” + “=” + “156(国家代码3N) ” 
+ “156(货币代码3N) ” + “000000000(金额指数1N&周期授权量4N&本周期余额4N) ” 
+ “000000(周期开始日期4N&周期长度2N) ” + “30000000(密码重输次数1N&个人授权控
制参数6N&交换控制符1N) ” + “000000(PAN的TA和SR& SAN-1的TA和SR& SAN-2的TA和SR
,各2N) ” + “expiry_date YYMM(4N) ” + “0(卡序列号1N) ” + “=” + “0000000
00000(SAN-1,12A) ” + “=” + “000000000000(SAN-2,12A) ” + “=” + “1(传递标
志1N) ” + “000000(加密校验数6N) ” + “00000000(附加数据8N) ” + “?”&#61664;共106位数
 
 
 
委托关系-》
TBL_MAONL_PMT_ENTRUST_INFXX表,共10张
USR_NO
USR_NO_TP
USR_NO_REGION_CD
USR_NO_REGION_ADDN_CD
上面四个字段去找TBL_MAMGM_USR_NO_BIN表,找到后端商户PARENT_MCHNT_CD,然后去商户表找到行业机构代码INDUSTRY_INS_ID_CD,再去找TBL_MAMGM_COMM_LINE_CFG获得链路,发送出去
PMT_NOTV30100101
PMT_NO_TPGD
PMT_ACCT_NO955800000000000001
PMT_ACCT_TPCD-银行卡
支付号码、支付号码类型、账户号码、账户类型
ENTRUST_ACQ_INS_ID_CD00280000   
ENTRUST_TERM_IDTERN0LYC
ENTRUST_MCHNT_CD898320154110210
ENTRUST_ACPT_INS_CD_ID00280000   
委托的渠道接入机构、终端、商户、受理机构代码
 
 
 
配置完成后读者可以通过访问: http://localhost:8088/jmx-console/ ,
输入jmx-console-roles.properties文件中定义的用户名和密码,访问jmx-console的页面。
 
 
 
 
response.sendRedirect向浏览器发送一个特殊的Header,然后由浏览器来做转向,转到指定的页面,所以用sendRedirect时,浏览器的地址栏上可以看到地址的变化
1、response.sendRedirect之后,应该紧跟一句return;
2、在使用response.sendRedirect时,前面不能有HTML输出
用<jsp:forward page=""/>则不同,它是直接在server做的,浏览器并不知道,也不和浏览器打交道,这从浏览器的地址并不变化可以看
 
 
 
会计里面借记什么贷记什么?
这个要根据科目的性质来判断:资产类借方记增加贷方记减少,负债类借方记减少贷方记增加,权益类借方记减少贷方记增加,收入和费用类借减贷加
 
 
JSP中包含swf文件,给swf传的参数中不能包括下划线 _
 
<param name="FlashVars" value="titleNm=<%=request.getParameter("titleNm")%>&syncBatNo=<%=request.getParameter("sync_bat_no")%>&paraTp=<%=request.getParameter("para_tp")%>" />
比如syncBatNo不能写成sync_Bat_No
这样在swf中就可以用如下方法取得值:
private var paratype : String;
paratype =  Application.application.parameters["paraTp"];
 
 
 Flex代码:在Flex中这样取其中obj 即是Java返回的Map
//输出格式为key:value  
for (var itemName:Object in obj){  
       trace(itemName+":"+obj[itemName])  
}  
//输出的只是value             
for each(var itemValue:Object in obj){  
      trace(itemValue.toString())  
}
 
 
 
打印cookie的值:
Cookie[] cs = request.getCookies();
if(cs!=null)
for(Cookie c: cs){
logger.info("c.getComment()="+c.getComment());
logger.info("c.getDomain()="+c.getDomain());
logger.info("c.getMaxAge()="+c.getMaxAge());
logger.info("c.getName()="+c.getName());
logger.info("c.getPath()="+c.getPath());
logger.info("c.getSecure()="+c.getSecure());
logger.info("c.getValue()="+c.getValue());
logger.info("c.getVersion()="+c.getVersion());
logger.info("########################################");
}
新增cookie
Cookie newCook = new Cookie("HOMEPAGESTYLE","1");
newCook.setPath("/isvr");
newCook.setMaxAge(3600*24*365);
response.addCookie(newCook);
没有修改cookie的方法,只可以再addCookie一次
删除cookie就是:newCook.setMaxAge(0);
 
 
 
 
weblogic10默认连接池个数是在config/jdbc/中配置的,最小1,最大100
   <initial-capacity>1</initial-capacity>
    <max-capacity>100</max-capacity>
 
upjas的数据库连接池个数是在vi upjas_tunning_setEnv.sh中配置
MIN_POOL_SIZE=100                    # initial count of db connections
MAX_POOL_SIZE=100                    # max count of db connections
 
db2数据的最大连接个数如下查看
1、db2实例
db2 get dbm cfg
--MAX_CONNECTIONS=AUTOMATIC(MAX_COORDAGENTS)
--MAX_COORDAGENTS=AUTOMATIC(200)
 
两值被设置成 AUTOMATIC,认为db2系统可以承受所有的连接:
db2 update dbm cfg using MAX_COORDAGENTS AUTOMATIC;
db2 update dbm cfg using MAX_CONNECTIONS AUTOMATIC;
 
2、db2数据库
db2 connect to dbname user username  using  passwd
db2 get db cfg
--Max number of active applications            (MAXAPPLS) = AUTOMATIC(323)
 
通过如下命令修改:
db2 update db cfg using MAXAPPLS  number
 
通过这个命令db2 get snapshot for dbm可以看到目前db2连接池的最高个数
High water mark for agents registered          = 12
Agents registered                              = 5
Idle agents                                    = 4
 
 
 
 
db2 "export to ETL_MAMGM_POS_PARA_INF.ixf of ixf select * from MA_MGMDB.ETL_MAMGM_POS_PARA_INF"
 
db2 "import from ETL_MAMGM_POS_PARA_INF.ixf of ixf REPLACE into MA_MGMDB.ETL_MAMGM_POS_PARA_INF"
INSERT | INSERT_UPDATE | REPLACE | REPLACE_CREATE
db2 connect to mamgmdb user maps_db using glbpoc0
 
 
 
248.188 回导多渠道商户终端参数ismgmdb
db2 connect to ISMGMDB user isvrdb3 using isvrdb3
db2 list tablespaces show detail
 
db2 import from MA_ONLDB.TBL_MAONL_TERM_STATIC_INF.ixf of ixf replace into IS_MGMDB.TBL_MAONL_TERM_STATIC_INF
db2 import from MA_ONLDB.TBL_MAONL_MCHNT_STATIC_INF.ixf of ixf replace into IS_MGMDB.TBL_MAONL_MCHNT_STATIC_INF
db2 runstats on table IS_MGMDB.TBL_MAONL_MCHNT_STATIC_INF
db2 runstats on table IS_MGMDB.TBL_MAONL_TERM_STATIC_INF
 
db2 import from MA_MGMDB.TBL_MAMGM_MCHNT_STATIC_INF.ixf of ixf commitcount 10000 replace into IS_MGMDB.TBL_MAMGM_MCHNT_STATIC_INF
db2 import from MA_MGMDB.TBL_MAMGM_TERM_STATIC_INF.ixf of ixf commitcount 10000 replace into IS_MGMDB.TBL_MAMGM_TERM_STATIC_INF
db2 runstats on table IS_MGMDB.TBL_MAMGM_MCHNT_STATIC_INF
db2 runstats on table IS_MGMDB.TBL_MAMGM_TERM_STATIC_INF
 
 
 
让datagrid可以文本选择:
http://stackoverflow.com/questions/1431574/flex-selectable-text-in-datagridcolumn
 
文件SelectableDataGridItemRenderer.as
package com.cup.isvr.view.grid
{
    import mx.controls.dataGridClasses.DataGridItemRenderer;
 
    public class SelectableDataGridItemRenderer extends DataGridItemRenderer
    {
        public function SelectableDataGridItemRenderer()
        {
            super();
            this.selectable = true;
        }
    }
}
用法:
<chkGrid:CheckboxDataGrid itemRenderer="com.cup.isvr.view.grid.SelectableDataGridItemRenderer" id = "dataGrid" width = "100%"  height = "100%" itemClick="ControlUtil.toggleSelected(event)"  doubleClickEnabled="true" itemDoubleClick="dbClicked(event)"/>
 
 
 
Eclipse 3.1 版本代号 IO 【木卫1,伊奥】  
Eclipse 3.2 版本代号 Callisto 【木卫四,卡里斯托】  
Eclipse 3.3 版本代号 Eruopa 【木卫二,欧罗巴】 2007  
Eclipse 3.4 版本代号 Ganymede 【木卫三,盖尼米德】 2008 
Eclipse 3.5 版本代号 Galileo 【伽利略】 2009
Eclipse 3.6 版本代号 Helios 【太阳神】(太阳之神and泰坦海泼里恩之子;阿波罗的后任.) 2010
Eclipse 3.7 版本代号 Indigo 【靛青】 2011
Eclipse 4.2 版本代号 Juno (朱诺(主神朱庇特的妻子), 鸿运当头) 2012
Eclipse 4.3 版本代号 Kepler 2013.6
 
 
 
如何使用JBPM5.4
1、下载Eclipse3.6 Helios,注意启动前修改eclipse.ini最后一行-Xmx256m改成-Xmx128m。
2、下载jbpm-5.4.0.Final-installer-full.zip(http://sourceforge.net/projects/jbpm/files/jBPM%205/jbpm-5.4.0.Final/)
3、解压jbpm-5.4.0.Final-installer-full\jbpm-installer\lib\org.drools.updatesite-5.5.0.Final-assembly.zip,将org.drools.updatesite-5.5.0.Final-assembly目录
拷贝到D:\eclipse3.6\dropins下
4、解压jbpm-5.4.0.Final-installer-full\jbpm-installer\lib\jbpm-5.4.0.Final-bin.zip放入某一目录,
重启eclipse后,在windows-preferences-jbpm-installed jbpm runtime中设置运行环境。
5、新建JBPM工程
 
 
 
 
 
命令行处理器选项设置查询
db2 list command options
 
设置自动提交为off
db2 update command options using c off
 
 
 
2014-01-24 09:35:39,306 [Thread-102852] ERROR com.cup.mtq.comm.mina.entity.tcp.MinaClient -     
java.lang.NoClassDefFoundError: org/apache/mina/core/future/DefaultConnectFuture                
        at org.apache.mina.core.polling.AbstractPollingIoConnector.connect0(AbstractPollingIoCon
nector.java:323)                                                                                
        at org.apache.mina.core.service.AbstractIoConnector.connect(AbstractIoConnector.java:248
)                                                                                               
        at org.apache.mina.core.service.AbstractIoConnector.connect(AbstractIoConnector.java:186
)                                                                                               
        at com.cup.mtq.comm.mina.entity.tcp.MinaClient.connect(MinaClient.java:72)              
        at com.cup.mtq.comm.mina.entity.tcp.MinaClient.connect(MinaClient.java:37)              
        at com.cup.mtq.comm.mina.manager.SysMinaLinkCacheManager$MinaClientLinkReconnectThread.r
un(SysMinaLinkCacheManager.java:455)
解决:重启就好了
 
 
2014-03-04 10:42:52,139 [Thread-64] ERROR com.cup.mtq.comm.mina.entity.tcp.MinaClient - 
java.lang.IllegalStateException: Waiting too long to get the classloader lock: BaseClassLoader@6f876f87{vfszip:/MAMGMAPS/usr/ma_mgmas/upjas/upjas-minimal/server/default/cup-deploy/mjc.war/}
at org.jboss.classloader.spi.base.BaseClassLoader.acquireLockFairly(BaseClassLoader.java:1106)
at org.jboss.classloader.spi.base.BaseClassLoader.loadClassFromDomain(BaseClassLoader.java:838)
at org.jboss.classloader.spi.base.BaseClassLoader.doLoadClass(BaseClassLoader.java:502)
at org.jboss.classloader.spi.base.BaseClassLoader.loadClass(BaseClassLoader.java:447)
at java.lang.ClassLoader.loadClass(ClassLoader.java:619)
at org.apache.mina.core.polling.AbstractPollingIoConnector.connect0(AbstractPollingIoConnector.java:323)
at org.apache.mina.core.service.AbstractIoConnector.connect(AbstractIoConnector.java:248)
at org.apache.mina.core.service.AbstractIoConnector.connect(AbstractIoConnector.java:186)
at com.cup.mtq.comm.mina.entity.tcp.MinaClient.connect(MinaClient.java:72)
at com.cup.mtq.comm.mina.entity.tcp.MinaClient.connect(MinaClient.java:37)
at com.cup.mtq.comm.mina.manager.SysMinaLinkCacheManager$MinaClientLinkReconnectThread.run(SysMinaLinkCacheManager.java:455)
解决:jboss内存设置的比较小。或者环境中cpu或内存不够。
 
 
 
安装eclipse的jquery插件:
1、Help - Find and Install :从remote site中安装插件http://www.spket.com/update/
2.下载jQuery文件,(要下载开发版本). 
3. 设置spket ,Window -> Preferences -> Spket -> JavaScript Profiles -> New,输入“jQuery”点击OK; 
选择“jQuery” 并点击“Add Library”然后在下拉条中选取“jQuery”; 选择 “jQuery”并点击“Add File”,然后选中你下载的jQuery.js 文件;设成Default; 
4.设置js打开方式 (这一步很重要,不设置的话,也不会有jQuery的智能提示),
 Window -> Preferences ->General-> Editors-> File Associations-> 选择*.js,将Spket JavaScript Editor设为Default。 
 
 
xp中保存操作系统的DNS缓存记录
C:\WINDOWS\system32\drivers\etc\hosts
 
 
 
2014-02-21 09:51:50,472 [http-172.17.248.74-11009-4] ERROR com.cup.maps.parameter.sync.ActivationRequester - Parameter change activa
tion failed: can not deliver activation request to ParameterEvent MDB
javax.jms.JMSException: Failed to create session
        at org.hornetq.core.client.impl.ClientSessionFactoryImpl.createSessionInternal(ClientSessionFactoryImpl.java:864)
        at org.hornetq.core.client.impl.ClientSessionFactoryImpl.createSession(ClientSessionFactoryImpl.java:279)
        at org.hornetq.jms.client.HornetQConnection.createSessionInternal(HornetQConnection.java:513)
        at org.hornetq.jms.client.HornetQConnection.createSession(HornetQConnection.java:161)
        at com.cup.maps.parameter.sync.ActivationRequester.activateForCommonParaSync(ActivationRequester.java:172)
        at com.cup.maps.parameter.command.ActivateCommand.sendQueue(ActivateCommand.java:81)
        at com.cup.maps.parameter.command.ActivateCommand.forwardOthers(ActivateCommand.java:71)
        at com.cup.maps.parameter.command.AbstractCommand.execute(AbstractCommand.java:70)
        at com.cup.maps.parameter.ParameterServiceBean.operTask(ParameterServiceBean.java:871)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:60)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:37)
        at java.lang.reflect.Method.invoke(Method.java:611)
        at org.jboss.aop.joinpoint.MethodInvocation.invokeTarget(MethodInvocation.java:122)
        at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:111)
        at org.jboss.ejb3.interceptors.container.ContainerMethodInvocationWrapper.invokeNext(ContainerMethodInvocationWrapper.java:7
2)
        at org.jboss.ejb3.interceptors.aop.InterceptorSequencer.invoke(InterceptorSequencer.java:76)
        at org.jboss.ejb3.interceptors.aop.InterceptorSequencer.aroundInvoke(InterceptorSequencer.java:62)
        at sun.reflect.GeneratedMethodAccessor300.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:37)
        at java.lang.reflect.Method.invoke(Method.java:611)
        at org.jboss.aop.advice.PerJoinpointAdvice.invoke(PerJoinpointAdvice.java:174)
        at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:102)
        at org.jboss.ejb3.interceptors.aop.InvocationContextInterceptor.fillMethod(InvocationContextInterceptor.java:72)
        at org.jboss.aop.advice.org.jboss.ejb3.interceptors.aop.InvocationContextInterceptor_z_fillMethod_549265597.invoke(Invocatio
nContextInterceptor_z_fillMethod_549265597.java)
        at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:102)
        at org.jboss.ejb3.interceptors.aop.InvocationContextInterceptor.setup(InvocationContextInterceptor.java:88)
        at org.jboss.aop.advice.org.jboss.ejb3.interceptors.aop.InvocationContextInterceptor_z_setup_549265597.invoke(InvocationCont
extInterceptor_z_setup_549265597.java)
        at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:102)
        at org.jboss.ejb3.connectionmanager.CachedConnectionInterceptor.invoke(CachedConnectionInterceptor.java:62)
        at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:102)
        at org.jboss.ejb3.entity.TransactionScopedEntityManagerInterceptor.invoke(TransactionScopedEntityManagerInterceptor.java:56)
        at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:102)
        at org.jboss.ejb3.AllowedOperationsInterceptor.invoke(AllowedOperationsInterceptor.java:47)
        at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:102)
        at org.jboss.ejb3.tx.NullInterceptor.invoke(NullInterceptor.java:42)
        at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:102)
        at org.jboss.ejb3.stateless.StatelessInstanceInterceptor.invoke(StatelessInstanceInterceptor.java:68)
        at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:102)
 
        at org.jboss.ejb3.stateless.StatelessInstanceInterceptor.invoke(StatelessInstanceInterceptor.java:68)
        at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:102)
        at org.jboss.aspects.tx.TxPolicy.invokeInOurTx(TxPolicy.java:79)
        at org.jboss.aspects.tx.TxInterceptor$Required.invoke(TxInterceptor.java:190)
        at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:102)
        at org.jboss.aspects.tx.TxPropagationInterceptor.invoke(TxPropagationInterceptor.java:76)
        at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:102)
        at org.jboss.ejb3.tx.NullInterceptor.invoke(NullInterceptor.java:42)
        at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:102)
        at org.jboss.ejb3.security.Ejb3AuthenticationInterceptorv2.invoke(Ejb3AuthenticationInterceptorv2.java:182)
        at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:102)
        at org.jboss.ejb3.ENCPropagationInterceptor.invoke(ENCPropagationInterceptor.java:41)
        at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:102)
        at org.jboss.ejb3.BlockContainerShutdownInterceptor.invoke(BlockContainerShutdownInterceptor.java:67)
        at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:102)
        at org.jboss.ejb3.core.context.CurrentInvocationContextInterceptor.invoke(CurrentInvocationContextInterceptor.java:47)
        at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:102)
        at org.jboss.aspects.currentinvocation.CurrentInvocationInterceptor.invoke(CurrentInvocationInterceptor.java:67)
        at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:102)
        at org.jboss.ejb3.interceptor.EJB3TCCLInterceptor.invoke(EJB3TCCLInterceptor.java:86)
        at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:102)
        at org.jboss.ejb3.stateless.StatelessContainer.dynamicInvoke(StatelessContainer.java:363)
        at org.jboss.ejb3.remoting.IsLocalInterceptor.invokeLocal(IsLocalInterceptor.java:88)
        at org.jboss.ejb3.remoting.IsLocalInterceptor.invoke(IsLocalInterceptor.java:75)
        at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:102)
        at org.jboss.aspects.remoting.PojiProxy.invoke(PojiProxy.java:62)
        at $Proxy275.invoke(Unknown Source)
        at org.jboss.ejb3.proxy.impl.handler.session.SessionProxyInvocationHandlerBase.invoke(SessionProxyInvocationHandlerBase.java
:188)
        at $Proxy295.operTask(Unknown Source)
        at com.cup.maps.portal.flex.ParameterFlexFacade.batchOperTask(ParameterFlexFacade.java:772)
        at com.cup.maps.portal.flex.ParameterFlexFacade$$FastClassByCGLIB$$2305f44f.invoke(<generated>)
        at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
        at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:698)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
        at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:80)
        at com.cup.maps.common.AuthPermission.checkAccess(AuthPermission.java:67)
        at sun.reflect.GeneratedMethodAccessor449.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:37)
        at java.lang.reflect.Method.invoke(Method.java:611)
        at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:621)
        at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:610)
        at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:65)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
        at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:91)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
        at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:631)
        at com.cup.maps.portal.flex.ParameterFlexFacade$$EnhancerByCGLIB$$ee5b83a3.batchOperTask(<generated>)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:60)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:37)
        at java.lang.reflect.Method.invoke(Method.java:611)
        at flex.messaging.services.remoting.adapters.JavaAdapter.invoke(JavaAdapter.java:421)
        at flex.messaging.services.RemotingService.serviceMessage(RemotingService.java:183)
        at flex.messaging.MessageBroker.routeMessageToService(MessageBroker.java:1503)
        at flex.messaging.endpoints.AbstractEndpoint.serviceMessage(AbstractEndpoint.java:884)
        at flex.messaging.endpoints.amf.MessageBrokerFilter.invoke(MessageBrokerFilter.java:121)
        at flex.messaging.endpoints.amf.LegacyFilter.invoke(LegacyFilter.java:158)
        at flex.messaging.endpoints.amf.SessionFilter.invoke(SessionFilter.java:44)
        at flex.messaging.endpoints.amf.BatchProcessFilter.invoke(BatchProcessFilter.java:67)
        at flex.messaging.endpoints.amf.SerializationFilter.invoke(SerializationFilter.java:146)
        at flex.messaging.endpoints.BaseHTTPEndpoint.service(BaseHTTPEndpoint.java:278)
        at flex.messaging.MessageBrokerServlet.service(MessageBrokerServlet.java:322)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
 
        at flex.messaging.MessageBrokerServlet.service(MessageBrokerServlet.java:322)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
        at com.cup.maps.portal.common.filter.SessionFilter.doFilter(SessionFilter.java:94)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
        at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88)
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
        at edu.yale.its.tp.cas.client.filter.CASFilter.doFilter(CASFilter.java:221)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:235)
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
        at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:183)
        at org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:95)
        at org.jboss.web.tomcat.security.SecurityContextEstablishmentValve.process(SecurityContextEstablishmentValve.java:126)
        at org.jboss.web.tomcat.security.SecurityContextEstablishmentValve.invoke(SecurityContextEstablishmentValve.java:70)
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
        at org.jboss.web.tomcat.service.jca.CachedConnectionValve.invoke(CachedConnectionValve.java:158)
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
        at org.jboss.web.tomcat.service.request.ActiveRequestResponseCacheValve.internalProcess(ActiveRequestResponseCacheValve.java
:74)
        at org.jboss.web.tomcat.service.request.ActiveRequestResponseCacheValve.invoke(ActiveRequestResponseCacheValve.java:47)
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:330)
        at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:829)
        at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:599)
        at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:451)
        at java.lang.Thread.run(Thread.java:736)
Caused by:
HornetQException[errorCode=0 message=Failed to create session]
        ... 129 more
Caused by:
java.lang.IllegalStateException: Connection is null
        at org.hornetq.core.client.impl.ClientSessionFactoryImpl.createSessionInternal(ClientSessionFactoryImpl.java:745)
        ... 128 more
原因是jms的connection的session失效了
 
 
 
server.log里面报错:
21 Feb 2014 16:53:21,965 TRACE [org.jboss.management.j2ee.MBean] Failed to initialize state from: 'jboss.jmx:type=adaptor,name=Invok
er,protocol=jrmp,service=proxyFactory' : javax.management.InstanceNotFoundException : jboss.jmx:type=adaptor,name=Invoker,protocol=j
rmp,service=proxyFactory is not registered.
21 Feb 2014 16:53:21,965 DEBUG [org.jboss.management.j2ee.deployers.ServiceModuleJSR77Deployer] Create MBean, name: jboss.jmx:type=a
daptor,name=Invoker,protocol=jrmp,service=proxyFactory, SAR Module: jboss.management.local:J2EEServer=Local,j2eeType=ServiceModule,n
ame=jmx-invoker-service.xml
21 Feb 2014 16:53:21,967 DEBUG [org.jboss.management.j2ee.MBean] postRegister(), parent: jboss.management.local:J2EEServer=Local,j2e
eType=ServiceModule,name=jmx-invoker-service.xml
21 Feb 2014 16:53:21,968 DEBUG [org.jboss.management.j2ee.MBean] Failed to register as listener of: jboss.jmx:type=adaptor,name=MBea
nProxyRemote,protocol=jrmp
解决是:maven打包前clean一下就解决了,原因不明。
 
 
 
英特尔至强E5,服务器CPU(Xeon E5 系列CPU)
 
SCSI即小型计算机系统接口。
小型计算机系统接口(英语:Small Computer System Interface; 简写:SCSI),
一种用于计算机和智能设备之间(硬盘、软驱、光驱、打印机、扫描仪等)系统级接口的独立处理器标准。 
SCSI是一种智能的通用接口标准。它是各种计算机与外部设备之间的接口标准。
 
除了SCSI,IDE也是一种极为常用的接口。
 
 
MTQJ报错?
java.lang.ArrayIndexOutOfBoundsException: Array index out of range: 512
        at java.lang.System.arraycopy(Native Method)
        at java.io.OutputStreamWriter.write(OutputStreamWriter.java:261)
        at java.io.Writer.write(Writer.java:151)
        at org.apache.log4j.helpers.CountingQuietWriter.write(CountingQuietWriter.java:44)
        at org.apache.log4j.WriterAppender.subAppend(WriterAppender.java:301)
        at org.apache.log4j.RollingFileAppender.subAppend(RollingFileAppender.java:236)
        at org.apache.log4j.WriterAppender.append(WriterAppender.java:159)
        at org.apache.log4j.AppenderSkeleton.doAppend(AppenderSkeleton.java:230)
        at org.apache.log4j.helpers.AppenderAttachableImpl.appendLoopOnAppenders(AppenderAttachableImpl.java:65)
        at org.apache.log4j.Category.callAppenders(Category.java:203)
        at org.apache.log4j.Category.forcedLog(Category.java:388)
        at org.apache.log4j.Category.info(Category.java:680)
        at com.cup.mtq.log.LogManager$LogOutputThread.run(LogManager.java:129)
java.lang.ArrayIndexOutOfBoundsException: Array index out of range: 512
        at java.lang.System.arraycopy(Native Method)
        at java.io.OutputStreamWriter.write(OutputStreamWriter.java:261)
        at java.io.Writer.write(Writer.java:151)
        at org.apache.log4j.helpers.CountingQuietWriter.write(CountingQuietWriter.java:44)
        at org.apache.log4j.WriterAppender.subAppend(
解决:磁盘满了,清了就好
 
 
 
myeclipse中spket安装jquery后没有编辑提示的原因是:
1、myeclipse要重启
2、jquery要下载开发版的
3、spket->javascript Profile中要把jquery设置成default
 
 
 
jsp访问时报错:编译jsp失败
org.apache.jasper.JasperException: The absolute uri: http://java.sun.com/jsp/jstl/core cannot be resolved in either web.xml or the jar files deployed with this application
org.apache.jasper.compiler.DefaultErrorHandler.jspError(DefaultErrorHandler.java:51)
org.apache.jasper.compiler.ErrorDispatcher.dispatch(ErrorDispatcher.java:409)
org.apache.jasper.compiler.ErrorDispatcher.jspError(ErrorDispatcher.java:116)
org.apache.jasper.compiler.TagLibraryInfoImpl.generateTLDLocation(TagLibraryInfoImpl.java:316)
org.apache.jasper.compiler.TagLibraryInfoImpl.<init>(TagLibraryInfoImpl.java:149)
org.apache.jasper.compiler.Parser.parseTaglibDirective(Parser.java:386)
org.apache.jasper.compiler.Parser.parseDirective(Parser.java:450)
org.apache.jasper.compiler.Parser.parseElements(Parser.java:1399)
org.apache.jasper.compiler.Parser.parse(Parser.java:130)
org.apache.jasper.compiler.ParserController.doParse(ParserController.java:255)
org.apache.jasper.compiler.ParserController.parse(ParserController.java:103)
org.apache.jasper.compiler.Compiler.generateJava(Compiler.java:185)
org.apache.jasper.compiler.Compiler.compile(Compiler.java:354)
org.apache.jasper.compiler.Compiler.compile(Compiler.java:334)
org.apache.jasper.compiler.Compiler.compile(Compiler.java:321)
org.apache.jasper.JspCompilationContext.compile(JspCompilationContext.java:592)
org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:328)
org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:313)
org.apache.jasper.servlet.JspServlet.service(JspServlet.java:260)
javax.servlet.http.HttpServlet.service(HttpServlet.java:723)
解决:换个jstl.jar包的1.2版本就好了。原因是servelt2.5版需要1.2的jstl包
 
 
 
CSS中点和井号:
#对应id
点对应class
 
jquery设置样式
$("#tt").attr("class","linkvisited");
 
 
jQuery中$("#id")只能选择第一个对象,不能选择所有相同id的元素。
通过 $("input[id='xxxx']"); 可以选择多个相同id的元素。
 
 
jQuery(elements);
我们传递一个element,然后产生一个jquery对象,这个是对象,一定要记住。我们可以把$("")看成是一个构造函数。
这就犹如java中的new 差不多.每调用一次构造函数 都是生成一个新的对象,用==比较 他们自然不会相等。
 
 
datatables 列宽 可拖动?
不支持
 
 
datatables从服务端取报错?
DataTables warning (table id = 'table1'): Requested unknown parameter '0' from the data source for row 0
解决:datatables 接收两种格式的数据,一种json格式的二维数组,另一种是json格式的数组对象,
如果是服务器端返回的json格式的数组对象,在js中需要设置mDataProp这个属性。
json数组:
var ourcountry=[["北京市"],["上海市"],["合肥市","芜湖市","蚌埠市"]]; 
json对象:
var zhongguo={provinces:[{name:"北京",cities:[{name:"北京市",quxian:["海淀区","朝阳区","东城区","西城区"]}]}, 
{name:"安徽省",cities:[{name:"芜湖市",quxian:["繁昌县","芜湖县","南陵县","三山区"]},{name:"合肥市",quxian:["肥西县","蜀山区","庐阳区"]}]}, 
"湖北省" 
]}; 
 
 
 
 
jquery ui 在$("#tabs").tabs时调用了/context?
解决:删除页面中的<base href="<%=basePath%>">语句即可。原因不明
 
 
 
upjas调试模式(监控模式)
打开upjas调试模式:
1. 把run.conf文件中的#JAVA_OPTS="$JAVA_OPTS -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=n"  注释去掉
2. 把jon_upjas_start文件中的 
# uncomment to enable jmx remote management
#JAVA_OPTS="$JAVA_OPTS \
#-Dcom.sun.management.jmxremote.port=12345 \
#-Dcom.sun.management.jmxremote.authenticate=false \
#-Dcom.sun.management.jmxremote.ssl=false \
#-Djboss.platform.mbeanserver \
#-Djavax.management.builder.initial=org.jboss.system.server.jmx.MBeanServerBuilderImpl"
 里面的注释全都去掉
3.重启upjas
 
 
aix查看网卡速率
netstat -v ent0
 
 
http keep-alive超时设置
nginx :keepalive_timeout :75s
tomcat:server.xml 中的Connector 元素中:keepAliveTimeout(单位毫秒);maxKeepAliveRequests:最大长连接个数
jboss:?
 
 
mtqj模拟性能测试端:
D:\mapsworkspace\mtqjperformancetest
 
mtqj打成jar包启动:
/usr/java6_64/bin/java -classpath ".:mjc-1.4.jar:slf4j-log4j12-1.6.1.jar:slf4j-api-1.6.1.jar:org.dtools.javaini-v1.1.00.jar:mina-core-2.0.7.jar:log4j-1.2.15.jar:commons-lang-2.1.jar" com.cup.mtq.Start
 
 
初始化的顺序跟Listener、Filter、Servlet在web.xml中的顺序无关
而多个Filter或多个Servlet的时候,谁的mapping在前面,谁先初始化。
如果web.xml中配置了<context-param>,初始化顺序:
context-param > Listener > Filter > Servlet 
 
 
mtqj以web应用方式使用时,增加是否初始化log4j:
在web.xml中指定下面即可:
<context-param>
<param-name>log4jinit</param-name>  
<param-value>false</param-value>  
</context-param>
修改文件:web.xml MjcLogger MtqInitListenser
 
 
MTQJ负载均衡策略,mtqNetwork.xml中设置负载均衡策略:
1、什么都没有:轮询
2、在host上设置:loadfactor="XXX"(XXX表示0-100),表示请求数负载
3、在domain上设置:lbmethod="bytraffic",在host上设置loadfactor="XXX"(XXX表示0-100),表示按流量负载
 
 
 
Caused by: java.net.UnknownHostException: UnknownHostException invoking http://P570_F_3:7001/csb/shcenter/BillDomain/IntegratedServicePlatformForIndustry/IsvrBatchParaSynchNotifyService/IsvrBatchParaSynchNotifyServiceProxy: P570_F_3
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
 
 
 
org.apache.cxf.interceptor.Fault: Could not send Message.
at org.apache.cxf.interceptor.MessageSenderInterceptor.handleMessage(MessageSenderInterceptor.java:48)
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:271)
at org.apache.cxf.endpoint.ClientImpl.doInvoke(ClientImpl.java:531)
 
 
 
PreparedStatement是如何大幅度提高性能的 
当一个数据库收到一个statement后,数据库引擎会先解析statement,然后检查其是否有语法错误。一旦statement被正确的解析,
数据库会选出执行statement的最优途径。遗憾的是这个计算开销非常昂贵。数据库会首先检查是否有相关的索引可以对此提供帮助,
不管是否会将一个表中的全部行都读出来。数据库对数据进行统计,然后选出最优途径。当决创建查询方案后,数据库引擎会将它执行。
存取方案(Access Plan)的生成会占用相当多的CPU。
一个perpared statement会同一个单独的数据库连接相关联。当数据库连接被关闭时prepared statement也会被丢弃
 
 
 
linux:
top
 
mysql
登陆
mysql客户端连接失败次数超过max_connect_errors次后, 会被自动锁住
 
查看状态变量
show global status;
 
查看二进制文件
show binary logs;
 
查看二进制日志内容
mysqlbinlog XXX
 
查看linux版本
lsb_release -a
 
 
lbpool是根据MySQL的复制机制设计的支持负 载均衡的JDBC连接缓冲池
 
 
d:\Program Files\MySQL\
d:\Documents and Settings\All Users\Application Data\MySQL\MySQL Server 5.5\
 
 
解决MySQL无法远程访问的3方案
1、改表法
mysql mysql -hlocalhost -uroot -p
update user set host='%' where user='root';
flush privileges;
 
 
判断mysql是主库还是从库
使用普通的driver也可以的:String driver = "com.mysql.jdbc.Driver";
使用这个url:String url = "jdbc:mysql:replication://localhost:3306,172.17.236.121:3306/test";
或者这个:String url = "jdbc:mysql://172.17.236.121:3306/test";
show global status like 'Slave_running';
System.out.println(rs.getString(1)+"="+rs.getString(2));//Slave_running=OFF off是主库、on是从库
 
 
 
postgre是个数据库?
 
采用RESOURCE_LOCAL管理事务时,要保证数据库支持事务。例如使用MySQL时,需要设置数据库的引擎类型为“InnoDB”,而“MyISAM”类型是不支持事务的。
 
系统异常包括RuntimeException及其子类,这些异常会导致JTA事务回滚。应用异常即CheckedException子类,不会导致回滚;但是如果应用异常标注了:
@ApplicationException(rollback=true),则JTA容器就会回滚
 
 
MapsDaoServiceBean在初始化时注入unitName = "mapsdb"的EntityManager,代码上将MapsDaoServiceBean对象保存在MAP中,导致了即使EntityManager替换了也没用
 
 
<input type="hidden" id="submittype" />
后台使用request.getParameter("submittype")取值为null,只能在jsp上使用name="submittype"属性后台才能取
 
 
.是类  #是id
id是唯一的,类是可以重用的.
比如你有多个地方样式要求一样的话,就用类.这样就不用些多个#了.
.name{.....}
<div class="name"></div>
<div class="name"></div>     /*就像这样.你多个地方都想要同一个样式就这样写.
 
#Idname{.......}
<div id="Idname"></div>        /*id只有一个.
 
div4=document.getElementById("fourth");
div4.className="yellow";
 
 
div没有disabled属性,因此不能简单的通过设置disabled属性达到效果。
 
任何对象的void finalize()方法只会被系统自动调用一次。
 
java的Calendar类add函数增加年时可以无限,但是数据库的time stamp类型的字段,最大值只能是9999-12-31 23:59:59.999999
 
 
前提:java用map缓存了数据库连接池返回的datasource后:
1、若数据库重启了,程序使用这个datasource时,它不为null,对程序透明,程序照常使用。
2、若数据库停了,程序使用这个datasource时,它不为null,但是在DataSource.getConnection()时报错如下:
org.jboss.util.NestedSQLException: Unable to get managed connection for jdbc/batdb; - nested throwable: (javax.resource.ResourceException: Unable to get managed connection for jdbc/batdb)
然后数据库再次启动后,缓存的datasource还是不为null,程序照常正常使用,对程序透明。
 
 
java.sql.sqlexception can not issue executeUpdate() from selects
 
 
jdbc执行语句select * from tbl_mimgm_ma_resp_cd into outfile 'd:/mysql/11.backup'报如下错误:
java.sql.SQLException:Can't create/write to file 'd:\11.backup'(Errcode:13)
解决:
1、在my.ini中[mysqld]里面添加一行:tmpdir="d:\mysql\"
2、重启mysql server后再次执行
 
 
my.ini在xp中位置如下:D:\Documents and Settings\All Users\Application Data\MySQL\MySQL Server 5.5
导出的文件若不指定绝对路径,位置是:
D:\Documents and Settings\All Users\Application Data\MySQL\MySQL Server 5.5\data\mimgmdb
其中mimgmdb是数据库名
 
 
jdbc执行语句select * from tbl_mimgm_ma_resp_cd into outfile 'd:/mysql/11.backup'报如下错误:
java.sql.SQLException:File 'd:/mysql/11.backup' already exists
解决:目前无法解决。只能先删除,再导出
 
 
jdbc执行语句select * from tbl_mimgm_ma_resp_cd into outfile d:/mysql/222.backup报如下错误:
com.mysql.jdbc.exception.jdbc4,MySQLSyntaxErrorException:You have an error in your SQL syntax;
check the manual that corresponds to your MySQL server version for the right syntax to use near
'd:/mysql/222.backup' at line 1
解决:outfile后面的文件名需要打上单引号
 
 
java.sql.SQLException: Can't get stat of '/home/mi_mgmap/upjas/upjas-minimal/bin/dbpatch/20140520115311.replace.TBL_MIMGM_TRANS_ID_INF' (Errcode: 2)
        at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1078)
解决:
 
 
com.mysql.jdbc.MysqlDataTruncation: Data truncation: Incorrect datetime value: 'null' for column 'REC_UPD_TS' at row 2
        at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4235)
解决:数据库data文件中REC_UPD_TS字段处为null值,在load时报错。
 
 
-Xss128k: 设置每个线程的堆栈大小。JDK5.0以后每个线程堆栈大小为1M,以前每个线程堆栈大小为256K。根据应用的线程所需内存大小进行调整。
在相同物理内 存下,减小这个值能生成更多的线程。但是操作系统对一个进程内的线程数还是有限制的,不能无限生成,经验值在3000~5000左右。
线程栈的大小是个双刃剑,如果设置过小,可能会出现栈溢出,特别是在该线程内有递归、大的循环时
时出现溢出的可能性更大,如果该值设置过大,就有影响到创建栈的数量,如果是多线程的应用,就会
出现内存溢出的错误
 
新生代 = Eden区+Survivor区(这两个比值由-XX:SurvivorRatio=8决定)
-Xmn2g:设置年轻代大小为2G
新生代GC(Minor GC),当Eden区不足以分配对象时触发
老年代GC(Major GC/Full GC),比MinorGC慢10倍以上
 
大对象直接进入老年代,避免大对象在Eden区和Survivor区之间复制拷贝(由-XX:PretenureSizeThreshlod=3145728B)
 
如果对象在Eden出生并经过第一次MinorGC后仍然存活,并且能被Survivor容纳,将被移动到Survivor空间中,并将对象年龄设为1。
对象在Survivor区中每熬过一次MinorGC,年龄就增加1岁,当它的年龄增加到一定程度(默认为15岁)时,就会被晋升到老年代。
这个年龄值可以通过参数-XX:MaxTenuringThreshold来设置。
 
jvm启动时的数据区域:
1、程序计数器:线程私有,较小内存,当前线程所执行的字节码的行号指示器,无OutOfMemoryError情况。
2、java虚拟机栈:线程私有,生命周期与线程相同,每个方法执行时会创建一个栈帧(Stack Frame)用于存储局部变量表、操作栈、动态链接、方法出口等。抛出StackOverflowError、OutOfMemoryError异常。
3、本地方法栈:虚拟机使用Native方法服务。
4、java堆:各线程共享区域。新生代(Eden + From Survivor + To Survivor)+老年代。抛出OutOfMemoryError。
5、方法区:各线程共享区域。又叫永久代。存储被虚拟机加载的类信息、常量、静态变量、即时编译器JIT编译后的代码。抛出OutOfMemoryError。-XX:MaxPermSize。只有sun的虚拟机需要设置,jrockit和ibm虚拟机无需设置。
6、运行时常量池:方法区的一部分;class文件中除包含类版本、字段、方法、接口等外,还有编译期生成的各种字面常量和符号引用。抛出OutOfMemoryError。
7、直接内存Direct Memory:不是虚拟机运行时数据区的一部分。java NIO引入的使用native函数库直接分配的堆外内存,
java堆里面的DirectByteBuffer对象是这块堆外内存的引用,避免了在java堆和native堆来回复制数据。
抛出OutOfMemoryError。-XX:MaxDirectMemorySize。垃圾回收器不会主动回收,只在full gc时顺便清理direct memory
 
实践经验:
除java堆和永久代外,下面也会占用内存,这里所有内存的总和受到操作系统进程最大内存的限制。
1、Direct Memory:OutOfMemoryError:Direct buffer memory。
2、线程堆栈:-Xss。 StackOverflowError无法分配新的栈帧;OutOfMemoryError无法建立新的线程。
3、socket缓存区。每个socket连接都有Receive和Send两个缓存区;分别占37KB和25KB内存。
4、JNI代码:使用JNI调用本地库,使用内存不在堆里面。
5、虚拟机和GC:虚拟机和GC的代码执行也消耗一定内存。
 
导致Gc的情况:
1、老年代(tenured)被写满
2、perm被写满
3、System.gc()的显式调用。
4、上一次GC之后heap的各域分配策略动态变化。
 
 
 
F5对后台应用做健康检查
1、Layer2层,F5会发送给服务器IP地址的ARP请求,服务器会响应这个ARP请求。
2、Layer3层,F5会发送给服务器ping命令,用来确认IP地址是否在网络中存在或者主机是否正常工作。
3、Layer4层,F5的负载均衡器会试图建立一个连接到服务器TCP或者UDP的某个端口,发送一个TCP SYN
请求包,并检查回应的TCP SYN ACK数据包是否收到。
 
 
 
upjas停止时打出
Heap
 PSYoungGen      total 458752K, used 62915K [0x00000000e0000000, 0x0000000100000000, 0x0000000100000000)
  eden space 393216K, 16% used [0x00000000e0000000,0x00000000e3d70c08,0x00000000f8000000)
  from space 65536K, 0% used [0x00000000f8000000,0x00000000f8000000,0x00000000fc000000)
  to   space 65536K, 0% used [0x00000000fc000000,0x00000000fc000000,0x0000000100000000)
 ParOldGen       total 1048576K, used 1339K [0x00000000a0000000, 0x00000000e0000000, 0x00000000e0000000)
  object space 1048576K, 0% used [0x00000000a0000000,0x00000000a014ece0,0x00000000e0000000)
 PSPermGen       total 131072K, used 8292K [0x0000000090000000, 0x0000000098000000, 0x00000000a0000000)
  object space 131072K, 6% used [0x0000000090000000,0x0000000090819370,0x0000000098000000)
  
 
管理upjas启动vm参数
14:38:19,727 INFO  [ServerInfo] VM arguments: 
-Dprogram.name=run.sh -XX:+UseParallelOldGC -XX:ParallelGCThreads=2 
-XX:PermSize=128m -XX:MaxPermSize=256m 
-verbose:gc -XX:+PrintGCDetails -XX:+PrintGCDateStamps 
-Dorg.jboss.resolver.warning=true 
-Dsun.rmi.dgc.client.gcInterval=3600000 
-Dsun.rmi.dgc.server.gcInterval=3600000 
-Dsun.lang.ClassLoader.allowArraySyntax=true 
-Dorg.jboss.ejb3.remoting.IsLocalInterceptor.passByRef=true 
-Ddb2.jcc.charsetDecoderEncoder=3 
-Dorg.jboss.net.protocol.file.useURI=false 
-DpwdServerIp=172.17.248.74 
-DpwdServerPort=7000 
-DpwdServerIp_bak=172.17.252.63 
-DpwdServerPort_bak=11140 
-Xms1536m -Xmx1536m 
-Djava.net.preferIPv4Stack=true 
-Djava.endorsed.dirs=/home/mi_mgmap/upjas/upjas-minimal/lib/endorsed 
 
 
管理upjas启动时gc日志
2014-05-06T14:38:29.602+0800: [GC [PSYoungGen: 393216K->46465K(458752K)] 393216K->46465K(1507328K), 0.2396330 secs] [Times: user=0.39 sys=0.07, real=0.24 secs] 
2014-05-06T14:38:31.725+0800: [GC [PSYoungGen: 147560K->61885K(458752K)] 147560K->61885K(1507328K), 0.2032700 secs] [Times: user=0.34 sys=0.06, real=0.20 secs] 
2014-05-06T14:38:31.929+0800: [Full GC (System) [PSYoungGen: 61885K->0K(458752K)] [ParOldGen: 0K->61565K(1048576K)] 61885K->61565K(1507328K) [PSPermGen: 29108K->29067K(131072K)], 1.1917110 secs] [Times: user=2.09 sys=0.07, real=1.19 secs] 
2014-05-06T14:38:39.731+0800: [GC [PSYoungGen: 393216K->35370K(458752K)] 454781K->96935K(1507328K), 0.0990800 secs] [Times: user=0.26 sys=0.01, real=0.10 secs] 
2014-05-06T14:38:46.592+0800: [GC [PSYoungGen: 428586K->59203K(458752K)] 490151K->120768K(1507328K), 0.2902710 secs] [Times: user=0.54 sys=0.00, real=0.28 secs] 
2014-05-06T14:38:53.579+0800: [GC [PSYoungGen: 452419K->65514K(458752K)] 513984K->150727K(1507328K), 0.3100880 secs] [Times: user=0.59 sys=0.02, real=0.31 secs] 
2014-05-06T14:39:02.693+0800: [GC [PSYoungGen: 458730K->65533K(371712K)] 543943K->180368K(1420288K), 0.2337030 secs] [Times: user=0.47 sys=0.02, real=0.23 secs] 
2014-05-06T14:39:05.698+0800: [GC [PSYoungGen: 371709K->75946K(415232K)] 486544K->190782K(1463808K), 0.2553100 secs] [Times: user=0.70 sys=0.00, real=0.26 secs] 
jlog.properties properties file found and used:URL=file:/home/mi_mgmap/upjas/upjas-minimal/server/default/cup-deploy/appCfg/jlog.properties
log4j.properties properties file found and used:URL=file:/home/mi_mgmap/upjas/upjas-minimal/server/default/cup-deploy/appCfg/log4j.properties
2014-05-06T14:39:14.944+0800: [GC [PSYoungGen: 382122K->85144K(409152K)] 496958K->219570K(1457728K), 0.4262070 secs] [Times: user=0.70 sys=0.05, real=0.42 secs] 
2014-05-06T14:39:21.885+0800: [GC [PSYoungGen: 385688K->66670K(412416K)] 520114K->231316K(1460992K), 0.5258480 secs] [Times: user=0.85 sys=0.07, real=0.52 secs] 
2014-05-06T14:39:32.110+0800: [GC [PSYoungGen: 367214K->60090K(419456K)] 531860K->247241K(1468032K), 0.3460030 secs] [Times: user=0.60 sys=0.02, real=0.35 secs] 
2014-05-06T14:39:41.029+0800: [GC [PSYoungGen: 372154K->54631K(416896K)] 559305K->260258K(1465472K), 0.3492870 secs] [Times: user=0.52 sys=0.03, real=0.35 secs] 
defaultCasLogin:http://172.17.248.56:6008/sso/login
2014-05-06T14:39:54.952+0800: [GC [PSYoungGen: 366695K->45038K(421184K)] 572322K->269223K(1469760K), 0.3133260 secs] [Times: user=0.50 sys=0.02, real=0.31 secs] 
 
 
 
启动时,YoungGen的大小是448M(1536*7/24);当使用到384M(即6/7的总内存时)时触发一次MinorGC
ParOldGen大小是1024M
PSPermGen大小是128M
 
并行(Parallel):垃圾收集线程并行工作,用户线程处理等待状态。
并发(Concurrent):用户线程与垃圾收集线程同时执行。
 
 
Parallel Scavenge收集器也被称作“吞吐量优先”收集器,新生代垃圾收集器,使用复制算法,并行处理,目标是达到一个可控的吞吐量,它的参数包括:
-XX:MaxGCPauseMillis     大于0的毫秒数,收集器尽量保证内存回收话费时间不超过该值。
-XX:GCTimeRatio     大于0小与100的整数,垃圾收集时间占总时间的比率,相当于吞吐量的倒数,默认99,就是容许最大1%(1/(99+1))的垃圾收集时间
-XX:UseAdaptiveSizePolicy   这个开关打开之后,就不需要手工指定新生代大小(-Xmn)、Eden与Survivor比例(-XX:SurvivorRatio),虚拟机动态调整。
-XX:+UseConcMarkSweepGC -XX:+UseParNewGC 使用CMS收集器,(CMS收集时的停顿时间只是收集过程中的一小部分)
 
Serial Old收集器,是Serial收集器的老年版本,单线程收集器,使用标记-整理算法。
Parallel Old:Parallel Scavenge的老年代版本,使用多线程和“标记-整理”算法。
CMS(Concurrent Mark Sweep)收集器是以获取最短回收停顿时间为目标的收集器,使用标记-清除算法,几种运用在互联网站或B/S系统的服务端上,重视响应速度。
优点是:并发收集(不会导致用户线程停顿)、低停顿。缺点是:对cpu资源较敏感;无法处理浮动垃圾;产生大量空间碎片。
G1收集器,基于标记-整理算法,
 
 
UseParallelOldGC = Parallel Scavenge + Parallel Old
 
 
 
运行日志
异常堆栈
GC日志         ibm jdk gc(xml格式) 查看工具ga441.zip
线程快照(threaddump/javacore)     kill -3
堆转储快照(heapdump/dump/hprof)-XX:+HeapDumpOnOutOfMemoryError   or  kill -3   or    jmap工具
 
 
 
 
jps:列出正在运行的虚拟机进程。 -q -m -l -v
jstat:监视虚拟机各种运行状态信息,可以显示本地或者远程虚拟机进程中的类装载、内存、垃圾收集、JIT编译等运行数据。如:jstat -gcutil pid
jinfo:实时查看或者调整各项虚拟机参数。
jmap:生成堆转储快照heapdump文件。如:jmap -dump:format=b,file=d:/eclipse.bin pid
jhat:与jmap搭配,分析heapdump文件,之后生成html文件,浏览器中键入http://localhost:7000/就可以看到分析结果。
jstack:生成虚拟机当前时刻的线程快照,是当前虚拟机内每一个线程正在执行的方法堆栈的集合。主要目的是定位线程长时间停顿的原因。如:jstack -l pid
jconsole:运行监视、故障处理
jvisualvm:除运行监视、故障处理外,还提供性能分析(双击应用程序-右边Profiler-性能分析CPU、内存)。工具-插件-可用插件,里面列出所有可用插件。BTrace动态日志。
 
 
 
 
apache在做负载均衡时要对同一sessionid分配到同一个服务器上?
 
 
系统总内存 = RAM + SWAP分区(linux)或者分页文件(aix)
 
 
java代码编译出来后形成的class文件中存储的是字节码,虚拟机通过解释方式执行字节码命令,比起C编译成本地二进制代码来说速度慢不少。
为解决慢的问题,jdk1.2以后,虚拟机内置了两个运行时编译器,如果一段java方法被调用的次数到达一定程度,就会被判定为热代码(hot spot code),从而交给
JIT(just in Time Compiler)编译器即时编译为本地代码,以提高运行速度。
 
虚拟机运行在-client模式时,使用代号为C1的轻量编译器,运行在-server模式下,使用代号为C2的重量级编译器,
-client,-server
这两个参数用于设置虚拟机使用何种运行模式,client模式启动比较快,但运行时性能和内存管理效率不如server模式,通常用于客户端应用程序。相反,server模式启动比client慢,但可获得更高的运行性能。
在windows上,缺省的虚拟机类型为client模式,如果要使用server模式,就需要在启动虚拟机时加-server参数,以获得更高性能,对服务器端应用,推荐采用server模式,尤其是多个CPU的系统。在Linux,Solaris上缺省采用server模式。
 
使用-classpath后虚拟机将不再使用CLASSPATH中的类搜索路径,如果-classpath和CLASSPATH都没有设置,则虚拟机使用当前路径(.)作为类搜索路径。
 
使用-XX:+DisableExplicitGC屏蔽程序主动触发的System.gc()
 
 
表 1. IBM SDK 5.0 中的 GC 策略
策略选项描述
针对吞吐量进行优化-Xgcpolicy:optthruput(可选)默认策略。对于吞吐量比短暂的 GC 停顿更重要的应用程序,通常使用这种策略。每当进行垃圾收集时,应用程序都会停顿。
针对停顿时间进行优化-Xgcpolicy:optavgpause通过并发地执行一部分垃圾收集,在高吞吐量和短 GC 停顿之间进行折中。应用程序停顿的时间更短。
分代并发-Xgcpolicy:gencon以不同方式处理短期存活的对象和长期存活的对象。采用这种策略时,具有许多短期存活对象的应用程序会表现出更短的停顿时间,同时仍然产生很好的吞吐量。
子池-Xgcpolicy:subpool采 用与默认策略相似的算法,但是采用一种比较适合多处理器计算机的分配策略。建议对于有 16 个或更多处理器的 SMP 计算机使用这种策略。这种策略只能在 IBM pSeries? 和 zSeries? 平台上使用。需要扩展到大型计算机上的应用程序可以从这种策略中受益。
 
ibm的分代并发:nursery(年轻代)占总javaheap的22.5%,tenured(老年代)占总javaheap的75%,还少2.5%不知道去哪里???
ibm jdk关于gc的几个配置项(upjas在这个文件里面vi upjas_all_setEnv.sh):
-verbose:gc     打开gc日志项
-verbose:gc -Xverbosegclog:gc.log  打开gc日志,并记录到bin下的gc.log文件中去
-XX:+PrintGCDetails -XX:+PrintGCDateStamps  gc日志记录gc的详细信息以及时间
-Xgcpolicy:optavgpause  gc策略(有几项:optthruput、optavgpause、gencon、subpool)
 
倒数第一行前加入:
JAVA_OPTS="$JAVA_OPTS -verbose:gc -Xverbosegclog:gc.log -XX:+PrintGCDetails -XX:+PrintGCDateStamps"
 
再加两个参数 -XX:+PrintGCApplicationConcurrentTime -XX:+PrintGCApplicationStoppedTime对暂停时间看得更清晰。 
 
 
upjas的run.conf设置了
-Dsun.rmi.dgc.client.gcInterval=3600000 -Dsun.rmi.dgc.server.gcInterval=3600000
 
 
 
JConsole连接监控:此进程中未启动代理管理java进程不了什么原因?
解决:在vm arguments中添加“-Dcom.sun.management.jmxremote”
 
class文件结构:
1、魔数
2、class文件版本
3、常量池
4、访问标志
5、类索引、父类索引与接口索引集合
6、字段表集合
7、方法表集合
8、属性表集合
 
方法的描述与字段的描述几乎一致,依次包括了访问标志(acess_flags)、名称索引(name_index)、描述符索引(descriptor_index)、属性表集合(attributes)
 
打印class文件结构工具:
javap -verbose Testjavap
结果:
Compiled from "Testjavap.java"
public class Testjavap extends java.lang.Object
  SourceFile: "Testjavap.java"
  minor version: 0
  major version: 50
  Constant pool:
const #1 = class        #2;     //  Testjavap
const #2 = Asciz        Testjavap;
const #3 = class        #4;     //  java/lang/Object
const #4 = Asciz        java/lang/Object;
const #5 = Asciz        i;
const #6 = Asciz        I;
const #7 = Asciz        <init>;
const #8 = Asciz        ()V;
const #9 = Asciz        Code;
const #10 = Method      #3.#11; //  java/lang/Object."<init>":()V
const #11 = NameAndType #7:#8;//  "<init>":()V
const #12 = Field       #1.#13; //  Testjavap.i:I
const #13 = NameAndType #5:#6;//  i:I
const #14 = Asciz       LineNumberTable;
const #15 = Asciz       LocalVariableTable;
const #16 = Asciz       this;
const #17 = Asciz       LTestjavap;;
const #18 = Asciz       main;
const #19 = Asciz       ([Ljava/lang/String;)V;
const #20 = Asciz       args;
const #21 = Asciz       [Ljava/lang/String;;
const #22 = Asciz       SourceFile;
const #23 = Asciz       Testjavap.java;
 
{
public int i;
 
public Testjavap();
  Code:
   Stack=2, Locals=1, Args_size=1
   0:   aload_0
   1:   invokespecial   #10; //Method java/lang/Object."<init>":()V
   4:   aload_0
   5:   iconst_0
   6:   putfield        #12; //Field i:I
   9:   return
  LineNumberTable:
   line 2: 0
   line 4: 4
   line 2: 9
 
  LocalVariableTable:
   Start  Length  Slot  Name   Signature
   0      10      0    this       LTestjavap;
 
 
public static void main(java.lang.String[]);
  Code:
   Stack=0, Locals=1, Args_size=1
   0:   return
  LineNumberTable:
   line 11: 0
 
  LocalVariableTable:
   Start  Length  Slot  Name   Signature
   0      1      0    args       [Ljava/lang/String;
 
 
}
 
eclipse中编译class的major_version属性设置在:
window-Preferences-java-Compiler-Configure Project Specific Settings-选择某一项目
- ok - “Compiler compliance level”选择6.0 - ok即可。
 
 
DK 编译器版本target 参数十六进制 minor.major十进制 minor.major
jdk1.1.8不能带 target 参数00 03 00 2D45.3
jdk1.2.2不带(默认为 -target 1.1)00 03 00 2D45.3
jdk1.2.2-target 1.200 00   00 2E46.0
jdk1.3.1_19不带(默认为 -target 1.1)00 03 00 2D45.3
jdk1.3.1_19-target 1.300 00   00 2F47.0
j2sdk1.4.2_10不带(默认为 -target 1.2)00 00   00 2E46.0
j2sdk1.4.2_10-target 1.400 00   00 3048.0
jdk1.5.0_11不带(默认为 -target 1.5)00 00   00 3149.0
jdk1.5.0_11-target 1.4 -source 1.400 00   00 3048.0
jdk1.6.0_01不带(默认为 -target 1.6)00 00   00 3250.0
jdk1.6.0_01-target 1.500 00   00 3149.0
jdk1.6.0_01-target 1.4 -source 1.400 00   00 3048.0
jdk1.7.0不带(默认为 -target 1.6)00 00   00 3250.0
jdk1.7.0-target 1.700 00   00 3351.0
jdk1.7.0-target 1.4 -source 1.400 00   00 3048.0
Apache Harmony 5.0M3不带(默认为 -target 1.2)00 00   00 2E46.0
Apache Harmony 5.0M3-target 1.400 00   00 3048.0
 
 
class文件类加载的生命周期:
1、加载
2、连接:验证、准备、解析
3、初始化
4、使用
5、卸载
 
只有遇到以下四种情况jvm才会立即对类进行初始化:
1、遇到new、getstatic、putstatic、invokestatic这四条字节码指令。
2、使用java.lang.reflect包的方法对类进行反射调用
3、当初始化一个类时,如果发现其父类没有进行初始化,需要先初始化其父类
4、当虚拟机启动时,用户需要指定一个要执行的类(包含main方法的那个类),虚拟机会先初始化这个主类。
除此之外,引用类的方式是被动引用,不会触发初始化:
1、通过子类引用父类的静态字段,不会导致子类初始化
2、通过数组定义来引用类,不会触发此类的初始化
3、调用别的类的常量,在编译时直接进入类的常量池,因此不会触发类的初始化。
 
 
<clinit>()方法是由编译器自动收集类中的所有类变量的赋值动作和静态语块(static{})中的语句合并而成,与类的构造函数(init())不同,
父类的<clinit>()方法先执行。
执行接口的<clinit>()方法不需要先执行父接口的<clinit>()方法。
虚拟机会保证一个类的<clinit>()方法在多线程环境中被正确的加锁和同步。
 
 
类加载器:
1、启动类加载器(Bottstrap ClassLoader)负责将存放在<JAVA_HOME>\lib目录中的,或者被-Xbootclasspath参数指定的路径中的,且被虚拟机识别的(严格按照文件名,如rt.jar)
2、扩展类加载器(Extension ClassLoader)负责加载<JAVA_HOME>\lib\ext目录中的,或者被java.ext.dirs系统变量所指定的路径中的所有类库
3、应用程序类加载器(Application ClassLoader)负责加载classpath中所指定的类库。
 
 
每一个栈帧都包括了局部变量表、操作数栈、动态连接、方法返回地址和一些额外的附加信息,在编译时,栈帧需要多大的局部变量表、多深的操作数栈都已经完全确定了。
 
java虚拟机提供了四条方法调用字节码指令:
1、invokestatic:调用静态方法。
2、invokespecial:调用实例构造器init方法、私有方法、父类方法。
3、invokevirtual:调用所有虚方法。
4、invokeinterface:调用接口方法,在运行时确定一个实现此接口的对象。
 
 
重载参数匹配优先级
char
int
long
Character
Serializable
Object
char... arg(变长参数的优先级最低)
 
变量被定义成volatile后具有两种特性;
1、保证此变量对所有线程可见:当前一线程修改此变量值时,另外的线程立即得知,普通变量在线程间传递需要通过主存完成。
showdown(){}停止线程这类场景很适合volatile来控制并发,调用showdown时可以保证所有线程立即停下。
2、禁止指令重排序化:在一个线程的方法执行过程中,赋值或者声明语句可能被重新排序,加了volatile后可以避免此情况
 
 
java内存模型定义了如何在工作内存和主内存间相互操作的的八个操作,要求lock、unlock、read、load、assign、use、store、write八个操作都具有原子性。
lock:作用于主内存的变量,把一个变量标识为一条线程独占的状态。
unlock:解锁,作用于主内存的变量,把一个处于锁定状态的变量释放出来。
read:作用于主内存的变量,把一个变量的值从主内存传输到线程的工作内存中。
load:作用于工作内存的变量,把read操作从主内存中得到的变量值放入工作内存的变量副本中。
use:作用于工作内存的变量,把工作内存中一个变量的值传递给执行引擎。
assign:作用于工作内存的变量,把一个执行引擎接收到的值赋给工作内存的变量。
store:作用于工作内存的变量,把工作内存的一个变量值传送到主内存中。
write:作用于主内存的变量,把store操作从工作内存中得到的变量的值放入主内存的变量中。
 
把一个变量从主内存复制到工作内存,要顺序执行read和load操作。把变量从工作内存同步到主内存,要顺序执行store和write操作。
java内存模型只要求两个操作要按顺序执行,并不保证必须是连续执行的。
 
 
并发的三个特性是:原子性、可见性、有序性。
 
java的线程是被映射到系统的原生线程来实现的。java提供10个级别的线程优先级(10最高,1最低),windows只有7种
 
线程安全程度从高到低:
1、不可变:Immutable,如:java.lang.String  java.lang.Integer(此类中定义了private final int value;)
2、绝对线程安全:
3、相对线程安全:Vector HashTable Collections的synchronizedCollection()方法包装的集合
4、线程兼容:ArrayList HashMap  对象本身并不是线程安全的,但是通过调用端正确的使用,保证并发环境安全的使用
5、线程对立:不管调用端采用如何措施,都无法在多线程环境中并发使用的代码。Thread的suspend和resume方法,如果suspend中断的线程就是即将要执行resume的那个线程,那就肯定要死锁。
 
 
线程安全的实现方法
1、互斥同步:synchronized使用操作系统互斥量来实现锁机制
2、非阻塞同步
3、无同步方案:可重入代码+线程本地存储
 
 
一些确保线程安全的方法 访问共享的,可变的数据,要求同步,为了保证变量元素的可见性,可以采用如下方法: 
① 线程封闭 最简单的方式就是不共享数据,如果数据仅在单线程中访问,就不需要任何同步。线程封闭技术是实现线程安全的最简单的方式,当对象封闭在一个线程中,
这种做法会自动成为线程安全的,即使被封闭的对象本身并不是。比如JDBC的连接池,虽然JDBC本身规范并没有要求Connection对象是线程安全的,但是在典型的服务器
应用中,线程总是从池中获得一个Connection对象,并且用它处理一个单一的请求,最后把它归还,每个线程都会同步地处理大多数请求,而且在Connection对象在被
归还前,池不会将它再分配给其他线程。
② 栈限制 将变量限制在方法中。 
③ ThreadLocal 它允许将变量和线程关联在一起,使得每个线程都有一份单独的拷贝。
④ 不可变性 不可变对象永远是线程安全的,一个对象是不可变的饿,要求它的状态创建后不会改变,所有域都是final类型,并且,它被正确创建。
 
 
 
StringBuffer的append方法是加上synchronized的。
 
JAVA编译期优化:
几乎没有
javac将java代码转变为字节码的编译器称作前端编译器。
 
 
JAVA运行期优化:
当程序需要迅速启动和执行时,解释器可以首先发挥作用,随着时间推移,编译器逐渐发挥作用,把越来越多的代码编译成本地代码,提高执行效率。
-Xint强制虚拟机运行于解释模式
-Xcomp强制虚拟机运行于编译模式
热点代码被执行client模式是1500次,server模式下是10000次,超过这个数将会触发JIT编译。这个次数是一段时间的被调用次数。使用-XX:CounterHalfLifeTime参数设置半衰期时间单位是秒。
-XX:-BackgroundCompilation来禁止后台JIT编译
-XX:+PrintCompilation要求虚拟机在即时编译时将编译成本地代码的方法名打印出来。(debug版的虚拟机支持)
-XX:+PrintInlining要求虚拟机输出内联信息。
 
JIT优化有很多技术,包括:
1、公共子表达式消除:b*c和c*b是一组公共表达式。
2、数组边界检查消除:访问数组元素foo[i]时系统会自动进行上下界的范围检查,否则会抛出ArrayIndexOutOfBoundsExcepiton,
如果编译器通过分析数据流判断循环变量的取值范围永远在[0,foo.length)之内,就可以把数组的上下界检查消除掉。
3、方法内联:把目标方法的代码复制到调用的方法中,避免发生真是的方法调用。只有使用了invokespecial指令调用的私有方法、实例构造器、父类方法和使用
invokestatic指令进行调用的静态方法、使用invokevirtual指令的被final修饰的方法才能内联。
java大部分方法都是虚方法。
激进优化:”类型继承关系分析CHA“技术,查询此方法是否有多个版本可供选择,如果只有一个版本,可以进行内联。如果加载了导致继承关系发生变化的新类,
需要抛弃已编译的代码,退回到解释状态执行,或者重新编译;如果有多个版本,编译器将会做最后一次努力。
4、逃逸分析:分析对象动态作用域。如果能证明一个对象不会逃逸到方法或者线程之外,那么可以在栈上分配对象;
如果能确认一个变量不会逃逸出线程,无法被其它线程访问,那么对此变量的同步措施就可消除;
把一个java对象拆散,根据访问情况,将其成员变量恢复到原始类型访问,叫标量替换,如果进一步证明对象不会逃逸,
那么虚拟机可能不会创建这个对象,使用成员变量代替,在栈上分配(栈上存储的数据很大机会会被虚拟机分配至物理机器的高速寄存器中存储)。
 -XX:DoEscapeAnalysis开启逃逸分析
 -XX:+PrintEscapeAnalysis查看分析结果
 -XX:+EliminateAllocations开启标量替换
 -XX:+EliminateLocks开启同步消除
 -XX:+PrintEliminateAllocations 查看标量的替换情况
 
 
java虚拟机家族:
sun hotspot:sun jdk1.3后的默认虚拟机。
bea JRockit:bea公司专注于服务端应用,内部不含解释器的实现,全部代码都靠JIT。
ibm J9:ibm单独开发的jvm
 
apache harmony:间接催生了google android平台的Dalvik虚拟机(嵌入式)。
 
 
apache提供了一个工具htcacheclean来清理由mod_disk_cache模块生成的缓存。
htcacheclean -p 目录 -l 50k
 
linux下最大文件描述符的限制有两个方面,一个是用户级的限制,另外一个则是系统级限制。
以下是查看Linux文件描述符的三种方式:
[root@localhost ~]# sysctl -a | grep -i file-max --color
fs.file-max = 392036
[root@localhost ~]# cat /proc/sys/fs/file-max
392036
[root@localhost ~]# ulimit -n
1024
查看当前进程的文件描述符限制linux:
vi /proc/[pid]/limits
 
 
apache的错误日志由核心模块mod_core提供。
LogLevel指定记录错误级别:emerg、alert、crit、error、warn、notice、info、debug
默认错误文件放在ServerRoot的logs目录中,使用ErrorLog来重新指定新位置或文件名。关闭错误日志:ErrorLog /dev/null
 
 
AB测试服务器性能
D:\Program Files\Apache Software Foundation\Apache2.2\bin>ab -n 100 -c 10 http://172.17.254.155:11000/mjc/
ab -n 100 -c 50 http://146.240.25.40:12000/wcg/webtest/1?a=1
ab -n 100 -c 50 http://146.240.25.39:4488/
ab -n 100 -c 50 http://146.240.25.40:4488/
 
ab -n 10000 -c 10 http://172.17.248.74:11000/test/webtrans
 
ab -n 100 -c 50 http://146.240.25.39:12000/test/webtrans
 
 
报class "org.apache.log4j.PropertyConfigurator"'s signer information does not... 
博客分类: tomcat 
Apachelog4j 
今天将tomcat5.5中的工程放在tomcat6.0里跑,报: 
class "org.apache.log4j.PropertyConfigurator"'s signer information does not。。。。。 
郁闷了,仔细看似乎是log4j的问题,其实不然,检查jftp.jar包,发现它里面也有log4j的包,可能是冲突了,于是干脆把jftp.jar包删了,重启,没事了!阿门! 
但是不知道jftp.jar做什么用的,这样删掉会不会出问题,为了保险起见删掉jftp.jar里面包含有Apache的代码,因为我的Project也有Apache的jar,估计是冲突。将jftp.jar里面的所有org包下的class都删掉。 
jftp.jar这个包初看好像是用ftp做上传功能用的,如果没用到全删。免得以后再出这样的问题。 
 
 
 
mtqj的web.xml中配置了如下语句,即可使得mtqj不会初始化log4j:
<context-param>
<param-name>log4jinit</param-name>  
<param-value>false</param-value>  
</context-param>
<listener>   
<!-- 指定Listener 的实现类-->   
<listener-class>com.cup.mtq.MtqInitListener</listener-class>   
</listener>  
 
 
wcg.war应用启动,读CommPacket.ini文件时,nohup报错
java.lang.IllegalArgumentException: URI scheme is not "file"
解决:web-inf/classes里面添加了mtqCfg的目录
 
eclipse中报错没找到.class file等?
解决:Project-> Build Automatically
 
 
 
 
 
Tomcat一个小时进行一次 Full GC,正常么?3
2014-06-08T04:33:07.721+0800: [GC [PSYoungGen: 253229K->64K(509248K)] 327975K->74809K(1557824K), 0.0392510 secs] [Times: user=0.08 sys=0.00, real=0.04 secs] 
2014-06-08T04:33:07.761+0800: [Full GC (System) [PSYoungGen: 64K->0K(509248K)] [ParOldGen: 74745K->74745K(1048576K)] 74809K->74745K(1557824K) [PSPermGen: 54430K->54429K(131072K)], 1.5088410 secs] [Times: user=2.82 sys=0.00, real=1.51 secs] 
2014-06-08T05:33:09.273+0800: [GC [PSYoungGen: 253178K->96K(512448K)] 327924K->74841K(1561024K), 0.0258150 secs] [Times: user=0.04 sys=0.00, real=0.02 secs] 
2014-06-08T05:33:09.299+0800: [Full GC (System) [PSYoungGen: 96K->0K(512448K)] [ParOldGen: 74745K->74746K(1048576K)] 74841K->74746K(1561024K) [PSPermGen: 54430K->54429K(131072K)], 1.3636130 secs] [Times: user=2.65 sys=0.00, real=1.37 secs] 
解决:Full GC (System)表明是程序中显示调用的gc。
一个小时一次,是tomcat的一个bug,不是你程序的问题,通过参数-XX:+DisableExplicitGC 就能去掉这一个小时一次的FGC。当然也有其他很多方法
 
 
org.apache.cxf.binding.soap.SoapFault: Unmarshalling Error: unexpected element (uri:"", local:"others"). Expected elements are <{}baseDomainName>,<{}serviceName>,<{}timeout>,<{}baseHostName>,<{}remoteDomainName>,<{}isFile>,<{}remoteHostName>,<{}systemName>,<{}data>,<{}fileContent> 
at org.apache.cxf.binding.soap.interceptor.Soap11FaultInInterceptor.unmarshalFault(Soap11FaultInInterceptor.java:75)
 
 
 
jaxb无法处理xml<->HashMap转换
jaxb在做xml与object互转时需要要如下事情
1、jdk1.6以上自带jaxb工具包
2、首先定义xsd文件
3、在windows的cmd里面执行命令,生成xsd文件中定义的元素对应的java类
xjc XXX.xsd -p 包名
例如:xjc mtqNetwork.xsd -p jaxb
4、此时就可以写测试程序了:请见jaxb/Test.java
 
 
 
cxf无法处理HashMap的入参。解决方法是给HashMap参数做个适配器,把JAXB不支持的对象类型(除了HashMap还有TimeStamp)转换方法重写下。本质上是把HashMap转成String传输。
1、新建类MapAdapter:(需要xstream-1.3.1.jar包)
package com.cup.wcg;
import java.util.HashMap;
import java.util.Map;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlType;
import javax.xml.bind.annotation.adapters.XmlAdapter;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;
/**
 * <数据模型转换>
 * <Map<String,Object> 与 String之间的转换>
 * 
 * @author  Owen
 * @version  [版本号, Apr 28, 2010]
 * @see  [相关类/方法]
 * @since  [产品/模块版本]
 */
@XmlType(name = "MapAdapter")
@XmlAccessorType(XmlAccessType.FIELD)
public class MapAdapter extends XmlAdapter<String, Map<String, Object>>
{
   /** *//**
    * Convert a bound type to a value type.
    * 转换JAXB不支持的对象类型为JAXB支持的对象类型
    *
    * @param map map
    *      The value to be convereted. Can be null.
    * @return String   
    * @throws Exception
    *      if there's an error during the conversion. The caller is responsible for
    *      reporting the error to the user through {@link javax.xml.bind.ValidationEventHandler}.
    */
   public String marshal(Map<String, Object> map)
       throws Exception
   {
   XStream xs = new XStream(new DomDriver());
  return xs.toXML(map);
 
   }
   /** *//**
    * Convert a value type to a bound type.
    * 转换JAXB支持的对象类型为JAXB不支持的的类型
    *
    * @param model
    *      The value to be converted. Can be null.
    * @return Map<String,Object>
    * @throws Exception
    *      if there's an error during the conversion. The caller is responsible for
    *      reporting the error to the user through {@link javax.xml.bind.ValidationEventHandler}.
    */
   @SuppressWarnings("unchecked")
   public Map<String, Object> unmarshal(String model)
       throws Exception
   {
   XStream xs = new XStream(new DomDriver());
   return (HashMap)xs.fromXML(model);
   }
}
 
2、创建webservice中带HashMap的入参:
@WebMethod
public String callByMap(@XmlJavaTypeAdapter(com.cup.wcg.MapAdapter.class) HashMap<String,String> map){
if(map==null){
log.info("map is null");
return "map is null";
}
else{
log.info("map key="+map.get("key"));
return "map key="+map.get("key");
}
}
 
如果HashMap是对象中的一个属性,采用如下方式:
  @XmlJavaTypeAdapter(MapAdapter.class)
    public HashMap<String,String> getMap()
    {
        return map;
    }
    
    public void setMap(@XmlJavaTypeAdapter(MapAdapter.class) HashMap<String,String> map)
    {
        this.map = map;
    }
 
 
3、调用时先转一把,从HashMap到String。
java.util.HashMap<String,String> map = new java.util.HashMap<String,String>();
map.put("key", "value");
XStream xs = new XStream(new DomDriver());
String s =  xs.toXML(map);
System.out.println(s);
res2 = client.invoke("callByMap",s);
System.out.println("Echo responsse: " + res2[0]);
 
xstream-1.3.1.jar包的maven位置:
<dependency>
  <groupId>com.thoughtworks.xstream</groupId>
  <artifactId>xstream</artifactId>
  <version>1.3.1</version>
</dependency>
 
 
报错
org.apache.cxf.binding.soap.SoapFault: Unmarshalling Error: java.lang.ClassCastException: org.apache.xerces.jaxp.DocumentBuilderFactoryImpl cannot be cast to javax.xml.parsers.DocumentBuilderFactory 
at org.apache.cxf.binding.soap.interceptor.Soap11FaultInInterceptor.unmarshalFault(Soap11FaultInInterceptor.java:75)
解决:去除war包中的xml-apis-1.0.b2.jar
 
 
Exception in thread "MtqResponseProcessThread_5" java.lang.NoClassDefFoundError:org/apache/commons/lang/StringUtils
at com.cup.mtq.cache.XmlHandle.getServiceByName()
解决:缺少commons-lang-2.1.jar
 
 
 
 
IE访问前置管理报错:http://146.240.25.38:11000/mi
Network Error (tcp_error)
A communication error occurred: ""  
The Web Server may be down, too busy, or experiencing other problems preventing it from responding to requests. You may wish to try again at a later time.  
For assistance, contact your network support team.  
解决:mi管理系统没有启动成功
 
 
android LogCat中不输出任何的信息 ?
简单的恢复方法:
1、clean logcat的内容
2、在Android 的 Devices视图,对自己的应用点一下debug。
一般这样以后Logcat 里就会突然出现很多消失了很久的log了。 
 
 
 
mysql 查看编码格式
mysql> SHOW VARIABLES LIKE 'character_set_%';
mysql> SHOW VARIABLES LIKE 'collation_%';
 
 修改编码格式
1. SET NAMES 'utf8';
它相当于下面的三句指令:
SET character_set_client = utf8;
SET character_set_results = utf8;
SET character_set_connection = utf8;
 
一般只有在访问之前执行这个代码就解决问题了,下面是创建数据库和数据表的,设置为我们自己的编码格式。
2. 创建数据库
mysql> create database name character set utf8;
 
3. 创建表
CREATE TABLE `type` (
`id` int(10) unsigned NOT NULL auto_increment,
`flag_deleted` enum('Y','N') character set utf8 NOT NULL default 'N',
`flag_type` int(5) NOT NULL default '0',
`type_name` varchar(50) character set utf8 NOT NULL default '',
PRIMARY KEY (`id`)
) DEFAULT CHARSET=utf8;
 
4. 修改数据库成utf8的.
mysql> alter database name character set utf8;
 
5. 修改表默认用utf8.
mysql> alter table type character set utf8;
 
6. 修改字段用utf8
mysql> alter table type modify type_name varchar(50) CHARACTER SET utf8;
 
 
 
 
JVM Crash 异常退出:SIGSEGV (0xb)问题定位分析?
# A fatal error has been detected by the Java Runtime Environment:
#
#  SIGSEGV (0xb) at pc=0x00007fc4b5d82120, pid=4844, tid=140482762118912
#
# JRE version: 6.0_37-b06
# Java VM: Java HotSpot(TM) 64-Bit Server VM (20.12-b01 mixed mode linux-amd64 compressed oops)
# Problematic frame:
# V  [libjvm.so+0x69e120]  MarkSweep::IsAliveClosure::do_object(oopDesc*)+0x20
#
# If you would like to submit a bug report, please visit:
#   http://java.sun.com/webapps/bugreport/crash.jsp
#
原因:系统上有两个jre环境。指定当前用户下JAVA_HOME即可。
# configuration of vms
export JAVA_HOME=${VMS_HOME}/jdk
export PATH=$JAVA_HOME/bin:$PATH
export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$CLASSPATH 
 
 
 
高性能:high performance
高速缓存、并行计算、异地镜像
 
高可用
负载均衡、数据灾备、异地容灾
 
高可扩展
开发框架、多层设计、业务分割
 
 
大型网站技术架构:核心原理与案例分析
pdf书下载?
 
 
CDN对动态网站内容加速效果:
优化访问线路:使用CDN动态加速,在A和B之间增加一个节点C,节点C长期存在于互联网上,不管是A访问C,还是B访问C,速度都不慢;因此,加入C节点以后,会让A访问B的速度会更快。
降低资源请求
不少CDN平台已经转型成为云安全加速平台,不仅支持内容分发,同时支持防攻击、防黑,有效减少安全隐患
 
 
 
到你的http://www.dnspod.cn用户后台更改你的
A记录:地址记录,用来指定域名的IPv4地址(如:8.8.8.8),如果需要将域名指向一个IP地址,就需要添加A记录。
CNAME: 如果需要将域名指向另一个域名,再由另一个域名提供ip地址,就需要添加CNAME记录。
TXT:在这里可以填写任何东西,长度限制255。绝大多数的TXT记录是用来做SPF记录(反垃圾邮件)。
NS:域名服务器记录,如果需要把子域名交给其他DNS服务商解析,就需要添加NS记录。
AAAA:用来指定主机名(或域名)对应的IPv6地址(例如:ff06:0:0:0:0:0:0:c3)记录。
MX:如果需要设置邮箱,让邮箱能收到邮件,就需要添加MX记录。
URL:从一个地址301重定向到另一个地址的时候,就需要添加URL记录(注:DNSPod目前只支持显性301重定向)。
SRV:记录了哪台计算机提供了哪个服务。格式为:服务的名字、点、协议的类型,例如:_xmpp-server._tcp。
 
注意:你解析时"线路类型"要选择"默认"如果选择其它线路,那么有可能有些宽带不能访问你的网站.
 
 
查询本机到服务器中间经过的路由器ip地址
tracert 域名/IP
 
 
查询DNS服务器的域名解析记录?
nslookup
现在的Dns可以根据访问ip的不同把域名解析到不同的ip上的
 
 
services-config.xml中
<channel-definition id="my-secure-amf" class="mx.messaging.channels.SecureAMFChannel">
            <endpoint url="https://{server.name}:{server.port}/{context.root}/messagebroker/amfsecure" class="flex.messaging.endpoints.SecureAMFEndpoint"/>
            <properties>
                <add-no-cache-headers>false</add-no-cache-headers>
            </properties>
</channel-definition>
1、endpoint中class修改成flex.messaging.endpoints.SecureAMFEndpoint或者flex.messaging.endpoints.AMFEndpoint均可,但是不能没有。
如果是SecureAMFEndpoint客户端与服务端的报文处于加密状态,如果是AMFEndpoint则没加密,但是两个都是二进制的格式。
如果是HTTPChannel/HTTPEndpoint(需要用http访问),则双方使用HTTP/XML格式报文,如果是SecureHTTPChannel则是加密。
按我的理解,使用SecureAMFChannel是使得客户端与服务端之间建立HTTPS链路,然后使用AMFEndpoint是传输二进制对象,使用SecureAMFEndpoint则是对此对象再次进行了加密。
2、endpoint中url中的/messagebroker配置在web.xml中的servlet-mapping处:<url-pattern>/messagebroker/*</url-pattern>。因此后面的/amfsecure是可以随便写的。
3、remoting-config.xml中<default-channels>中可以配置多个,flex页面连不上第一个channel的endpoint,会退而连第二个。
 
 
通过抓包发现,对于https的链路,握手并建立链路后,上面走的报文就不能以http协议来解析了,只能按照TCP来解包。
 
 
linux
vmstat 报告虚拟内存的统计信息。
 
Linux在计算进程情况时不将正在运行的 vmstat 自己计算进去。 
vmstat对系统的虚拟内存、进程、CPU活动进行监视,同时它也对磁盘和forks和vforks操作的个数进行汇总。
不足是vmstat不能对某个进程进行深入分析,它仅是一对系统的整体情况进行分析。
例如:[angel@home /angel]# vmstat
procs memory swap io system cpu
r b w swpd free buff cache si so bi bo in cs us sy id
0 0 0 7180 1852 56092 48400 0 0 6 5 24 8 0 0 18
其中:
Procs
r:等待运行的进程数
b:处在非中断睡眠状态的进程数
w:被交换出去的可运行的进程数。
Memory
swpd:虚拟内存使用情况,单位:KB
free:空闲的内存,单位KB
buff:被用来做为缓存的内存数,单位:KB
Swap
si:从磁盘交换到内存的交换页数量,单位:KB/秒
so:从内存交换到磁盘的交换页数量,单位:KB/秒
IO
bi:发送到块设备(也就是硬盘,因为硬盘是块设备)的块数,单位:块/秒
bo:从块设备接收到的块数,单位:块/秒 从块设备收到的块数,单位:块/秒
System
in:每秒的中断数,包括时钟中断
cs:每秒的环境(上下文)切换次数
CPU按CPU的总使用百分比来显示
us: CPU使用时间
sy: CPU系统使用时间
id:闲置时间
wa:cpu等待IO的时间(如果wa的值很高而且虚拟内存基本没有使用,则说明硬盘的速度是性能的一个瓶颈,此时应该更换一个速度更快的硬盘)
 
 
查看linux上某个进程的详细信息
ps aux
 
查看linux上某端口是哪个进程
netstat -nltp |grep 80
lsof -i:80 (还可以看到是哪个用户启的)
fuser -n tcp 80
 
 
 
Logging Error: Caught an IOException
java.io.IOException: 系统资源不足,无法完成请求的服务。
 
 
 
CET时区,GMT时区
⑴Greenwich Mean Time (GMT)格林尼治标准时间英国、爱尔兰、冰岛和葡萄牙属于该时区。这个时区与中国北京时间的时差是8个小时,也就是说比北京时间晚8个小时。
比如,如果是北京时间的下午3:00,也就是这个时区的上午7:00。
⑵Central European Time(CET)中欧时区奥地利、比利时、克罗地亚、捷克共和国、丹麦、法国、德国、荷兰、匈牙利、卢森堡、马耳他、意大利、摩纳哥、
挪威、波兰、斯洛文尼亚、斯洛伐克、西班牙、瑞士和瑞典,都属于这个时区。
该时区与北京时间的时差是7个小时。比如,北京时间的下午3:00,那么是这个时区的上午8:00。
⑶Eastern European Time(EET)东欧时区属于这个时区的欧洲国家有:保加利亚、赛浦路斯、爱脱尼亚、芬兰、希腊、拉脱维亚、立陶宛、罗马尼亚、土耳其和乌克兰。
这个时区与北京时间的时差是6个小时。比如,北京时间的下午3:00,也就是这个时区的上午9:00。大部分欧洲国家实行夏令时(Summer Time or DST)。
三月份的最后一个周未是夏令时的开始,这一天他们把时钟往后调一个小时,比如2:00am,他们调整为3:00am。十月份的最后一个周未是夏令时的结束,
这一天他们把时钟往前调一个小时,比如2:00am,他们调整为1:00am。
 
 
 
通过kill -3 进程号能生成javacore....txt日志,但是没法生成.phd文件。
而.phd文件是JVM内存映射文件,获取它才能分析此时JVM内存的情况,进而分析出服务器宕机的原因。
 
对于IBM JDK需要做以下设置:
1.设置JVM参数:
   -XX:+HeapDumpOnOutOfMemoryError -XX:+HeapDumpOnCtrlBreak
2.设置操作系统环境变量:
   export IBM_HEAP_DUMP=true
   export IBM_HEAPDUMP=true
   export IBM_HEAPDUMP_OUTOFMEMORY=true
   export IBM_JAVADUMP_OUTOFMEMORY=true
   export IBM_JAVACORE_OUTOFMEMORY=true
重启服务器。如果这样仍然解决不了问题,则需要在服务器启动脚本添加一行:
    #!/bin/ksh
    #...
    set -m
HP JDK生成Heapdump文件需要在在环境变量上,加上export _JAVA_HEAPDUMP=1
 
 
Thread Dump分析
通过分析Thread Dump,可以了解JVM到底有哪些线程正在工作,有助于找出死锁,性能低下的原因。 
Sun HotSpot有两种方式: 
jstack pid > /tmp/my_thread_dump.log (生成的是文本文件,直接看即可。)
kill -3 pid, dump文本会生成在标准输出中,在upjas1.x中就是$UPJAS_HOME/bin/nohup.out中,需要手工截取 
IBM J9: 
kill -3 pid, thread dump文本会生成在类似 javacore.20131223.135411.7130.0002.txt 的文件中
 
Heap Dump分析
通过分析Heap Dump,可以了解JVM中到底哪些对象占用了大量内存,有助于定位内存泄漏等问题。 
Sun HotSpot: 
jmap -dump:format=b,file=/tmp/mydump.hprof pid
说明
其中 /tmp/mydump.hprof 是用户自己指定的文件名。 
IBM J9 
kill -3 pid
heap dump会生成在类似 heapdump.20131223.135411.7130.0001.phd 的文件中 
说明
kill -3 pid之所以能在upjas环境下生成heapdump,是因为upjas_all_setEnv.sh中设置了ibm J9能识别的参数: -Xdump:heap 
 
 
 
 
org.apache.cxf.endpoint.Client是线程安全的,测试程序在:D:\isvrupjasworkspace\Testupjascxf\src\Test里面
 
 
 
WeakHashMap与HashMap的用法基本相同,区别在于:后者的key保留对象的强引用,即只要HashMap对象不被销毁,其对象所有key所引用的对象不会被垃圾回收,
HashMap也不会自动删除这些key所对应的键值对对象。但WeakHashMap的key所引用的对象没有被其他强引用变量所引用,
则这些key所引用的对象可能被回收。WeakHashMap中的每个key对象保存了实际对象的弱引用,当回收了该key所对应的实际对象后,
WeakHashMap会自动删除该key所对应的键值对。
 
 
System.gc(); 
//告诉垃圾收集器打算进行垃圾收集,而垃圾收集器进不进行收集是不确定的 
 
System.runFinalization(); 
//强制调用已经失去引用的对象的finalize方法 
 
 
 
 
用Jmeter发送TCP二进制的消息
1、tcp:右键添加-》Sampler -》TCP取样器
2、要发送二进制的话可以在TCPClient classname的这个参数中填入
org.apache.jmeter.protocol.tcp.sampler.BinaryTCPClientImpl
这样在text to send的区域直接写入HEX形式的二进制
 
 
 
"Java请求"是指JMeter对Java Class进行性能测试
 
 
jmeter csv data set config 使用文件中配置的参数
 
 
Jmeter日志输出和日志级别设置
Jmeter日志默认存放在%JMeter_HOME%\bin目录,文件名通常是JMeter.log。日志记录与JMeter本身运行有关的日志信息。
 
Jmeter使用Log4j日志组件输出日志,%JMETER_HOME%\bin\jmeter.properties中的log_level.jmeter用于控制Jmeter日志记录级别。log_level.jmeter可以设置以下日志级别:FATAL_ERROR, ERROR, WARN, INFO,DEBUG,其中FATAL_ERROR打印日志最少,DEBUG级别日志最详细
 
 
DNS协议运行在UDP协议之上,使用端口号53
 
 
确定同类业务:成本、客户矩阵
 
 
关闭 Apache 的web日志?
httpd.conf文件里面有如下配置,注掉就不记日志了
ErrorLog "logs/error_log"
CustomLog "logs/access_log" common
 
 
 
传统上,Linux 的先辈 Unix 还有一个环境变量:LD_LIBRARY_PATH 来处理非标准路经的共享库
 
 
apache反向代理时部分图片显示不出?
解决:图片的链接一般是img src="/mjc/resources/images/filter.gif"这种,如果apache代理配置成这样
ProxyPass         /mi http://146.240.25.38:11000/mjc
ProxyPassReverse  /mi http://146.240.25.38:11000/mjc
当使用http://146.240.25.38:4488/mi访问网站时,图片的链接变成了http://146.240.25.38:4488/mjc/resources/images/filter.gif就无法成功代理。
只能改成如下配置:
ProxyPass         /mjc http://146.240.25.38:11000/mjc
ProxyPassReverse  /mjc http://146.240.25.38:11000/mjc
 
 
 
wget命令测试http服务
 
 
浏览器关了,但是apache上https的端口还有很多状态在CLOSE_WAIT、TIME_WAIT?
 
 
 
问题:使用apache做类似于F5的角色的方法?(访问通讯协议:浏览器--https-->APACHE--http-->管理mgm server)
1、apache上安装、配置ssl
略,参考:学习\apache2.2和php5的安装使用\linux上安装apache2.2\(可行)Linux上Apache服务器的搭建与配置手册(包含openssl安装及ssl代理+ssl证书).doc
2、apache/conf/extra> vi httpd-ssl.conf文件中</VirtualHost>之前配置如下:
SSLProxyEngine on
ProxyRequests off
ProxyPreserveHost on
ProxyPass         /maps http://172.17.248.186:11000/maps
ProxyPassReverse  /maps http://172.17.248.186:11000/maps
3、管理要做相应修改,使得登陆时sso会跳到正确地址。
172.17.248.186的maps的appCfg/securityClient.properties中配置:
146.240.25.38=https://172.17.248.33:4433
(其中146.240.25.38是代理apache的ip,172.17.248.186上安装了管理应用,其flex页面必须使用HTTPS才能打开)
4、浏览器访问:
https://146.240.25.38:4489/maps(4489是代理apache上https端口)
 
 
问题:使用apache访问外网https方法?目前只会单向的,(访问通讯协议:应用--http-->APACHE--https-->外部HTTPS SERVER)
1、apache上安装、配置ssl
同上,例外是此处可不用打开下面这个配置,也无需配置此文件:
#Include conf/extra/httpd-ssl.conf
2、apache/conf > vi httpd.conf文件配置:
SSLProxyEngine on
ProxyRequests off
ProxyPreserveHost on
ProxyPass         /mjc https://172.17.248.185:11009/mjc
ProxyPassReverse  /mjc https://172.17.248.185:11009/mjc
3、浏览器使用http://146.240.25.38:4488/mjc即可访问
(其中146.240.25.38是代理apache的ip,4488是其http端口,172.17.248.185表示开启了HTTPS端口的外部应用)
 
 
双向https
请求http的形式发送到apache上,通过apache服务器继续以https形式去往外部,调用其他公司为银联提供的服务,双向加密,由于本情形配置较复杂,请联系主机组协助。
ProxyRequests Off
SSLProxyEngine On
SSLProxyMachineCertificateFile /home/apache/chmoNFC/htdocs/certificate/120.204.69.183.pem
SSLProxyCACertificateFile /home/apache/chmoNFC/htdocs/certificate/120.204.69.183.crt
ProxyPass /tsm balancer://TSMProxy/tsm
ProxyPassReverse /tsm balancer://TSMProxy/tsm
<Proxy balancer://TSMProxy>
    BalancerMember  https://112.106.165.36:9443
    SetEnv proxy-nokeepalive 1
</Proxy>
在配置中120.204.69.183.pem和120.204.69.183.crt两个证书文件会有业务室或应用科室提供。
 
 
 
通常来说,一个CLOSE_WAIT会维持至少2个小时的时间?(系统默认超时时间的是7200秒,也就是2小时)
一、 修改方法:(暂时生效,重新启动服务器后,会还原成默认值) 
sysctl -w net.ipv4.tcp_keepalive_time=600   
sysctl -w net.ipv4.tcp_keepalive_probes=2 
sysctl -w net.ipv4.tcp_keepalive_intvl=2 
注意:Linux的内核参数调整的是否合理要注意观察,看业务高峰时候效果如何。 
二、 若做如上修改后,可起作用;则做如下修改以便永久生效。 
vi /etc/sysctl.conf 
 
若配置文件中不存在如下信息,则添加: 
net.ipv4.tcp_keepalive_time = 1800 
net.ipv4.tcp_keepalive_probes = 3 
net.ipv4.tcp_keepalive_intvl = 15 
 
编辑完 /etc/sysctl.conf,要重启network 才会生效 
/etc/rc.d/init.d/network restart 
然后,执行sysctl命令使修改生效,基本上就算完成了。 
------------------------------------------------------------ 
修改原因: 
当客户端因为某种原因先于服务端发出了FIN信号,就会导致服务端被动关闭,若服务端不主动关闭socket发FIN给Client,此时服务端Socket会处于CLOSE_WAIT状态(而不是LAST_ACK状态)。通常来说,一个CLOSE_WAIT会维持至少2个小时的时间(系统默认超时时间的是7200秒,也就是2小时)。如果服务端程序因某个原因导致系统造成一堆CLOSE_WAIT消耗资源,那么通常是等不到释放那一刻,系统就已崩溃。因此,解决这个问题的方法还可以通过修改TCP/IP的参数来缩短这个时间,于是修改tcp_keepalive_*系列参数: 
tcp_keepalive_time: 
/proc/sys/net/ipv4/tcp_keepalive_time 
INTEGER,默认值是7200(2小时) 
当keepalive打开的情况下,TCP发送keepalive消息的频率。建议修改值为1800秒。 
 
tcp_keepalive_probes:INTEGER 
/proc/sys/net/ipv4/tcp_keepalive_probes 
INTEGER,默认值是9 
TCP发送keepalive探测以确定该连接已经断开的次数。(注意:保持连接仅在SO_KEEPALIVE套接字选项被打开是才发送.次数默认不需要修改,当然根据情形也可以适当地缩短此值.设置为5比较合适) 
 
tcp_keepalive_intvl:INTEGER 
/proc/sys/net/ipv4/tcp_keepalive_intvl 
INTEGER,默认值为75 
当探测没有确认时,重新发送探测的频度。探测消息发送的频率(在认定连接失效之前,发送多少个TCP的keepalive探测包)。乘以tcp_keepalive_probes就得到对于从开始探测以来没有响应的连接杀除的时间。默认值为75秒,也就是没有活动的连接将在大约11分钟以后将被丢弃。(对于普通应用来说,这个值有一些偏大,可以根据需要改小.特别是web类服务器需要改小该值,15是个比较合适的值) 
 
【检测办法】 
1. 系统不再出现“Too many open files”报错现象。 
 
2. 处于TIME_WAIT状态的sockets不会激长。 
 
在 Linux 上可用以下语句看了一下服务器的TCP状态(连接状态数量统计): 
 
netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}' 
 
返回结果范例如下:
ESTABLISHED 1423 
FIN_WAIT1 1 
FIN_WAIT2 262 
SYN_SENT 1 
TIME_WAIT 962
-----------------------------------------------------------------------------------------------
 
apache/conf> vi extra/httpd-default.conf
KeepAlive On
keep-alvie默认是开启的
 
 
服务器负载均衡有三大基本Feature:负载均衡算法,健康检查和会话保持
 
 
 
java.lang.reflect.UndeclaredThrowableException
        at $Proxy298.parseSchema(Unknown Source)
        at org.apache.cxf.endpoint.dynamic.DynamicClientFactory.addSchemas(DynamicClientFactory.java:423)
        at org.apache.cxf.endpoint.dynamic.DynamicClientFactory.createClient(DynamicClientFactory.java:271)
        at org.apache.cxf.endpoint.dynamic.DynamicClientFactory.createClient(DynamicClientFactory.java:198)
        at org.apache.cxf.endpoint.dynamic.DynamicClientFactory.createClient(DynamicClientFactory.java:191)
        at org.apache.cxf.endpoint.dynamic.DynamicClientFactory.createClient(DynamicClientFactory.java:146)
        at com.cup.maps.online.OnlineTrans.getResponseByType(OnlineTrans.java:630)
        at com.cup.maps.online.OnlineTrans.access$000(OnlineTrans.java:57)
        at com.cup.maps.online.OnlineTrans$ServiceDealThread.run(OnlineTrans.java:834)
Caused by: java.lang.reflect.InvocationTargetException
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:60)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:37)
        at java.lang.reflect.Method.invoke(Method.java:611)
        at org.apache.cxf.common.util.ReflectionInvokationHandler.invoke(ReflectionInvokationHandler.java:52)
        ... 9 more
Caused by: java.lang.NullPointerException
        at org.apache.xerces.dom.ParentNode.nodeListItem(Unknown Source)
        at org.apache.xerces.dom.ParentNode.item(Unknown Source)
        at com.sun.xml.internal.bind.unmarshaller.DOMScanner.visit(DOMScanner.java:246)
        at com.sun.xml.internal.bind.unmarshaller.DOMScanner.visit(DOMScanner.java:277)
        at com.sun.xml.internal.bind.unmarshaller.DOMScanner.visit(DOMScanner.java:246)
        at com.sun.xml.internal.bind.unmarshaller.DOMScanner.visit(DOMScanner.java:277)
        at com.sun.xml.internal.bind.unmarshaller.DOMScanner.visit(DOMScanner.java:246)
        at com.sun.xml.internal.bind.unmarshaller.DOMScanner.scan(DOMScanner.java:123)
        at com.sun.tools.internal.xjc.api.impl.s2j.SchemaCompilerImpl.parseSchema(SchemaCompilerImpl.java:136)
        ... 14 more
解决:通讯配置文件同步,会有多个线程同时使用cxf生成ws客户端,此处代码非线程安全导致报错。
 
 
 
TestHttpHeartBeat测试HttpClient的executeMethod执行3000次,未见内存泄露
 
 
 
Exception in thread "pool-1-thread-1" java.lang.IllegalStateException: Unable to create JAXBContext for generated packages: "com.cup.mtq" doesnt contain ObjectFactory.class or jaxb.index
at org.apache.cxf.endpoint.dynamic.DynamicClientFactory.createClient(DynamicClientFactory.java:345)
at org.apache.cxf.endpoint.dynamic.DynamicClientFactory.createClient(DynamicClientFactory.java:198)
at org.apache.cxf.endpoint.dynamic.DynamicClientFactory.createClient(DynamicClientFactory.java:191)
at org.apache.cxf.endpoint.dynamic.DynamicClientFactory.createClient(DynamicClientFactory.java:146)
at TestcxfCreateWsClient.run(TestcxfCreateWsClient.java:52)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:895)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:918)
at java.lang.Thread.run(Thread.java:662)
Caused by: javax.xml.bind.JAXBException: "com.cup.mtq" doesnt contain ObjectFactory.class or jaxb.index
at com.sun.xml.bind.v2.ContextFactory.createContext(ContextFactory.java:197)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:128)
at javax.xml.bind.ContextFinder.find(ContextFinder.java:277)
at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:372)
at org.apache.cxf.endpoint.dynamic.DynamicClientFactory.createClient(DynamicClientFactory.java:342)
... 7 more
 javac: 找不到文件: C:\DOCUME~1\沈雷\LOCALS~2\Temp\cxf-tmp-833848\cxf-compiler3952818340990681712.tmp (系统找不到指定的文件。)
解决:使用ExecutePool会导致此问题,使用Thread线程调用cxf.createClient不会有问题。
另外,在.profile中添加PATH=$PATH:/usr/java6_64/bin:.生效后重启也能解决问题
 
 
 
前置管理启动时报错:
The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.)
at org.jboss.resource.adapter.jdbc.local.LocalManagedConnectionFactory.getLocalManagedConnection(LocalManagedConnectionFactory.java:225)
at org.jboss.resource.adapter.jdbc.local.LocalManagedConnectionFactory.createManagedConnection(LocalManagedConnectionFactory.java:195)
at org.jboss.resource.connectionmanager.InternalManagedConnectionPool.createConnectionEventListener(InternalManagedConnectionPool.java:639)
at org.jboss.resource.connectionmanager.InternalManagedConnectionPool.getConnection(InternalManagedConnectionPool.java:273)
at org.jboss.resource.connectionmanager.JBossManagedConnectionPool$BasePool.getConnection(JBossManagedConnectionPool.java:689)
at org.jboss.resource.connectionmanager.BaseConnectionManager2.getManagedConnection(BaseConnectionManager2.java:404)
... 95 more
Caused by: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure
The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
at com.mysql.jdbc.Util.handleNewInstance(Util.java:408)
at com.mysql.jdbc.SQLError.createCommunicationsException(SQLError.java:1137)
at com.mysql.jdbc.MysqlIO.<init>(MysqlIO.java:356)
at com.mysql.jdbc.ConnectionImpl.coreConnect(ConnectionImpl.java:2504)
at com.mysql.jdbc.ConnectionImpl.connectOneTryOnly(ConnectionImpl.java:2541)
at com.mysql.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:2323)
at com.mysql.jdbc.ConnectionImpl.<init>(ConnectionImpl.java:832)
at com.mysql.jdbc.JDBC4Connection.<init>(JDBC4Connection.java:46)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
at com.mysql.jdbc.Util.handleNewInstance(Util.java:408)
at com.mysql.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:417)
at com.mysql.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:344)
at org.jboss.resource.adapter.jdbc.local.LocalManagedConnectionFactory.getLocalManagedConnection(LocalManagedConnectionFactory.java:207)
... 100 more
解决:排除程序和jar包冲突问题后,发现管理应用的ip和访问用户mi_mgmap没有访问mimgmdb数据库的权限,如此增加即可:
grant all privileges on mimgmdb.* to mi_mgmap@'146.240.10.64' identified by 'mi_mgmap';
grant all privileges on mionldb.* to mi_mgmap@'146.240.10.64' identified by 'mi_mgmap';
 
 
 
服务器启动时,ServletContextListener的contextInitialized()方法被调用;服务器将要关闭时,ServletContextListener 的 contextDestroyed()方法被调用;
spring在web应用启动的listener类:org.springframework.web.context.ContextLoaderListener就用到了ServletContextListener。
 
 
 
系统室在146.240.25.38的apache上配置了ProxyRemote,使其通过访问代理服务访问外网,做法是:
在apache/conf/httpd.conf文件代理配置前添加:
ProxyRemote * http://172.18.64.89:3128
 
 
ProxyPreserveHost On 意思是传送原始请求的Host信息给被代理的机器。
 
 
javax.xml.bind.UnmarshalException
 - with linked exception:
[org.xml.sax.SAXParseException: The element type "domain" must be terminated by the matching end-tag "</domain>".]
        at javax.xml.bind.helpers.AbstractUnmarshallerImpl.createUnmarshalException(AbstractUnmarshallerImpl.java:315)
        at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.createUnmarshalException(UnmarshallerImpl.java:514)
        at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:215)
        at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(UnmarshallerImpl.java:184)
        at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:137)
        at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:184)
解决:mtqService和mtqNetwork均有校验
 
 
 
linux
# uname -a # 查看内核/操作系统/CPU信息 
# head -n 1 /etc/issue # 查看操作系统版本 
# cat /proc/cpuinfo # 查看CPU信息 
# hostname # 查看计算机名 
# lspci -tv # 列出所有PCI设备 
# lsusb -tv # 列出所有USB设备 
# lsmod # 列出加载的内核模块 
# env # 查看环境变量资源 
# free -m # 查看内存使用量和交换区使用量 
# df -h # 查看各分区使用情况 
# du -sh <目录名> # 查看指定目录的大小 
# grep MemTotal /proc/meminfo # 查看内存总量 
# grep MemFree /proc/meminfo # 查看空闲内存量 
# uptime # 查看系统运行时间、用户数、负载 
# cat /proc/loadavg # 查看系统负载磁盘和分区 
# mount | column -t # 查看挂接的分区状态 
# fdisk -l # 查看所有分区 
# swapon -s # 查看所有交换分区 
# hdparm -i /dev/hda # 查看磁盘参数(仅适用于IDE设备) 
# dmesg | grep IDE # 查看启动时IDE设备检测状况网络 
# ifconfig # 查看所有网络接口的属性 
# iptables -L # 查看防火墙设置 
# route -n # 查看路由表 
# netstat -lntp # 查看所有监听端口 
# netstat -antp # 查看所有已经建立的连接 
# netstat -s # 查看网络统计信息进程 
# ps -ef # 查看所有进程 
# top # 实时显示进程状态用户 
# w # 查看活动用户 
# id <用户名> # 查看指定用户信息 
# last # 查看用户登录日志 
# cut -d: -f1 /etc/passwd # 查看系统所有用户 
# cut -d: -f1 /etc/group # 查看系统所有组 
# crontab -l # 查看当前用户的计划任务服务 
# chkconfig –list # 列出所有系统服务 
# chkconfig –list | grep on # 列出所有启动的系统服务程序 
# rpm -qa # 查看所有安装的软件包
 
查看主机名
vi /proc/sys/kernel/hostname
hostname
 
hostname –a: 获取主机别名。
hostname –d: 获取DNS域名。
hostname –f: 获取FQDN名称。
hostname –i: 获取主机的IP地址。
hostname –s: 获取域名的netbios名称。
 
hostname和ip的对应文件:
vi /etc/hosts
 
 
HttpClient对于要求接受后继服务的请求(301、302、303、307),比如POST和PUT,不支持自动转发,因此需要自己对页面转向做处理。
client.executeMethod(post);
        System.out.println(post.getStatusLine().toString());
        post.releaseConnection();
        //检查是否重定向
        int statuscode = post.getStatusCode();
        if ((statuscode == HttpStatus.SC_MOVED_TEMPORARILY) ||
            (statuscode == HttpStatus.SC_MOVED_PERMANENTLY) ||
            (statuscode == HttpStatus.SC_SEE_OTHER) ||
(statuscode == HttpStatus.SC_TEMPORARY_REDIRECT)) {
//读取新的URL地址
            Header header = post.getResponseHeader("location");
            if (header != null) {
                String newuri = header.getValue();
                if ((newuri == null) || (newuri.equals("")))
                    newuri = "/";
                GetMethod redirect = new GetMethod(newuri);
                client.executeMethod(redirect);
                System.out.println("Redirect:"+ redirect.getStatusLine().toString());
                redirect.releaseConnection();
            } else
                System.out.println("Invalid redirect");
        }
 
 
HttpClient支持自动重传,如果要自定义exception重传需要实现HttpMethodRetryHandler类,然后设置:
httpget.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, myretryhandler);
 
 
<%@ page isELIgnored="true" %> 表示是否禁用EL语言,TRUE表示禁止.FALSE表示不禁止.JSP2.0中默认的启用EL语言。
<%=request.getParameter(“username”)%> 等价于 ${param.username}
<%=user.getAddr( ) %> 等价于 ${user.addr}
<%=request.getAttribute(“userlist”) %> 等价于$ { requestScope.userlist } 注意不是request.getParameter
EL表达式:http://baike.baidu.com/view/1488964.htm?fr=aladdin
 
 
 
DWR的逆向Ajax主要包括两种模式:主动模式和被动模式。其中主动模式包括polling和comet两种,被动模式只有piggyback这一种。默认是下面的第一种piggyback
1、piggyback方式
 这是默认的方式。
如果后台有什么内容需要推送到前台,是要等到那个页面进行下一次ajax请求的时候,将需要推送的内容附加在该次请求之后,传回到页面。
只有等到下次请求页面主动发起了,中间的变化内容才传递回页面。
2、comet方式
当服务端建立和浏览器的连接,将页面内容发送到浏览器之后,对应的连接并不关闭,只是暂时挂起。如果后面有什么新的内容需要推送到客户端的时候
直接通过前面挂起的连接再次传送数据。服务器所能提供的连接数目是一定的,在大量的挂起的连接没有关闭的情况下,可能造成新的连接请求不能接入,
从而影响到服务质量。
3、polling方式
由浏览器定时向服务端发送ajax请求,询问后台是否有什么内容需要推送,有的话就会由服务端返回推送内容。这种方式和我们直接在页面通过定时器发送ajax请求,
然后查询后台是否有变化内容的实现是类似的。只不过用了dwr之后这部分工作由框架帮我们完成了。
 
<!-- 使用polling和comet的方式 -->
 <init-param>
   <param-name>pollAndCometEnabled</param-name>
   <param-value>true</param-value>
 </init-param>
<!-- comet方式 --> 
 <init-param>  
<param-name>activeReverseAjaxEnabled</param-name>  
<param-value>true</param-value> 
</init-param> 
<!-- polling方式:在comet方式的基础之上,再配置以下参数 -->
  <init-param>  
  <param-name>org.directwebremoting.extend.ServerLoadMonitor</param-name>  
  <param-value>org.directwebremoting.impl.PollingServerLoadMonitor</param-value> 
  </init-param>
<!-- 毫秒数。页面默认的请求间隔时间是5秒 --> 
<init-param> 
 <param-name>disconnectedTime</param-name> 
 <param-value>60000</param-value>  
</init-param>
 
 
veloctiy中将某javabean输出到前台vhtml时,需要该javabean是public的,并且该属性的get函数也是public的才行。例如:
public class Model {
 String abc = "a111111";
public String getAbc() {
return abc;
}
}
ctx.put("model2", new Model());
 
 
velocity页面取值的区别?一个int型,一个string
alert("@@@@@@@@@@@="+$tblcd);       267777
alert("@@@@@@@@@@@="+'$tblcd');01013001
 
 
在spring 中,常用的ViewResolver 有如下几种:
InternalResourceViewResolver 将逻辑视图名字解析为一个路径 
BeanNameViewResolver 将逻辑视图名字解析为bean的Name属性,从而根据name属性,找定义View的bean 
ResourceBundleResolver 和BeanNameViewResolver一样,只不过定义的view-bean都在一个properties文件中,用这个类进行加载这个properties文件 
XmlViewResolver 和ResourceBundleResolver一样,只不过定义的view-bean在一个xml文件中,用这个类来加载xml文件 
 
DispatcherServlet会加载所有的viewResolver到一个list中,并按照优先级进行解析。
注意:①order中的值越小,优先级越高。
   ②而id为viewResolver的viewResolver的优先级是最低的。
 
 
问:velocityViewResolver不起作用?
解决:如果为DispatcherServlet指定多个ViewResolver的话,不要给予InternalResourceViewResolver以及其他UrlBasedViewResolver子类过高的优先级,
因为这些ViewResolver即使找不到相应的视图,也不会返回null以给我们轮询下一个ViewResolver的机会。要给org.springframework.web.servlet.view.velocity.VelocityViewResolver
最高级别的等级。
 
 
 
@ModelAttribute获取POST请求的FORM表单数据
JSP表单如下
<form method="post" action="hao.do">
    a: <input id="a" type="text"   name="a"/>
    b: <input id="b" type="text"   name="b"/>
    <input type="submit" value="Submit" />
 </form>
Java  Pojo如下
    public class Pojo{
        private String a;
        private int b;
    }
Java Controller如下
@RequestMapping(method = RequestMethod.POST) 
public String processSubmit(@ModelAttribute("pojo") Pojo pojo) { 
    return "helloWorld"; 
}
 
 
switch语句的判断条件可以接受int,byte,char,short,enum。不能接受其他类型.
 
构造器Constructor不能被继承,因此不能重写Overriding,但可以被重载Overloading
overload和override的区别 
override(重写) 
1、方法名、参数、返回值相同。
2、子类方法不能缩小父类方法的访问权限。
3、子类方法不能抛出比父类方法更多的异常(但子类方法可以不抛出异常)。
4、存在于父类和子类之间。
5、方法被定义为final不能被重写。
overload(重载)
1、参数类型、个数、顺序至少有一个不相同。  
2、不能重载只有返回值不同的方法名。
3、存在于父类和子类、同类中。
 
 
abstract的method是否可同时是static,是否可同时是native,是否可同时是synchronized?
都可以的
 
Error与Exception有什么区别?
Exception表示应用程序级错误,Error表示系统错误或低层资源的错误 
 
List, Set, Map是否继承自Collection接口?
Map不继承,另外两个继承
 
short s1 = 1; s1 += 1;有什么错?
不会报错,+=这个运算具有隐式转换的功能
 
 
Math类中提供了三个与取整有关的方法:ceil、floor、round。ceil的英文意义是天花板,该方法就表示向上取整,floor的英文意义是地板,该方法就表示向下取整
round方法,它表示“四舍五入”,算法为Math.floor(x+0.5),即将原来的数字加上0.5后再向下取整
 
HashMap是Hashtable的轻量级实现(非线程安全的实现),他们都完成了Map接口,主要区别在于HashMap允许空(null)键值(key),
由于非线程安全,效率上可能高于Hashtable。
 
 
Anonymous Inner Class (匿名内部类)匿名的内部类是没有名字的内部类。
匿名的内部类不能extends(继承)其它类,但一个内部类可以作为一个接口,由另一个内部类实现。
 
String s = new String("xyz");创建了几个String Object?
一个引用s,一个对象new String在堆中,一个存于常量池,即永久代中。
 
银行卡包括借记卡,准贷记卡和贷记卡,其中,准贷记卡跟贷记卡并称为信用卡。 
1、贷记卡是指发卡银行给予持卡人一定的信用额度,持卡人可在信用额度内先消费,后还款的银行卡,一般可以透支取现。
如果在贷记卡里面你的账户有钱的话,这部分钱不会获得银行利息,即贷记卡存款不计息。
2、准贷记卡是指持卡人须先按发卡银行要求交存一定金额的备用金(其实这个备用金你马上就可以全部取走的,跟没存没多少差别),
当备用金账户余额不足支付时,可在发卡银行规定的信用额度内透支的银行卡,这个卡一般不可以透支取现,不过可以透支消费,
但透支消费后往往没有免息期。另外,如果在准贷记卡里面你的账户有钱的话,是可以从银行获得活期利息的。 
3、借记卡是指先存款后消费(或取现),没有透支功能的银行卡。其按功能不同,又可分为转账卡(含储蓄卡)、专用卡及储值卡。
如果在借记卡里面你的账户有钱的话,是可以从银行获得活期利息的。
 
 
apache负载均衡
http://146.240.25.39:4488/mi
 
 
hibernate java project 最小依赖包
hibernate-release-4.0.0.Beta4.zip包里面lib/required下的jar包全部添加到工程的library里面,
另外还需添加slf4j的实现包slf4j-log4j12-1.5.8.jar和log4j的实现包log4j-1.2.16.jar,还有别忘了把JDBC的驱动jar包也加入到library
 
 
UPJAS1.x包含的组件版本
Component Version 
JBoss Application Server 5.1.0.GA 
JBoss Microcontainer 2.0.10.GA 
JBoss Web (based on Tomcat 6.0) 2.1.12.GA-patch-01 
JBoss EJB3 1.3.8 
Hibernate Core 3.3.2.GA_CP04 
Hibernate Entity Manager 3.4.0.GA_CP04 
Hibernate Annotations 3.4.0.GA_CP04 
Hibernate Validator 3.1.0.GA 
JBoss WS-CXF 3.1.2.SP9 
JPA 1.0.0 
HornetQ HornetQ_2_2_20_EAP_GA 
 
 
tomcat数据源配置使用:
1、apache-tomcat-6.0.37\conf\context.xml增加
<Resource name="jdbc/mysqldb"
       auth="Container"
       type="javax.sql.DataSource"
       driverClassName="com.mysql.jdbc.Driver"
       url="jdbc:mysql://146.240.54.1:60016/mimgmdb?useUnicode=true&amp;characterEncoding=utf-8&amp;useOldAliasMetadataBehavior=true&amp;zeroDateTimeBehavior=convertToNull"
       username="mi_mgmap"
       password="mi_mgmap"
       maxActive="100"
       maxIdle="30"
       maxWait="10000"
    logAbandoned="true" />
2、index.jsp中调用:
<%
Context initContext = new InitialContext();
DataSource ds = (DataSource)initContext.lookup("java:comp/env/jdbc/mysqldb");
Connection conn = ds.getConnection();
Statement stat = conn.createStatement();
String sql = "select * from tbl_user";
ResultSet rs = stat.executeQuery(sql);
if(rs.next())
out.print(rs.getString(1));
conn.close();
initContext.close();
%>
 
换成db2的配置:(竟然无需db2驱动。。。)
<Resource name="jdbcMapsMng"
       auth="Container"
       type="javax.sql.DataSource"
       driverClassName="com.ibm.db2.jcc.DB2Driver"
       url="jdbc:db2://172.17.252.83:60004/mamgmdb:currentSchema=MA_MGMDB;"
       username="ma_mgmdb"
       password="ma_mgmdb"
       maxActive="100"
       maxIdle="30"
       maxWait="10000"
 logAbandoned="true" />
 
 
 
jboss数据源配置:
1、新增server/default/cup-deploy/jdbc/mysql-mimgm-ds.xml文件,内容如下:
<datasources>
  <local-tx-datasource>
        <jndi-name>miMng</jndi-name>
        <connection-url>jdbc:mysql://172.17.254.249:3306/mimgmdb?useUnicode=true&amp;characterEncoding=utf-8&amp;useOldAliasMetadataBehavior=true&amp;zeroDateTimeBehavior=convertToNull</connection-url>
        <driver-class>com.mysql.jdbc.Driver</driver-class>
        <user-name>mi_mgmdb</user-name>
        <password>mi_mgmdb</password>
        <exception-sorter-class-name>org.jboss.resource.adapter.jdbc.vendor.MySQLExceptionSorter</exception-sorter-class-name>
    <!-- should only be used on drivers after 3.22.1 with "ping" support
    <valid-connection-checker-class-name>org.jboss.resource.adapter.jdbc.vendor.MySQLValidConnectionChecker</valid-connection-checker-class-name>
    -->
    <!-- sql to call when connection is created
    <new-connection-sql>some arbitrary sql</new-connection-sql>
      -->
    <!-- sql to call on an existing pooled connection when it is obtained from pool - MySQLValidConnectionChecker is preferred for newer drivers
    <check-valid-connection-sql>some arbitrary sql</check-valid-connection-sql>
      -->
    <!-- corresponding type-mapping in the standardjbosscmp-jdbc.xml (optional) -->
    <use-java-context>false</use-java-context>
    <min-pool-size>5</min-pool-size>
    <max-pool-size>100</max-pool-size>
    <blocking-timeout-millis>30000</blocking-timeout-millis>
    <idle-timeout-minutes>10</idle-timeout-minutes>
    <set-tx-query-timeout/>
    <query-timeout>60</query-timeout> <!-- maximum of 1 minutes for queries -->
    <metadata>
       <type-mapping>mySQL</type-mapping>
    </metadata>
  </local-tx-datasource>
</datasources>
2、修改server/default/conf/login-config.xml文件,如果已在第1步中配置了password,这个文件可以不用改,但是密码是明文的,
如果在这个文件里面加了以后,启动后密码是密文(其实可破解)。
<application-policy name="EncryptDBPassword_mimgmdb">
               <authentication>
                 <login-module code="org.jboss.resource.security.SecureIdentityLoginModule" flag="required">
                   <module-option name="username">ma_mgmdb</module-option>
                   <module-option name="password">-5cdd895416a30c6207a6df87216de44</module-option>
                   <module-option name="managedConnectionFactoryName">jboss.jca:name=miMng,service=LocalTxCM</module-option>
                 </login-module>
                </authentication>
</application-policy>
 
3、使用
外部client程序调用:
Context initContext = new InitialContext();
Properties props = new Properties();
props.setProperty("java.naming.factory.initial",
"org.jnp.interfaces.NamingContextFactory");
props.setProperty("java.naming.provider.url",
"jnp://172.17.236.133:11004");//"jnp://172.17.236.133:11004"
props.setProperty("java.naming.factory.url.pkgs",
"org.jboss.naming:org.jnp.interfaces");
initContext = new InitialContext(props);
 
DataSource ds = (DataSource)initContext.lookup("miMng");
Connection conn = ds.getConnection();
Statement stat = conn.createStatement();
String sql = "select * from tbl_user";
ResultSet rs = stat.executeQuery(sql);
if(rs.next())
System.out.print(rs.getString(1));
conn.close();
initContext.close();
 
war包内程序调用:
<%
Context initContext = new InitialContext();
DataSource ds = (DataSource)initContext.lookup("miMng");
Connection conn = ds.getConnection();
Statement stat = conn.createStatement();
String sql = "select * from tbl_user";
ResultSet rs = stat.executeQuery(sql);
if(rs.next())
out.print(rs.getString(1));
conn.close();
initContext.close();
%>
 
 
报错:
org.jboss.resource.JBossResourceException: Apparently wrong driver class specified for URL: 
class: com.mysql.jdbc.Driver, url: jdbc:mysql://146.240.54.1:60016/mimgmdb?useUnicode=true&characterEncoding=utf-8&useOldAliasMetadataBehavior=true&zeroDateTimeBehavior=convertToNull
org.jboss.resource.adapter.jdbc.local.LocalManagedConnectionFactory.getDriver(LocalManagedConnectionFactory.java:492)
解决:将war包的WEB-INF/lib下的mysql驱动移动到server\default\lib下就好了
 
 
 
高危漏洞
Slow HTTP Denial Of Service Attack
这个攻击的原理和slowloris有点类似,略有不同的是利用的HTTP POST:POST的时候,指定一个非常大的
content-length,然后以很低的速度发包,比如10-100s发一个字节,hold住这个连接不断开。这样当客
户端连接多了后,占用住了webserver的所有可用连接,从而导致DOS。
 
 
管理系统因浏览器flash插件原因无法显示?
解决:安装install_flash_player_ax_14.0.0.176.1407893783.exe
 
 
 
java.net.UnknownHostException: miftcom01: miftcom01
        at java.net.InetAddress.getLocalHost(InetAddress.java:1360)
        at org.jboss.system.server.ServerInfo.getHostName(ServerInfo.java:344)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at org.jboss.reflect.plugins.introspection.ReflectionUtils.invoke(ReflectionUtils.java:59)
        at org.jboss.reflect.plugins.introspection.ReflectMethodInfoImpl.invoke(ReflectMethodInfoImpl.java:150)
        at org.jboss.beans.info.plugins.DefaultPropertyInfo.get(DefaultPropertyInfo.java:133)
        at org.jboss.managed.plugins.factory.AbstractInstanceClassFactory.getValue(AbstractInstanceClassFactory.java:202)
        at org.jboss.deployers.plugins.managed.BeanMetaDataICF.getValue(BeanMetaDataICF.java:205)
        at org.jboss.deployers.plugins.managed.BeanMetaDataICF.getValue(BeanMetaDataICF.java:54)
        at org.jboss.managed.plugins.factory.AbstractManagedObjectPopulator.populateValues(AbstractManagedObjectPopulator.java:204)
        at org.jboss.managed.plugins.factory.AbstractManagedObjectPopulator.populateManagedObject(AbstractManagedObjectPopulator.java:130)
        at org.jboss.managed.plugins.factory.AbstractManagedObjectFactory.initManagedObject(AbstractManagedObjectFactory.java:422)
        at org.jboss.managed.api.factory.ManagedObjectFactory.initManagedObject(ManagedObjectFactory.java:77)
        at org.jboss.system.server.profileservice.ProfileServiceBootstrap.initBootstrapMDs(ProfileServiceBootstrap.java:450)
        at org.jboss.system.server.profileservice.ProfileServiceBootstrap.start(ProfileServiceBootstrap.java:242)
        at org.jboss.bootstrap.AbstractServerImpl.start(AbstractServerImpl.java:461)
        at org.jboss.Main.boot(Main.java:221)
        at org.jboss.Main$1.run(Main.java:556)
        at java.lang.Thread.run(Thread.java:662)
解决:vi /etc/hosts查看hostname与ip设置是否一致。
 
 
 
javascript调用android4.2中的方法失败?
Android4.2对webview中Javascript接口声明进行了修改,Android 4.2以上版本调用Javascript接口失败的解决方法是在方法之前
使用声明@JavascriptInterface。
view plaincopyprint?.addJavascriptInterface(new Object()
{  
                @JavascriptInterface  
                public void download(int bookId)  
                {  
                    bid = String.valueOf(bookId);  
                    downLoad.show();  
                }
 
 
访问url:http://172.17.252.88:10000/mjc/MtqWebService?wsdl报如下错:
Error creating bean with name 'MtqWebServiceServlethttp': Invocation of init method failed; 
nested exception is javax.xml.ws.WebServiceException: org.apache.cxf.service.factory.ServiceConstructionException
解决:MjcRequest类缺少无参构造函数,考,报错这么模糊。
public MjcResponse callByObject(MjcRequest mr) {}
public MjcRequest(){}
 
 
mtqj1.4.3版本改造成访问这个url需要给content-length,否则报411
http://172.17.248.74:11000/mjc/webtrans/s?aa=1111
 
 
mtq.properties中的READ_TIME_OUT设置是mtqj同步交易超时最大值。
注掉READ_TIME_OUT后刷新并不能还原成原先java中定义的值。
 
增加link的para=OB,表示mjc在调用时,函数入参是MjcCoreRequest,返回参数是MjcCoreResponse
 
mtqj的java端接口(MtqWebService+MtqMethodInvocationHandler)使用改变:
callByObject(MjcRequest mjcRequest):交易报文默认使用UTF-8转字节传递
callByObjectUsedBytes(MjcCoreRequest mjcCoreRequest):字节传递
http接口-MtqWebAction:取request.getInputStream(),字节传递
 
日志由异步线程来打的坏处是:
如果tps高导致记录的日志太大的话,而异步线程在写磁盘的速度又低,会导致日志队列变的巨大,导致fullgc时间过长,且无法清理。陷入死循环。
 
 
ConcurrentLinkedQueue非阻塞队列
BlockingQueue    阻塞队列
 
 
ant中条件判断这里有2种形式,一种是运用 target 的if and unless attributes (ant 中自带功能),
一种是运用ant-contrib(一个ant的插件)中的if else。
 
 
2014-09-25 16:45:32,937 [Thread-4630] ERROR com.cup.maps.online.OnlineTrans - WS调用失败:
java.lang.reflect.UndeclaredThrowableException
at $Proxy298.parseSchema(Unknown Source)
at org.apache.cxf.endpoint.dynamic.DynamicClientFactory.addSchemas(DynamicClientFactory.java:423)
at org.apache.cxf.endpoint.dynamic.DynamicClientFactory.createClient(DynamicClientFactory.java:271)
at org.apache.cxf.endpoint.dynamic.DynamicClientFactory.createClient(DynamicClientFactory.java:198)
at org.apache.cxf.endpoint.dynamic.DynamicClientFactory.createClient(DynamicClientFactory.java:191)
at org.apache.cxf.endpoint.dynamic.DynamicClientFactory.createClient(DynamicClientFactory.java:146)
at com.cup.maps.online.OnlineTrans.getResponseByType(OnlineTrans.java:628)
at com.cup.maps.online.OnlineTrans.access$000(OnlineTrans.java:57)
at com.cup.maps.online.OnlineTrans$ServiceDealThread.run(OnlineTrans.java:834)
Caused by: 
java.lang.reflect.InvocationTargetException
at sun.reflect.GeneratedMethodAccessor500.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:37)
at java.lang.reflect.Method.invoke(Method.java:600)
at org.apache.cxf.common.util.ReflectionInvokationHandler.invoke(ReflectionInvokationHandler.java:52)
... 9 more
Caused by: 
java.lang.StackOverflowError
at org.apache.xerces.dom.ElementNSImpl.setName(Unknown Source)
at org.apache.xerces.dom.ElementNSImpl.<init>(Unknown Source)
at org.apache.xerces.dom.CoreDocumentImpl.createElementNS(Unknown Source)
at com.sun.xml.internal.bind.marshaller.SAX2DOMEx.startElement(SAX2DOMEx.java:118)
at com.sun.tools.internal.xjc.reader.internalizer.DOMBuilder.startElement(DOMBuilder.java:84)
at org.xml.sax.helpers.XMLFilterImpl.startElement(Unknown Source)
at com.sun.tools.internal.xjc.reader.internalizer.WhitespaceStripper.startElement(WhitespaceStripper.java:109)
at org.xml.sax.helpers.XMLFilterImpl.startElement(Unknown Source)
at com.sun.tools.internal.xjc.reader.internalizer.VersionChecker.startElement(VersionChecker.java:94)
at org.xml.sax.helpers.XMLFilterImpl.startElement(Unknown Source)
at com.sun.tools.internal.xjc.reader.internalizer.AbstractReferenceFinderImpl.startElement(AbstractReferenceFinderImpl.java:80)
at org.xml.sax.helpers.XMLFilterImpl.startElement(Unknown Source)
at com.sun.xml.internal.bind.unmarshaller.DOMScanner.visit(DOMScanner.java:236)
...
at com.sun.xml.internal.bind.unmarshaller.DOMScanner.scan(DOMScanner.java:119)
at com.sun.tools.internal.xjc.api.impl.s2j.SchemaCompilerImpl.parseSchema(SchemaCompilerImpl.java:131)
... 13 more
解决:多线程调用DynamicClientFactory.createClient()时出现死循环,导致StackOverflowError错误。解决方法重启。
提出的缺陷
http://stackoverflow.com/questions/23907726/jaxwsdynamicclientfactory-newinstance-createclientwsdl-java-lang-reflect-u
http://mail-archives.apache.org/mod_mbox/cxf-issues/201405.mbox/%3CJIRA.12717029.1401278298753.30879.1401278406504@arcas%3E
 
 
 
2014-09-25 16:46:29,770 [Thread-4635] ERROR com.cup.maps.online.OnlineTrans - WS调用失败:
java.lang.reflect.UndeclaredThrowableException
at $Proxy298.bind(Unknown Source)
at org.apache.cxf.endpoint.dynamic.DynamicClientFactory.createClient(DynamicClientFactory.java:273)
at org.apache.cxf.endpoint.dynamic.DynamicClientFactory.createClient(DynamicClientFactory.java:198)
at org.apache.cxf.endpoint.dynamic.DynamicClientFactory.createClient(DynamicClientFactory.java:191)
at org.apache.cxf.endpoint.dynamic.DynamicClientFactory.createClient(DynamicClientFactory.java:146)
at com.cup.maps.online.OnlineTrans.getResponseByType(OnlineTrans.java:628)
at com.cup.maps.online.OnlineTrans.access$000(OnlineTrans.java:57)
at com.cup.maps.online.OnlineTrans$ServiceDealThread.run(OnlineTrans.java:834)
Caused by: 
java.lang.reflect.InvocationTargetException
at sun.reflect.GeneratedMethodAccessor528.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:37)
at java.lang.reflect.Method.invoke(Method.java:600)
at org.apache.cxf.common.util.ReflectionInvokationHandler.invoke(ReflectionInvokationHandler.java:52)
... 8 more
Caused by: 
java.lang.reflect.UndeclaredThrowableException
at $Proxy300.error(Unknown Source)
at com.sun.tools.internal.xjc.api.impl.s2j.SchemaCompilerImpl.error(SchemaCompilerImpl.java:276)
at com.sun.tools.internal.xjc.util.ErrorReceiverFilter.error(ErrorReceiverFilter.java:73)
at com.sun.xml.internal.xsom.impl.parser.ParserContext$2.error(ParserContext.java:178)
at com.sun.xml.internal.xsom.impl.parser.ParserContext$1.reportError(ParserContext.java:156)
at com.sun.xml.internal.xsom.impl.parser.NGCCRuntimeEx.reportError(NGCCRuntimeEx.java:146)
at com.sun.xml.internal.xsom.impl.parser.DelayedRef.resolve(DelayedRef.java:98)
at com.sun.xml.internal.xsom.impl.parser.DelayedRef.run(DelayedRef.java:64)
at com.sun.xml.internal.xsom.impl.parser.ParserContext.getResult(ParserContext.java:107)
at com.sun.xml.internal.xsom.parser.XSOMParser.getResult(XSOMParser.java:202)
at com.sun.tools.internal.xjc.ModelLoader.createXSOM(ModelLoader.java:515)
at com.sun.tools.internal.xjc.api.impl.s2j.SchemaCompilerImpl.bind(SchemaCompilerImpl.java:228)
... 12 more
Caused by: 
java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:48)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:37)
at java.lang.reflect.Method.invoke(Method.java:600)
at org.apache.cxf.common.util.ReflectionInvokationHandler.invoke(ReflectionInvokationHandler.java:52)
... 24 more
Caused by: 
java.lang.RuntimeException: Error compiling schema from WSDL at {http://145.0.153.23:10080/mjc/MtqWebService?WSDL}: undefined simple or complex type 'tns:callByObject'
at org.apache.cxf.endpoint.dynamic.DynamicClientFactory$InnerErrorListener.error(DynamicClientFactory.java:579)
... 29 more
Caused by: 
org.xml.sax.SAXParseException: undefined simple or complex type 'tns:callByObject'
at com.sun.xml.internal.xsom.impl.parser.ParserContext$1.reportError(ParserContext.java:152)
... 19 more
解决:上面那个报错发生后,再次调用这个函数DynamicClientFactory.createClient均会出现这个问题。
 
 
 
 
ulimit 限制的是当前 shell 进程以及其派生的子进程.
建议设置成无限制(unlimited)的一些重要设置是:
数据段长度:ulimit –d unlimited
最大内存大小:ulimit –m unlimited
堆栈大小:ulimit –s unlimited
CPU 时间:ulimit –t unlimited
虚拟内存:ulimit –v unlimited
 
 
 
response.getoutputstream 可以close()多次吗?
解决:试验后发现可以执行多次不报错。
 
 
 
替换某个目录/home/mi_mgmap/sl下的所有文件的某个字符串/SERVICE01/ma,改成/maps
即使用/maps替换/SERVICE01/ma,命令如下:
sed -i "s/\/SERVICE01\/ma/\/maps/g" `grep /SERVICE01/ma -rl /home/mi_mgmap/sl`
注意:特殊字符 / 需要用 \/ 代替;`是1左边的符号;/home/mi_mgmap/sl是需要替换文件的目录
 
 
查找某一类型文件(比如.h文件)中含有的字符串(比如ABC)
find . -name "*.h"|xargs grep -R ABC
 
 
调整JBOSS最大连接数.
配置deploy/jboss-web.deployer/server.xml文件 .
       <Connector         port="8080"         address="0.0.0.0"         maxThreads="1600"         minSpareThreads="100"
         maxSpareThreads="250"         emptySessionPath="false"         enableLookups="false"         redirectPort="8443"
         acceptCount="800"         connectionTimeout="20000"         disableUploadTimeout="true"         URIEncoding="UTF-8"/>
maxThreads:表示最多同时处理的连接数。应该将线程数(最大线程数)设置比最大预期负载(同时并发的点击)多25%(经验规则)。
acceptCount:当同时连接的人数达到maxThreads时,还可以接收排队的连接。
minSpareThread:指“启动以后,总是保持该数量的线程空闲等待”;设置比预期负载多25%。 
maxSpareThread:指“如果超过了minSpareThread,然后总是保持该数量的线程空闲等待”;设置比预期负载多25%。
其中主要修改两个参数maxThreads和acceptCount值。增加maxThreads,减少acceptCount值有利缩短系统的响应时间。
但是maxThreads和acceptCount的总和最高值不能超过6000,而且maxThreads过大会增加CPU和内存消耗,
故低配置用户可通过降低maxThreads并同时增大acceptCount值来保证系统的稳定。
下表罗列出了在不同并发情况下jboss参数与并发在线的一般关系。
并发数服务器内存jboss参数
  maxThreadsacceptCount
50以下2G256800
50-3004G6001024
300-8008G10241528
800-10008G10242048
1000-120012G15262048
1200-150016G20482048
 
 
top命令找到占用CPU最高的java线程?
1、top -Hp 28174 -d 2 -n 6 
解释:查找进程号pid=28174的所有线程,每隔2秒显示一次,共6次。
找到最耗CPU的线程是20766,转换成16进制511e
2、/usr/java/jdk1.6.0_37/bin/jstack -l  28174 | grep 511e -A 20
用jstack命令查看线程堆栈,-A 20表示显示以511e开头的后20行记录。
例:
"DestroyJavaVM" prio=10 tid=0x00002aaab4268800 nid=0x511e waiting on condition [0x0000000000000000]  
   java.lang.Thread.State: RUNNABLE  
   Locked ownable synchronizers:  
        - None
(此方法还能看到哪个线程存活时间最长)
 
 
 
jsp、freemarker、velocity优缺点
jsp优点:官方标准,支持TAG、EL,使用java代码,丰富的第三方标签库。缺点是前后分离较难,容易破坏MVC结构。
velocity优点:不能写java代码,严格的前后分离;性能最佳;使用表达式语言。缺点是非官方标准;文档少。
freemarker优点:不能写java代码,严格的前后分离;性能较好;使用表达式语言;内置大量常用功能;支持jsp标签。缺点是非官方标准;文档少。
 
JSF优点是开发大量数据交互和表单展示时比较方便;缺点是学习曲线陡峭,UI组件及其生命周期需要学习,组件限制了前端展示的自由度,
对于企业内部系统比较合适。最好的框架是自己开发的框架,修改方便,了解框架极限。
 
 
 
velocity在与spring一起使用时,要使得vhtml模板能使用jsp里面的request对象,要在spring-mvc.xml中的
<bean id="velocityViewResolver"
配置
<property name="requestContextAttribute" value="req"/>
这样在vhtml中可使用如下方法:
${req.contextPath}      == /biz (注意前面有个斜杠/)
 
 
 
Velocity与jQuery的$发生冲突时的三种解决办法:
Velocity的$与Jquery的$发生冲突时的解决方法有以下几个:
1、使用jQuery代替$。
   如:jQuery.ajax();
   缺点:不适合扩展,一旦替换成第三方库时,那就麻烦大发
2、使用jQuery.noConflict。
   如:var j = jQuery.noConflict(); j.ajax();
   缺点:当使用jQuery的相关插件时,会使得插件失效哦!
3、wrap jQuery中的冲突方法。
   如$.ajax()在Velocity中会冲突,则重新定义如下:
function dw(){}
dw.ajax=function(s){
    jQuery.ajax(s);
}
dw.ajax();
方案3基本上解决了1、2中的缺点~~~故推荐使用第三种方法!
 
 
 
SPRING MVC 的请求参数获取的几种方法?
1、通过@PathVariabl注解获取路径中传递参数
JAVA
 @RequestMapping(value = "/{id}/{str}")
 public ModelAndView helloWorld(@PathVariable String id, @PathVariable String str) {
 System.out.println(id);
 System.out.println(str);
 return new ModelAndView("/helloWorld");
}
2、用@ModelAttribute注解获取POST请求的FORM表单数据
JSP
<form method="post" action="hao.do">
 a: <input id="a" type="text" name="a"/>
 b: <input id="b" type="text" name="b"/>
 <input type="submit" value="Submit" />
</form>
JAVA pojo
 public class Pojo{
 private String a;
 private int b;
}
JAVA controller
@RequestMapping(method = RequestMethod.POST)
public String processSubmit(@ModelAttribute("pojo") Pojo pojo) {
 return "helloWorld";
 }
3、直接用HttpServletRequest获取
JAVA
@RequestMapping(method = RequestMethod.GET)
public String get(HttpServletRequest request, HttpServletResponse response) {
 System.out.println(request.getParameter("a"));
 return "helloWorld";
}
4、用注解@RequestParam绑定请求参数a到变量a
当请求参数a不存在时会有异常发生,可以通过设置属性required=false解决,
例如: @RequestParam(value="a", required=false)
JAVA
@RequestMapping(value = "/requestParam", method = RequestMethod.GET)
public String setupForm(@RequestParam("a") String a, ModelMap model) {
 System.out.println(a);
return "helloWorld";} 
 
 
 
<UL id=comparePro>
        <li id=compare_prod_list_001>信用卡贷款活动产品1-中国建设银行</li>
         <li id=compare_prod_list_002>信用卡贷款活动产品2-中国建设银行</li>
        <li id=compare_prod_list_003>信用卡贷款活动产品3-中国建设银行</li>
<li id=other>其他</li>
</UL>
要取到所有 id以compare_prod_list_开头的<li>   :  var list=$('li[id^=compare_prod_list_]');
 
 
 
遍历json 对象的属性并且动态添加属性
 var person= {
  name: 'zhangsan',
  pass: '123' ,
  'sni.ni' : 'sss',
  hello:function (){
     for(var i=0;i<arguments.length;i++){
             //在不知参数个数情况下可通过for循环遍历            
             // arguments这个是js 默认提供
            alert("arr["+i+"]="+arguments[i]);
     }    
  }
 }
  
//遍历属性
 for(var item in person){
    if(typeof person[item]  === 'string'){
      alert("person中"+item+"的值="+person[item]);
    }else if(typeof person[item] === 'function'){
        person[item](1,1);//js 的function的参数可以动态的改变
    } 
 }
//添加属性
 person.isMe = 'kaobian'; // 这种是属性名字正常的
//当属性名字不正常时,像下面这种,必须用这种形式的,
 person['isMe.kaobian'] = 'hello kaobian'; //上面的也可以用下面的形式
 
 for(var item in person){
    if(typeof person[item]  === 'string'){
      alert("person中"+item+"的值="+person[item]);
    }else if(typeof person[item] === 'function'){
 
        person[item](1,1);
    } 
 } 
 
 
调用load方法的完整格式是:load( url, [data], [callback] ),其中
url:是指要导入文件的地址。
data:可选参数;因为Load不仅仅可以导入静态的html文件,还可以导入动态脚本,例如PHP文件,所以要导入的是动态文件时,我们可以把要传递的参数放在这里。
callback:可选参数;是指调用load方法并得到服务器响应后,再执行的另外一个函数。
一:如何使用data
1.加载一个php文件,该php文件不含传递参数
$("#myID").load("test.php");
//在id为#myID的元素里导入test.php运行后的结果
2. 加载一个php文件,该php文件含有一个传递参数
$("#myID").load("test.php",{"name" : "Adam"});
//导入的php文件含有一个传递参数,类似于:test.php?name=Adam
3. 加载一个php文件,该php文件含有多个传递参数。注:参数间用逗号分隔
$("#myID").load("test.php",{"name" : "Adam" ,"site":"61dh.com"});
//导入的php文件含有一个传递参数,类似于:test.php?name=Adam&site=61dh.com
4. 加载一个php文件,该php文件以数组作为传递参数
$("#myID").load("test.php",{'myinfo[]', ["Adam", "61dh.com"]});
//导入的php文件含有一个数组传递参数。
注意:使用load,这些参数是以POST的方式传递的,因此在test.php里,不能用GET来获取参数。
 
 
 
$(":input")                  选择所有的表单输入元素,包括input, textarea, select 和 button
$(":text")                     选择所有的text input元素
 
$("#myELement")    选择id值等于myElement的元素,id值不能重复在文档中只能有一个id值是myElement所以得到的是唯一的元素
$("div")           选择所有的div标签元素,返回div元素数组
$(".myClass")      选择使用myClass类的css的所有元素
$("*")             选择文档中的所有的元素,可以运用多种的选择方式进行联合选择:例如$("#myELement,div,.myclass")
 
层叠选择器:
$("form input")         选择所有的form元素中的input元素
$("#main > *")          选择id值为main的所有的子元素
$("label + input")     选择所有的label元素的下一个input元素节点,经测试选择器返回的是label标签后面直接跟一个input标签的所有input标签元素
$("#prev ~ div")       同胞选择器,该选择器返回的为id为prev的标签元素的所有的属于同一个父元素的div标签
 
基本过滤选择器:
$("tr:first")               选择所有tr元素的第一个
$("tr:last")                选择所有tr元素的最后一个
$("input:not(:checked) + span")  
 
过滤掉:checked的选择器的所有的input元素
$("tr:even")               选择所有的tr元素的第0,2,4... ...个元素(注意:因为所选择的多个元素时为数组,所以序号是从0开始)
 
$("tr:odd")                选择所有的tr元素的第1,3,5... ...个元素
$("td:eq(2)")             选择所有的td元素中序号为2的那个td元素
$("td:gt(4)")             选择td元素中序号大于4的所有td元素
$("td:ll(4)")              选择td元素中序号小于4的所有的td元素
$(":header")
$("div:animated")
内容过滤选择器:
 
$("div:contains('John')") 选择所有div中含有John文本的元素
$("td:empty")           选择所有的为空(也不包括文本节点)的td元素的数组
$("div:has(p)")        选择所有含有p标签的div元素
$("td:parent")          选择所有的以td为父节点的元素数组
可视化过滤选择器:
 
$("div:hidden")        选择所有的被hidden的div元素
$("div:visible")        选择所有的可视化的div元素
属性过滤选择器:
 
$("div[id]")              选择所有含有id属性的div元素
$("input[name='newsletter']")    选择所有的name属性等于'newsletter'的input元素
 
$("input[name!='newsletter']") 选择所有的name属性不等于'newsletter'的input元素
 
$("input[name^='news']")         选择所有的name属性以'news'开头的input元素
$("input[name$='news']")         选择所有的name属性以'news'结尾的input元素
$("input[name*='man']")          选择所有的name属性包含'news'的input元素
 
$("input[id][name$='man']")    可以使用多个属性进行联合选择,该选择器是得到所有的含有id属性并且那么属性以man结尾的元素
 
子元素过滤选择器:
 
$("ul li:nth-child(2)"),$("ul li:nth-child(odd)"),$("ul li:nth-child(3n + 1)")
 
$("div span:first-child")          返回所有的div元素的第一个子节点的数组
$("div span:last-child")           返回所有的div元素的最后一个节点的数组
$("div button:only-child")       返回所有的div中只有唯一一个子节点的所有子节点的数组
 
表单元素选择器:
 
$(":input")                  选择所有的表单输入元素,包括input, textarea, select 和 button
 
$(":text")                     选择所有的text input元素
$(":password")           选择所有的password input元素
$(":radio")                   选择所有的radio input元素
$(":checkbox")            选择所有的checkbox input元素
$(":submit")               选择所有的submit input元素
$(":image")                 选择所有的image input元素
$(":reset")                   选择所有的reset input元素
$(":button")                选择所有的button input元素
$(":file")                     选择所有的file input元素
$(":hidden")               选择所有类型为hidden的input元素或表单的隐藏域
 
表单元素过滤选择器:
 
$(":enabled")             选择所有的可操作的表单元素
$(":disabled")            选择所有的不可操作的表单元素
$(":checked")            选择所有的被checked的表单元素
$("select option:selected") 选择所有的select 的子元素中被selected的元素
 
选取一个name 为”S_03_22″的input text框的上一个td的text值
$(”input[@name =S_03_22]“).parent().prev().text()
 
名字以”S_”开始,并且不是以”_R”结尾的
$(”input[@name ^='S_']“).not(”[@name $='_R']“)
 
一个名为radio_01的radio所选的值
$(”input[@name =radio_01][@checked]“).val();
 
$("A B") 查找A元素下面的所有子节点,包括非直接子节点
$("A>B") 查找A元素下面的直接子节点 www.2cto.com
$("A+B") 查找A元素后面的兄弟节点,包括非直接子节点
$("A~B") 查找A元素后面的兄弟节点,不包括非直接子节点
 
 
unix系统提供两个数据文件:
utmp记录当前登陆进系统的各个用户
wtmp跟踪各个登陆和注销事件
who命令读取utmp并打印
last命令读取wtmp并打印
 
 
 
测试85-/maps/usr/ma_onl/xty/unix>uname -a
AIX P570_H_5 1 6 00C7112D4C00(操作系统 主机名 操作系统主版本 从版本号 硬件号码)
 
 
hostname 主机名
超级用户通过此命令设置主机名,该名字通常是TCPIP网络上主机的名字。
 
测试85-/maps/usr/ma_onl/xty/unix>date -u +%a
Sun
测试85-/maps/usr/ma_onl/xty/unix>date -u +%x
11/09/14
格式输出
 
测试85-/maps/usr/ma_onl/xty/unix>echo $TZ 
Asia/Shanghai
该环境变量决定时区
 
 
 
UNIX下core文件的分析 一般步骤:
1. file core文件,可以显示出core文件是哪个进程产生的
2.使用gdb或者dbx加载core文件,  gdb 进程名  core文件
3.where,显示堆栈信息,显示出coredump的地方
 
 
 
使用如下方法提交表单时,recid将不会传到后台。必须在form表单中增加一个input=hidden列,名字叫recid
var path = "${req.contextPath}/vm/edit/$tblcd?recid="+1;
  jQuery('#form2').attr("action", path).submit();
 
 
0配置的spring mvc需要在web.xml如下配置:
<context:component-scan base-package="com.cup.maps.parameter.bizcontrol.contol" />
 
<aop:aspectj-autoproxy />
spring aop需要增加到:
<context:component-scan base-package="com.cup.maps.parameter.bizcontrol.contol,com.cup.maps.parameter.bizcontrol.advice">
<context:include-filter type="annotation" expression="org.aspectj.lang.annotation.Aspect" />
</context:component-scan>
<aop:aspectj-autoproxy />
 
 
使用stax读取xml:
"<message name="PARAM_EDITPAGE_TYPE_0">0</message>"
1、reader.getAttributeName(0)   ->   name
2、reader.getAttributeValue(0)->   PARAM_EDITPAGE_TYPE_0
3、reader.getElementText()->   0
在调用语句3后,1、2都不能调用了,会报错。
 
 
jquery复选框全选、全不选?
<input type="checkbox" id="recids" />全选
<input type="checkbox" id="recid" value="$actives.recid"/>
<input type="checkbox" id="recid" value="$actives.recid"/>
 
function doInit(){//初始化加载
  jQuery("#recids").change(function(){ 
jQuery(":checkbox").prop("checked",this.checked); 
});
}
 
 
Hibernate
save() 保存持久化对象,返回对应的主键值
persist()保存持久化对象,无返回值
load()加载持久化实例,无匹配时抛出HibernateException异常;如果设置了延迟加载,返回未初始化对象,直到调用该对象方法时,Hibernate才会访问db
get()加载持久化实例,无匹配时返回null;而且无延迟加载功能。
 
持久化对象的修改,会在flush()时保存入数据库,如:
News n = sess.load(News.class,new Integer(pk));
n.setTitle("");
sess.flush();
 
对于托管对象,可以采用update() merge() updateOrSave()方法保存修改:
update()
merge()   与update区别是不会持久化给定对象
updateOrSave()
lock()  将某个托管对象重新持久化
 
delete() 删除持久化实例
 
Hibernate映射文件
 
 
主从表级联操作,持久化实体操作的传播:(默认是none)
<one-to-one name="person" cascade="persist"/>
<one-to-one name="person" cascade="persist,delete,lock"/>
<one-to-one name="person" cascade="all"/>
 
Hibernate批量插入,多次调用下面语句将导致OutofMemory,解决是每隔若干条save记录后session.flush()+session.clear():
session.save(bean);    //session级别缓存。
 
 
HQL查询:
session.createQuery("...").setString("","").list();
 
 
apache配置负载均衡session粘性?
解决:
1、需要在apache的配置文件httpd.conf里最后一段加上
ProxyPass       /mposWcg balancer://wcgbalancer stickySession=JSESSIONID
ProxyPassReverse  /mposWcg balancer://wcgbalancer
<Proxy balancer://wcgbalancer>
BalancerMember http://172.18.63.69:12000/mposWcg loadfactor=1 route=Node1
BalancerMember http://172.18.63.70:12000/mposWcg loadfactor=1 route=Node2
</Proxy>
2、增加jboss的server.xml中jvmRoute并重启,两台设置要不一样
vi ~/upjas/upjas-minimal/server/default/deploy/jbossweb.sar/server.xml
修改 <Engine name="jboss.web" defaultHost="localhost">
成<Engine name="jboss.web" defaultHost="localhost" jvmRoute="Node1">
 
原理是给浏览器的Cookie中出了jsessionid外还增加了jvmRoute值,apache可以知道是从哪个jboss来的。
Cookie:"JSESSIONID=33430E7895899E3CD7A051A4457D1D85.Node1"
 
 
 
严重: Exception sending context initialized event to listener instance of class org.springframework.web.context.ContextLoaderListener
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory' defined in ServletContext resource [/WEB-INF/applicationContext.xml]: Initialization of bean failed; nested exception is java.lang.NoClassDefFoundError: javax/transaction/TransactionManager
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:532)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:461)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:295)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:292)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:608)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:932)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:479)
at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:389)
at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:294)
at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:112)
at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4206)
at org.apache.catalina.core.StandardContext.start(StandardContext.java:4705)
at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1057)
at org.apache.catalina.core.StandardHost.start(StandardHost.java:840)
at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1057)
at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:463)
at org.apache.catalina.core.StandardService.start(StandardService.java:525)
at org.apache.catalina.core.StandardServer.start(StandardServer.java:754)
at org.apache.catalina.startup.Catalina.start(Catalina.java:595)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:289)
at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:414)
Caused by: java.lang.NoClassDefFoundError: javax/transaction/TransactionManager
at java.lang.Class.getDeclaredMethods0(Native Method)
at java.lang.Class.privateGetDeclaredMethods(Class.java:2436)
at java.lang.Class.privateGetPublicMethods(Class.java:2556)
at java.lang.Class.getMethods(Class.java:1412)
at org.springframework.beans.ExtendedBeanInfoFactory.supports(ExtendedBeanInfoFactory.java:53)
at org.springframework.beans.ExtendedBeanInfoFactory.getBeanInfo(ExtendedBeanInfoFactory.java:44)
at org.springframework.beans.CachedIntrospectionResults.<init>(CachedIntrospectionResults.java:236)
at org.springframework.beans.CachedIntrospectionResults.forClass(CachedIntrospectionResults.java:152)
at org.springframework.beans.BeanWrapperImpl.getCachedIntrospectionResults(BeanWrapperImpl.java:321)
at org.springframework.beans.BeanWrapperImpl.getPropertyDescriptorInternal(BeanWrapperImpl.java:351)
at org.springframework.beans.BeanWrapperImpl.isWritableProperty(BeanWrapperImpl.java:427)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1395)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1134)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:522)
... 26 more
Caused by: java.lang.ClassNotFoundException: javax.transaction.TransactionManager
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1680)
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1526)
... 40 more
解决:加入jta.jar
 
 
 
java.lang.ClassNotFoundException: antlr.RecognitionException
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1680)
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1526)
at org.hibernate.hql.ast.ASTQueryTranslatorFactory.createQueryTranslator(ASTQueryTranslatorFactory.java:58)
at org.hibernate.engine.query.HQLQueryPlan.<init>(HQLQueryPlan.java:98)
at org.hibernate.engine.query.HQLQueryPlan.<init>(HQLQueryPlan.java:80)
at org.hibernate.engine.query.QueryPlanCache.getHQLQueryPlan(QueryPlanCache.java:124)
at org.hibernate.impl.AbstractSessionImpl.getHQLQueryPlan(AbstractSessionImpl.java:156)
at org.hibernate.impl.AbstractSessionImpl.createQuery(AbstractSessionImpl.java:135)
at org.hibernate.impl.SessionImpl.createQuery(SessionImpl.java:1694)
at org.springframework.orm.hibernate3.HibernateTemplate$30.doInHibernate(HibernateTemplate.java:914)
at org.springframework.orm.hibernate3.HibernateTemplate$30.doInHibernate(HibernateTemplate.java:912)
at org.springframework.orm.hibernate3.HibernateTemplate.doExecute(HibernateTemplate.java:406)
at org.springframework.orm.hibernate3.HibernateTemplate.executeWithNativeSession(HibernateTemplate.java:374)
at org.springframework.orm.hibernate3.HibernateTemplate.find(HibernateTemplate.java:912)
at com.cup.maps.parameter.bizcontrol.dao.ParamDao.getInqFldByTblcd(ParamDao.java:14)
at com.cup.maps.parameter.bizcontrol.service.ParamSerivceImpl.genInqFldInParaFileds(ParamSerivceImpl.java:118)
at com.cup.maps.parameter.bizcontrol.service.ParamSerivceImpl.setParamQueryInq(ParamSerivceImpl.java:103)
at com.cup.maps.parameter.bizcontrol.contol.InitController.bizParaminit(InitController.java:41)
at com.cup.maps.parameter.bizcontrol.contol.InitController$$FastClassByCGLIB$$886e2fe6.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:698)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:91)
at com.cup.maps.parameter.bizcontrol.advice.DealforVm.privcheck(DealforVm.java:41)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:621)
at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:610)
at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:65)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.adapter.AfterReturningAdviceInterceptor.invoke(AfterReturningAdviceInterceptor.java:51)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:91)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:631)
at com.cup.maps.parameter.bizcontrol.contol.InitController$$EnhancerByCGLIB$$529de169.bizParaminit(<generated>)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:176)
at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:440)
at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:428)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:925)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:856)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:936)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:827)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:617)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:812)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:723)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293)
at org.apache.coyote.http11.Http11AprProcessor.process(Http11AprProcessor.java:879)
at org.apache.coyote.http11.Http11AprProtocol$Http11ConnectionHandler.process(Http11AprProtocol.java:617)
at org.apache.tomcat.util.net.AprEndpoint$Worker.run(AprEndpoint.java:1760)
at java.lang.Thread.run(Thread.java:662)
解决:引入antlr.jar
 
 
org.hibernate.hql.ast.QuerySyntaxException: TblMamgmParaFldAttr is not mapped [from TblMamgmParaFldAttr a]
at org.hibernate.hql.ast.util.SessionFactoryHelper.requireClassPersister(SessionFactoryHelper.java:181)
at org.hibernate.hql.ast.tree.FromElementFactory.addFromElement(FromElementFactory.java:109)
解决:使用hbm.xml中的class name 而不是table真实表名。
find("from TblMamgmParaFldAttr a");
 
 
 
org.hibernate.MappingException: Unknown entity: com.cup.maps.parameter.bizcontrol.model.hibernate.TblMamgmParaFldAttr
at org.hibernate.impl.SessionFactoryImpl.getEntityPersister(SessionFactoryImpl.java:629)
at org.hibernate.event.def.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:91)
解决:spring和hibernate整合在配置sessionFactory时有两种配置方法。
方法一:不要hibernate.cfg.xml,在applicationContext.xml中配置如下
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="myDataSource"></property>
<property name="mappingResources">
<list>
<value>com/cup/maps/parameter/bizcontrol/model/hibernate/TblMamgmParaFldAttr.hbm.xml</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">
org.hibernate.dialect.DB2Dialect
</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.connection.release_mode">
auto
</prop>
<prop key="hibernate.transaction.auto_close_session">
true
</prop>
<prop key="show_sql">true</prop>
</props>
</property>
</bean>
 
方法二:
applicationContext.xml中配置:
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="myDataSource"></property>
<property name="configLocations">  
        <value>classpath:hibernate.cfg.xml</value>  
    </property> 
</bean>
hibernate.cfg.xml中配置(propertry要再mapping之前):
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
          "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
          "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="dialect">org.hibernate.dialect.DB2Dialect</property>
<property name="show_sql">true</property> 
<property name="hibernate.show_sql">true</property>  
<property name="hibernate.connection.release_mode">auto</property>  
<property name="hibernate.transaction.auto_close_session">true</property> 
<mapping
resource="com/cup/maps/parameter/bizcontrol/model/hibernate/TblMamgmIndustryInsAttr.hbm.xml" />
<mapping
resource="com/cup/maps/parameter/bizcontrol/model/hibernate/TblMamgmParaFldAttr.hbm.xml" />
</session-factory>
</hibernate-configuration>
 
 
 
 
Caused by: java.lang.NoClassDefFoundError: javassist/util/proxy/MethodFilter
...
at org.hibernate.tuple.entity.PojoEntityTuplizer.<init>(PojoEntityTuplizer.java:77)
... 16 more
Caused by: java.lang.ClassNotFoundException: javassist.util.proxy.MethodFilter
at java.net.URLClassLoader$1.run(URLClassLoader.java:200)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
at java.lang.ClassLoader.loadClass(ClassLoader.java:252)
at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:320)
... 21 more
解决:缺少javassist.jar,在upjas\upjas-minimal\lib下。
 
 
 
org.hibernate.QueryException: could not resolve property: tblcd of: com.cup.maps.parameter.bizcontrol.model.hibernate.TblMamgmParaFldAttr
at org.hibernate.persister.entity.AbstractPropertyMapping.propertyException(AbstractPropertyMapping.java:67)
at org.hibernate.persister.entity.AbstractPropertyMapping.toType(AbstractPropertyMapping.java:61)
解决:字段名有问题,tblcd改成tblCd。
criteria.add(Restrictions.eq("tblcd", tblcd)).add(Restrictions.eq("inqFldIn", "1"));
改成
criteria.add(Restrictions.eq("tblCd", tblcd)).add(Restrictions.eq("inqFldIn", "1"));
 
 
org.hibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here
at org.springframework.orm.hibernate3.SpringSessionContext.currentSession(SpringSessionContext.java:64)
at org.hibernate.impl.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:623)
解决:
Session session = sessionFactory.getCurrentSession();这句报错。因为是直接从spring中获得的bean。
正确代码如下:
SessionFactory sessionFactory = (SessionFactory)SpringContextUtil.getBean("mgmSessionFactory");
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
。。。
tx.commit();
//session.close(); 无需调用close
 
 
org.hibernate.SessionException: Session was already closed
org.hibernate.impl.SessionImpl.close(SessionImpl.java:304)
com.cup.maps.parameter.bizcontrol.cache.ParamCache.init(ParamCache.java:60)
解决:如果不是使用的SessionFactory.getSession()来获得Session。而是使用SessionFactory.getCurrentSession()或者sessionFactory.openSession();
方法来获得Session时,当事务结束的时候,不管是提交还是回滚事务,hibernate会自动关闭Session的。
因此在tx.commit();后面不需要再session.close();
 
 
java.lang.UnsupportedOperationException: The user must supply a JDBC connection
at org.hibernate.connection.UserSuppliedConnectionProvider.getConnection(UserSuppliedConnectionProvider.java:54)
at org.hibernate.jdbc.ConnectionManager.openConnection(ConnectionManager.java:446)
解决:
 
 
 
 
win7 TortoiseCVS-1.12.5 cvs checkout乱码?
解决:卸载当前cvsnt软件,重新安装老版本cvsnt_setup.exe,重启win7就好了
 
 
 
解决Spring MVC ResponseBody 乱码问题?
在SpringMVC中,ResponseBody返回的中文是乱码,google了一下,原因是这可以说是spring mvc的一个bug,
spring MVC有一系列HttpMessageConverter去处理用@ResponseBody注解的返回值,如返回list则使用
MappingJacksonHttpMessageConverter,返回string,则使用 StringHttpMessageConverter,这个convert
使用的是字符集是iso-8859-1,而且是final的
     public static final Charset DEFAULT_CHARSET = Charset.forName("ISO-8859-1");    
解决方法是在
    <context:annotation-config />  
前面加入以下配置:
    <bean  class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" >    
        <property name="messageConverters">    
             <list>    
                 <bean class = "org.springframework.http.converter.StringHttpMessageConverter">    
                    <property name = "supportedMediaTypes">    
                         <list>
                             <value>text/plain;charset=UTF-8</value>    
                         </list>
                    </property>    
                 </bean>    
             </list>    
        </property>    
    </bean>    
但是也有网友认为前面这种方式不太优雅,而且不一定有效,经试验下面这种方法也可以:
    @RequestMapping(value="qxyjqyresult",produces = "plain/text; charset=UTF-8")  
        @ResponseBody  
        public String getQxyjqyResult(String filename) throws Throwable {  
    return "中文"  
    }  
也就是用produces。
 
 
 
使用另外一个相关联的对象的标识符作为主键。 
<id>元素中的<generator>用来为该持久化类的实例生成唯一的标识,hibernate提供了很多内置的实现。 
Increment:由hibernate自动递增生成标识符,用于为long, short或者int类型生成唯一标识。 
identity :由底层数据库生成标识符(自动增长),返回的标识符是 long, short 或者int类型的。 
sequence :hibernate根据底层数据库序列生成标识符,返回的标识符 是long, short或者 int类型的。 
hilo     :使用一个高/低位算法来高效的生成long, short 或者int类型的标识符。 
uuid.hex :用一个128-bit的UUID算法生成32位字符串类型的标识符。 
native   :根据底层数据库的能力选择identity, sequence 或者hilo中的一个。 
assigned :让应用程序在save()之前为对象分配一个标示符。 
foreign :使用另外一个相关联的对象的标识符。和<one-to-one>联合一起使用。
 
 
List list = session
.createQuery(
"select b.id.drdlItemKey,b.drdlItemVal from TblMamgmDrdlCfg a,TblMamgmDrdlItemDef b where a.drdlId = b.id.drdlId and a.drdlNm = :dropDownNm")
.setString("dropDownNm", dropDownNm).list();
联合主键在hbm.xml中的联合主键配置是: <composite-id name="id" class="com.cup.maps.parameter.bizcontrol.model.hibernate.TblMamgmDrdlItemDefId">
原生sql中使用则是b.id.drdlItemKey。
 
 
 
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.cup.maps.parameter.bizcontrol.model.hibernate.TblMamgmDrdlCfg.drdlItemList, no session or session was closed
解决:这个是懒加载异常,就是在查询时没有加载关联表的对象,你读取这个关联对象的时候,hibernate的session已经关闭,所以无法获取对象。
你可以在配置文件里关闭懒加载 lazy=false
 
 
 
spring mvc中遇到了如何实现页面跳转的问题.比如在页面A中的提交按钮用户提交后,需要重定向到另外一个新的页面,并且有可能要把一些参数带
过去.
  这其实在实现中有两个方法
1 在controller中实现redirect,可以使用sendRedirect()方法,然后返回
 public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception 
{
........
 response.sendRedirect("photohouxuandetail.do?pid="+pid);
   return null;
}
2 还可以用redirect来实现,这样viewResolver认为是重定向操作,不再渲染该视图了,而是直接向客户端发出redirect响应
   return new ModelAndView("redirect:photohouxuandetail.do?pid="+pid);
 
 
 
 
org.springframework.dao.DataIntegrityViolationException: not-null property references a null or transient value: com.cup.maps.parameter.bizcontrol.model.hibernate.TblMamgmDrdlItemDef.operIn; nested exception is org.hibernate.PropertyValueException: not-null property references a null or transient value: com.cup.maps.parameter.bizcontrol.model.hibernate.TblMamgmDrdlItemDef.operIn
at org.springframework.orm.hibernate3.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:665)
解决:在Hibernate中使用数据库字段默认值的配置 
1、在相关表的映射XML文件的class项增加:dynamic-insert="true"
2、同时需在相关字段设置:not-null="false"
 
 
 
org.springframework.dao.DataIntegrityViolationException: could not update: [com.cup.maps.parameter.bizcontrol.model.hibernate.TblMamgmDrdlItemDef#component[drdlId,drdlItemKey]{drdlItemKey=1111, drdlId=1111}]; SQL [update MA_MGMDB.TBL_MAMGM_DRDL_ITEM_DEF set DRDL_ITEM_VAL=?, OPER_IN=?, EVENT_ID=?, REC_ID=?, REC_UPD_USR_ID=?, REC_UPD_TS=?, REC_CRT_TS=? where DRDL_ID=? and DRDL_ITEM_KEY=?]; constraint [null]; nested exception is org.hibernate.exception.ConstraintViolationException: could not update: [com.cup.maps.parameter.bizcontrol.model.hibernate.TblMamgmDrdlItemDef#component[drdlId,drdlItemKey]{drdlItemKey=1111, drdlId=1111}]
at org.springframework.orm.hibernate3.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:643)
at org.springframework.orm.hibernate3.HibernateAccessor.convertHibernateAccessException(HibernateAccessor.java:412)
解决:DataIntegrityViolationException。字段对应属性非空,改成not-null="false"
 
 
 
严重: Exception sending context initialized event to listener instance of class org.springframework.web.context.ContextLoaderListener
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'paramService' defined in ServletContext resource [/WEB-INF/applicationContext.xml]: Initialization of bean failed; nested exception is org.springframework.beans.factory.BeanNotOfRequiredTypeException: Bean named 'bziControltxAdvice' must be of type [org.aopalliance.aop.Advice], but was actually of type [org.springframework.transaction.interceptor.TransactionInterceptor]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:532)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:461)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:295)
解决:TransactionInterceptor是 org.aopalliance.aop.Advice
的一个实现,可能是Jar包的冲突。
到jar包中去查看。
 我的问题是: aopalliance-1.0.jar 和 aopalliance-alpha1.jar之间的冲突。
 
 
 
 
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataTableController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: com.cup.maps.parameter.bizcontrol.service.ParamSerivceImpl com.cup.maps.parameter.bizcontrol.contol.DataTableController.pService; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.cup.maps.parameter.bizcontrol.service.ParamSerivceImpl] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:288)
解决:强制转换的必须是接口类ParamService,而不是实际类ParamSerivceImpl
ParamService pService = (ParamSerivceImpl) SpringContextUtil.getBean("paramService");
改成
ParamService pService = (ParamService) SpringContextUtil.getBean("paramService");
 
 
 
 
Hibernate: select tmpmamgmin_.INDUSTRY_INS_ATTR_CD, tmpmamgmin_.INDUSTRY_INS_ATTR_NM as INDUSTRY2_6_, tmpmamgmin_.INDUSTRY_INS_ID_CD as INDUSTRY3_6_, tmpmamgmin_.INDUSTRY_INS_CATA_OPT as INDUSTRY4_6_, tmpmamgmin_.TEST_MD as TEST5_6_, tmpmamgmin_.RVSL_IN as RVSL6_6_, tmpmamgmin_.TO_RVSL_IN as TO7_6_, tmpmamgmin_.SYS_TO_SYS_FLAG as SYS8_6_, tmpmamgmin_.PROD_CUP_OPER_SPEC as PROD9_6_, tmpmamgmin_.CHNL_LD_CUP_OPER_SPEC as CHNL10_6_, tmpmamgmin_.CHNL_LD_CUP_BRANCH_OPER_SPEC as CHNL11_6_, tmpmamgmin_.CHNL_OPER_SPEC as CHNL12_6_, tmpmamgmin_.SP_OPER_SPEC as SP13_6_, tmpmamgmin_.SUCC_SP_RESP_INF as SUCC14_6_, tmpmamgmin_.REPAY_SP_RESP_INF as REPAY15_6_, tmpmamgmin_.NOTOUTBILL_SP_RESP_INF as NOTOUTBILL16_6_, tmpmamgmin_.SPEC_SP_RESP_INF as SPEC17_6_, tmpmamgmin_.CORRECT_USR_NO_SP_RESP_INF as CORRECT18_6_, tmpmamgmin_.REMARK as REMARK6_, tmpmamgmin_.OPER_IN as OPER20_6_, tmpmamgmin_.EVENT_ID as EVENT21_6_, tmpmamgmin_.REC_ID as REC22_6_, tmpmamgmin_.REC_UPD_USR_ID as REC23_6_, tmpmamgmin_.REC_UPD_TS as REC24_6_, tmpmamgmin_.REC_CRT_TS as REC25_6_ from MA_MGMDB.TMP_MAMGM_INDUSTRY_INS_ATTR tmpmamgmin_ where tmpmamgmin_.INDUSTRY_INS_ATTR_CD=?
org.springframework.orm.hibernate3.HibernateSystemException: identifier of an instance of com.cup.maps.parameter.bizcontrol.model.hibernate.TblMamgmIndustryInsAttr was altered from 00002400-1-001     to 00002400-1-001; nested exception is org.hibernate.HibernateException: identifier of an instance of com.cup.maps.parameter.bizcontrol.model.hibernate.TblMamgmIndustryInsAttr was altered from 00002400-1-001     to 00002400-1-001
at org.springframework.orm.hibernate3.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:690)
解决:实体中主键被修改了,所以报错。从00002400-1-001     改成了00002400-1-001,因为页面trim的关系。
 
 
 
spring多次执行flush也不会有问题:
this.getHibernateTemplate().flush();
 
 
 
 
在hibernate中实现oracle的主键自增策略
1、在oracle 首先创建sequence
      create sequence seq_id
      minvalue 1
      start with 1
      increment by 1
      cache 20;
2.在你的hbm.xml中的配置
   
     <id column="ID0000" name="id" type="integer">
         <generator class="sequence">
              <param name="sequence">seq_id</param>
         </generator>
     </id>
 
 
 
spring3中bean自动注入
@Resource(name="paramService")
ParamService paramService;
 
 
在dwr_spring.xml中配置的bean,必须在applicationContext.xml中配置,spring-mvc.xml不可以。
 
 
spring托管类,要想达到这个效果:在初始化并注入所有属性后,执行某个方法:
1、实现InitializingBean
public class ParamCache  implements InitializingBean
 
2、实现这个方法afterPropertiesSet
public void afterPropertiesSet() throws Exception {
init();
}
 
 
使用sessionFactory时未绑定事务,使用方法:
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
Criteria criteria = session.createCriteria(TblMamgmParaTblAttr.class);
tx.commit();
 
 
 
 
DAO层
DAO层主要是做数据持久层的工作,负责与数据库进行联络的一些任务都封装在此,DAO层的设计首先是设计DAO的接口,然后在Spring的配置文件
中定义此接口的实现类,然后就可在模块中调用此接口来进行数据业务的处理,而不用关心此接口的具体实现类是哪个类,显得结构非常清晰,
DAO层的数据源配置,以及有关数据库连接的参数都在Spring的配置文件中进行配置。 
 
Service层
Service层主要负责业务模块的逻辑应用设计。同样是首先设计接口,再设计其实现的类,接着再Spring的配置文件中配置其实现的关联。
这样我们就可以在应用中调用Service接口来进行业务处理。Service层的业务实现,具体要调用到已定义的DAO层的接口,封装Service层
的业务逻辑有利于通用的业务逻辑的独立性和重复利用性,程序显得非常简洁。 
 
Controller层
Controller层负责具体的业务模块流程的控制,在此层里面要调用Serice层的接口来控制业务流程,控制的配置也同样是在Spring的配置文件
里面进行,针对具体的业务流程,会有不同的控制器,我们具体的设计过程中可以将流程进行抽象归纳,设计出可以重复利用的子单元流程模块,
这样不仅使程序结构变得清晰,也大大减少了代码量。 
 
View层 
此层与控制层结合比较紧密,需要二者结合起来协同工发。View层主要负责前台jsp页面的表示, 
 
 
DAO层,Service层这两个层次都可以单独开发,互相的耦合度很低,完全可以独立进行,这样的一种模式在开发大项目的过程中尤其有优势,
Controller,View层因为耦合度比较高,因而要结合在一起开发,但是也可以看作一个整体独立于前两个层进行开发。这样,在层与层之前
我们只需要知道接口的定义,调用接口即可完成所需要的逻辑单元应用,一切显得非常清晰简单。 
 
DAO设计的总体规划需要和设计的表,和实现类之间一一对应。 
 
DAO层所定义的接口里的方法都大同小异,这是由我们在DAO层对数据库访问的操作来决定的,对数据库的操作,我们基本要用到的就是新增,
更新,删除,查询等方法。因而DAO层里面基本上都应该要涵盖这些方法对应的操作。除此之外,可以定义一些自定义的特殊的对数据库访问的方法。 
 
Service逻辑层设计 
Service层是建立在DAO层之上的,建立了DAO层后才可以建立Service层,而Service层又是在Controller层之下的,因而Service层应该既调用DAO层
的接口,又要提供接口给Controller层的类来进行调用,它刚好处于一个中间层的位置。每个模型都有一个Service接口,每个接口分别封装各自的
业务处理方法。 
 
在DAO层定义的一些方法,在Service层并没有使用,那为什么还要在DAO层进行定义呢?这是由我们定义的需求逻辑所决定的。DAO层的操作
经过抽象后基本上都是通用的,因而我们在定义DAO层的时候可以将相关的方法定义完毕,这样的好处是在对Service进行扩展的时候不需要
再对DAO层进行修改,提高了程序的可扩展性。
 
 
前置PIT环境管理启动时现象:nohup和serverlog中没有报错,cpu占用率近于0,等待很长时间以后nohup中报错,获取不了数据源miMng。
原因:server/default/lib中upjas_dbpm.jar没有删除,而upjas_setEnv.sh里面设置了dbpm的ip地址和PIT环境不在一个网段,所以用了很长的时间
去连接,可能jar包里面还重试了多次。
 
 
onblur="if(value==''){value='your email address'}" 失去焦点的时候
onfocus="" 得到焦点的时候
 
 
$("#textDiv").show();//显示div  
$("#imgDiv").hide();//隐藏div  
$("#sendPhoneNum").css("display", "none");   //通过jquery的css方法,设置div隐藏
$("#top_notice").attr("style", "display:block;");  //给元素设置style属性
 
 
用CSS设置浮动层
margin-top:0px; position:absolute; display:none
 
 
velocity 字符串解析报错:
#set($bmpnumvalue=${flds.value}.substring($bmpnum,$bmpnumend))
要改成下面这种,原因未知
#set($bmpnumvalue=$flds.value.substring($bmpnum,$bmpnumend))
 
jquery如果判断元素是否隐藏(hide)?_百度知道
$("p").is(":hidden")
 
 
让input表单只读的几种方法
方法1: onfocus=this.blur()
<input type="text" name="input1" value="建站学" onfocus=this.blur()>
方法2: readonly
<input type="text" name="input1" value="建站学" readonly>
<input type="text" name="input1" value="建站学" readonly="true">
方法3: disabled
<input type="text" name="input1" value="建站学" disabled>
 
 
Hibernate配置文件中设置隔离级别,默认是4
#hibernate.connection.isolation 4
<property name=” hibernate.connection.isolation”>4</property>
1:读操作未提交(Read Uncommitted)
2:读操作已提交(Read Committed)
4:可重读(Repeatable Read)
8:可串行化(Serializable)
 
1、更新丢失(Lost Update):两个事务都企图去更新一行数据,导致事务抛出异常退出,两个事务的更新都白费了。
2、脏数据(Dirty Read):如果第二个应用程序使用了第一个应用程序修改过的数据,而这个数据处于未提交状态,这时就会发生脏读。
第一个应用程序随后可能会请求回滚被修改的数据,从而导致第二个事务使用的数据被损坏,即所谓的“变脏”。
3、不可重读(Unrepeatable Read):一个事务两次读同一行数据,可是这两次读到的数据不一样,就叫不可重读。如果一个事务在提交数据之前,
另一个事务可以修改和删除这些数据,就会发生不可重读。
4、幻读(Phantom Read):一个事务执行了两次查询,发现第二次查询结果比第一次查询多出了一行,这可能是因为另一个事务在这两次查询
之间插入了新行。
 
1、读操作未提交(Read Uncommitted):说明一个事务在提交前,其变化对于其他事务来说是可见的。这样脏读、不可重读和幻读都是允许的。
当一个事务已经写入一行数据但未提交,其他事务都不能再写入此行数据;但是,任何事务都可以读任何数据。这个隔离级别使用排写锁实现。
2、读操作已提交(Read Committed):读取未提交的数据是不允许的,它使用临时的共读锁和排写锁实现。这种隔离级别不允许脏读,
但不可重读和幻读是允许的。
3、可重读(Repeatable Read):说明事务保证能够再次读取相同的数据而不会失败。此隔离级别不允许脏读和不可重读,但幻读会出现。
4、可串行化(Serializable):提供最严格的事务隔离。这个隔离级别不允许事务并行执行,只允许串行执行。这样,脏读、不可重读
或幻读都不可发生。
 
 
 
java.io.IOException: Missing config file: 'WEB-INF/para/dwr_spring.xml'
org.directwebremoting.impl.DwrXmlConfigurator.setServletResourceName(DwrXmlConfigurator.java:78)
org.directwebremoting.impl.StartupUtil.configureFromInitParams(StartupUtil.java:645)
jboss里面WEB-INF/para/dwr_spring.xml说是找不到?
解决:权宜之计
1、删除配置未知
<!--   <init-param>  
      <param-name>config-1</param-name>  
      <param-value>WEB-INF/para/dwr_spring.xml</param-value>  
  </init-param>
 -->
2、把dwr.xml配置文件移动位置,并改名。
把WEB-INF/para/dwr_spring.xml移动到web.xml平级目录,然后改名成dwr.xml
 
 
 
 
hibernate 默认jdbc事务,并整合spring后配置(在applicationContext.xml文件中):
<bean id="MgmDataSource"
class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="jdbcMapsMng"></property>
</bean>
<bean id="mgmSessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="MgmDataSource"></property>
<property name="configLocations">  
        <value>classpath:hibernate.cfg.xml</value>  
    </property> 
</bean>
<!-- 配置事务管理器 指定其作用的sessionFactory把事务交给Spring去处理 -->
    <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    <property name="sessionFactory">
    <ref bean="mgmSessionFactory"/>
    </property>
    </bean>    
<!-- bizcontrol 配置事务的传播特性 -->
    <tx:advice id="bziControltxAdvice" transaction-manager="transactionManager">
    <tx:attributes>
    <tx:method name="save*" propagation="REQUIRED"/>
    <tx:method name="delete*" propagation="REQUIRED"/>
    <tx:method name="active*" propagation="REQUIRED"/>
    <tx:method name="get*" read-only="true" propagation="NOT_SUPPORTED"/>
    <tx:method name="*" read-only="true"/>
    </tx:attributes>
    </tx:advice>
    
<!-- 那些类的哪些方法参与事务 -->
    <aop:config>
    <aop:pointcut id="allServiceMethod" expression="execution(* com.cup.maps.parameter.bizcontrol.service.*.*(..))"/>
    <aop:advisor pointcut-ref="allServiceMethod" advice-ref="bziControltxAdvice"/>
    </aop:config> 
 
 
hibernate 使用jboss的jta事务,并整合spring
1、applicationContext.xml文件中配置:
<bean id="MgmDataSource"
class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="jdbcMapsMng"></property>
</bean>
<bean id="mgmSessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="MgmDataSource"></property>
<property name="configLocations">  
        <value>classpath:hibernate.cfg.xml</value>  
    </property> 
</bean>
  <!-- 配置Spring使用JTA事务 -->
  <tx:jta-transaction-manager />
  
<!-- bizcontrol 配置事务的传播特性 -->
    <tx:advice id="bziControltxAdvice" transaction-manager="transactionManager">
    <tx:attributes>
    <tx:method name="save*" propagation="REQUIRED"/>
    <tx:method name="delete*" propagation="REQUIRED"/>
    <tx:method name="active*" propagation="REQUIRED"/>
    <tx:method name="get*" read-only="true" propagation="NOT_SUPPORTED"/>
    <tx:method name="*" read-only="true"/>
    </tx:attributes>
    </tx:advice>
<!-- 那些类的哪些方法参与事务 -->
    <aop:config>
    <aop:pointcut id="allServiceMethod" expression="execution(* com.cup.maps.parameter.bizcontrol.service.*.*(..))"/>
    <aop:advisor pointcut-ref="allServiceMethod" advice-ref="bziControltxAdvice"/>
    </aop:config>
2、hibernate.cfg.xml中配置:
<property name="hibernate.current_session_context_class">jta</property>
<property name="hibernate.transaction.manager_lookup_class">org.hibernate.transaction.JBossTransactionManagerLookup</property>
<property name="hibernate.transaction.factory_class">org.hibernate.transaction.JTATransactionFactory</property>
3、com.cup.maps.parameter.bizcontrol.service包下的所有类的save、active、delete开头的方法自动具有事务属性。
 
 
 
 
 
 
 
form提交时
action="${req.contextPath}/vm/paramimport/$tblcd"
必须要写成这样
action="${req.contextPath}/vm/paramimport/${tblcd}"
 
 
 
dwr返回list<javabean>时报错:bean is null
解决:dwr.xml中要配置新加bean的东东,否则页面bean==null
 <convert converter="bean" match="com.cup.maps.parameter.bizcontrol.model.DropDownItem">  
        <param name="include" value="key,value" />  
</convert>
 
 
jquery获得某个name是INQ_加变量eventDef表示的值的select元素:
解决:jQuery("select[name=INQ_"+eventDef+"]").empty();
 
 
弹出框
 var sw = screen.width;
 var sh = screen.height;
 var w = 500;
 var h = 600; 
 var l = (sw-w)/2;
 var t = 200;
 var parm=",toolbar=no,location=no,directories=no,status=no,menubar=no,scrollbars=yes,resizable=no,maxsige=yes";
 var scoll="width="+w+",height="+h+",left="+l+",top="+t;
 var urls = "${req.contextPath}/vm/load/biztree?bpmparamaction=hySearch";
 window.open(urls,"_blank",scoll+parm);
注意:window.open()浏览器不支持隐藏地址栏
 
window.open()使用POST方式提交?
解决:注意form的target="newWin"
function submitForm(){  
  window.open('','newWin','width=400,height=500,scrollbars=yes');  
  form对象.submit();  
}
<FORM name=form action="YourActionFile.html" method="post" target="newWin">  
...  
</Form>
 
 
alert(parseInt("11111010", 2));
alert(parseInt("11111010", 2).toString(16));
 
 
 
 
overflow从字面意义上来讲就是溢出的意思,换句话说,你有个层,但是里面的内容,图片或者文字要比层大,
overflow就是针对这种情况进行处理的。
包含4个属性值,visible,hidden,auto,scroll
visible就是超出的内容仍然正常被显示出来。
hidden就是超出的内容被隐藏。
auto是默认值,根据内容剪切或者加滚动条。
scroll就是总加滚动条
 
 
 
bizcontrol生效页面,IE8无法生效?
解决:F12,浏览器模式选型IE8兼容性视图,文本模式选择IE8标准。原因是IE8兼容性模式下才支持JSON.stringify。
 
 
bizcontrol新增修改页面,IE8无法保存?
解决:发现IE8没有tmpvalue.trim()函数竟然,使用jQuery.trim(tmpvalue)替代。
 
 
firefox里生效页面,选择一条记录,点参数查看,然后点返回,报“文档已过期”错误,IE里面没有此错误?
解决:无法解决,不过在报“文档已过期”错误的那个页面上,点“重试”再次进入参数查看页面,点返回,回到参数查询页面。
 
 
hibernate关联记录,配置过滤条件和排序字段
<set name="drdlItemList" table="TBL_MAMGM_DRDL_ITEM_DEF" lazy="false" where="OPER_IN NOT IN ('D','d')" order-by="DRDL_ITEM_KEY">
        <key column="DRDL_ID" />
        <one-to-many
        class="com.cup.maps.parameter.bizcontrol.model.hibernate.TblMamgmDrdlItemDef" />
        </set>
 
 
 
db2查看锁表信息
>db2pd -db mamgmdb -locks show detail
 
表解锁
db2 force application all
 
 
SELECT * FROM SYSCAT.TABLES WHERE TBSPACEID = 2 AND TABLEID = 512;
 
SELECT * FROM SYSCAT.COLUMNS WHERE  TABNAME= '*******' AND COLNO = 8 
 
 
 
 
Javascript 判断是否存在函数的方法?
function aa()
{
 this.length=1;
 this.size =2;
}
if (typeof(aa)=="function")
alert(1);
else
alert(2);
 
使用SqlMapClientTemplate查询?
当执行没有参数的查询时: 
List result = getSqlMapClientTemplate().queryForList("TestSpace.qryTest");  
"TestSpace"为iBatis SqlMap文件的命名空间;"qryTest"为iBatis SqlMap的查询方法id 
 
当按照主键获取某条记录信息时: 
Long id = new Long("2");  
Object resultObj = getSqlMapClientTemplate().queryForObject("TestSpace.getTest", id);
 
 
LRU缓存介绍与实现 (Java)?
public class LRUCache<K,V> extends LinkedHashMap<K, V>{
    private LinkedHashMap<K,V>  cache =null ;
    private int cacheSize = 0;       
    public LRUCache(int cacheSize){
        this.cacheSize = cacheSize;
        int hashTableCapacity = (int) Math.ceil (cacheSize / 0.75f) + 1;
        cache = new LinkedHashMap<K, V>(hashTableCapacity, 0.75f,true)
        {
            // (an anonymous inner class)
            private static final long serialVersionUID = 1;
 
            @Override
            protected boolean removeEldestEntry (Map.Entry<K, V> eldest)
            {
                System.out.println("size="+size());
                return size () > LRUCache.this.cacheSize;
            }
        };
    }   
    public V put(K key,V value){
        return cache.put(key, value);
    }
    public V get(Object key){
        return cache.get(key);
    }
}
LRUCache<String, String> lruCache = new LRUCache<String, String>(5);
 
 
LinkedHashMap缺省是使用插入顺序的,如何构造一个访问顺序的LinkedHashMap呢?
public LinkedHashMap(int initialCapacity, float loadFactor, boolean accessOrder) accessOrder = true 即可。
 
LinkedHashMap提供按照访问的次序来排序的功能?
LinkedHashMap改写HashMap的get(key)方法(HashMap不需要排序)和HashMap.Entry的recordAccess(HashMap)方法
public Object get(Object key) {
        Entry e = (Entry)getEntry(key);
        if (e == null)
            return null;
        e.recordAccess(this); 
        return e.value;
    }
void recordAccess(HashMap m) {
            LinkedHashMap lm = (LinkedHashMap)m;
            if (lm.accessOrder) {
                lm.modCount++;
                remove();
                addBefore(lm.header);
            }
        }
注 意addBefore(lm.header)是将该entry放在header线性表的最后。(参考LinkedHashMap.Entry extends HashMap.Entry 
比起HashMap.Entry多了before, after两个域,是双向的)
 
 
 
关于在RCP程序开发过程中遇到的:No Application ID has been found错误提示?
原因:依赖项添加不完整,漏掉了某些插件。
解决:运行配置中,在Main选项卡中选择运行方式为run an Application,然后在plugins选项卡中选择chose plugins and fregments from the list,
然后在列表中Workspace Plugins里面选择自己的插件,在target platform中先设为全不选,然后再点击右边的add required Plugins。
这样就可以把必须的插件都自动的添加到项目中。
 
 
 
Jar mismatch! Fix your dependenciesmPOSAppUnknownAndroid Dependency Problem?
解决:在开发Android项目的时候,有时需要引用多个项目作为library。在引用项目的时候,有时会出现“Jar mismatch! Fix your dependencies”错误。
这是因为两个项目的jar包(android-support-v4.jar)不一致。
解决方法是把2个jar都删除,然后各自加上最新的jar包。
 
 
Conversion to Dalvik format failed with error 1?
解决:做为lib工程,java build path标签的Libraries中不应该直接从Add External JARs引入android.jar,而是应该从Add Library
进入,再从Android Classpath Container进,点next,点Finish进入。

 



已有 0人发表留言,猛击->> 这里<<-参与讨论


ITeye推荐



solr的使用

$
0
0

solr的原理不和大家一一讲述,主要讲solr在使用过程中的注意事项

一.solr建立服务

 首先是安装solr,安装步骤省略。。。。(不要说我懒,安装步骤导出都是。。。)

成功之后 需要在solr里面建立一个针对你的业务的服务,我想建立一个叫做discuz的服务

./bin/solr create -c discuz

 

然后你在你的solr目录 :solr-5.5.3/server/solr/  下看见了discuz   ,这是你刚刚创建的,针对某一业务的整个搜索配置都是在这个目录下配置的。

discuz目录解析:

    1.conf :配置文件(索引、分词库、停词库等等配置)

    2.core.properties

    3.data

二.建立索引

   建立索引就是数据库和solr建立一个关系,可以满足数据库数据定时导入solr里面,方面solr实现搜索。那么怎么建立索引呢? 

   在solr-5.5.3/server/solr/discuz/conf/data-config.xml 里面

 

<dataConfig><dataSource type="JdbcDataSource"
        driver="com.mysql.jdbc.Driver"
        url="jdbc:mysql://11.11.11.11:800/database"
        user="root" password="123456"/><document><entity name="database" query="SELECT * FROM table;  "  
 deltaQuery="SELECT id  FROM table  where  `create` > unix_timestamp('${dataimporter.last_index_time}' ;  " 
  deltaImportQuery="SELECT * FROM table where id =${dataimporter.delta.tid}"  pk='tid'><field column="id" name="id" /><field column="subject" name="subject" /><field column="views" name="views" /><field column="vip" name="vip" /><field column="message" name="message" /><field column="create" name="create" /></entity></document></dataConfig>

 

 

  dataConfig 里面是对数据库导入的一个配置

   dataSource:数据库连接配置

   document:数据库索引配置

       entity:name= 数据库名字

                   query=全量导入数据的sql

                  deltaQuery:增量导入的id

                  deltaImportQuery:增量导入的sql  

 解释一下全量和增量:正常数据库导入solr第一次是全部导入,但是随着时间的变化数据库和solr数据不一致,这时候需要再次导入,按时间技术,半小时或者更合适的时间,只需要增量导入即可,更合适的时间再次全量导入即可

               field  这些是返回字段的定义

 

==到现在数据库和solr的关系完事了,下面是solr自身对这些字段的处理

三.solr 对展示字段以及搜索的配置

   在solr-5.5.3/server/solr/discuz/conf/solrconfig.xml

   1.添加一下代码

<schemaFactory class="ManagedIndexSchemaFactory"><bool name="mutable">true</bool><str name="managedSchemaResourceName">managed-schema</str></schemaFactory>

 

 

   在conf下面的 managed-schema 文件里对索引配置

 1.配置中文分词mmseg4j

 

<!-- mmseg4j--><fieldType name="text_mmseg4j_complex" class="solr.TextField" positionIncrementGap="100" >  <analyzer type="index">  <tokenizer class="com.chenlb.mmseg4j.solr.MMSegTokenizerFactory" mode="complex" dicPath="solr-5.5.3/server/solr/discuz/conf/dic"/>  <filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt"/><filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="true"/></analyzer><analyzer type="query"><tokenizer class="com.chenlb.mmseg4j.solr.MMSegTokenizerFactory" mode="complex" dicPath="solr-5.5.3/server/solr/discuz/conf/dic"/> <filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt"/><filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="true"/></analyzer></fieldType>  <fieldType name="text_mmseg4j_maxword" class="solr.TextField" positionIncrementGap="100" >  <analyzer>  <tokenizer class="com.chenlb.mmseg4j.solr.MMSegTokenizerFactory" mode="max-word" dicPath="solr-5.5.3/server/solr/discuz/conf/dic"/></analyzer>  </fieldType><fieldType name="text_mmseg4j_simple" class="solr.TextField" positionIncrementGap="100" >  <analyzer>  <tokenizer class="com.chenlb.mmseg4j.solr.MMSegTokenizerFactory" mode="simple" dicPath="solr-5.5.3/server/solr/discuz/conf/dic"/>     </analyzer>  </fieldType><!-- mmseg4j-->

   solr-5.5.3/server/solr/discuz/conf/dic:中文分词的分词库目录,在改目录下放word.dic分词文件

 stopwords.txt:停词文件

 synonyms.txt:近义词文件

    analyzer type="index":索引检查分词、停词、近义词

   analyzer type="query":查找检查分词、停词、近义词

2.配置索引字段、字段类型、查询字段的中文分词类型

 

<field name="submes" type="text_mmseg4j_complex" indexed="true" stored="true" required="true" multiValued="true" /><field name="id" type="int" indexed="true" stored="true" required="true" multiValued="false" /><field name="vip" type="int" indexed="true" stored="true" required="true" multiValued="false" /><field name="views"    type="int" indexed="true" stored="true" required="true" multiValued="false" /><field name="create" type="int" indexed="true" stored="true" required="true" multiValued="false" /><field name="subject" type="string" indexed="true" stored="true" required="true" multiValued="false" /><field name="message" type="text_general" indexed="true" stored="true" required="true" multiValued="false" /><copyField source="subject" dest="submes" /><copyField source="vip" dest="submes" /><copyField source="views" dest="submes" /><copyField source="create" dest="submes" />

 field 字段定义了solr展示的类型

   name:字段名字

   type:字段类型(如果是要进行查询的字段,类型为中文分词类型如:text_mmseg4j_complex)

   indexed:true

    stored:true

   required:true

        multiValued:查询字段设置为true ,其他为false

copyField : 拷贝需要索引的字段到整合字段中 submes是本列子中的整合字段  solr查询也是查询这个字段

  这个字段可以根据多个字段进行权重设置,并且打分,排序

 

 

四.重启solr

  discuz配置都已经更改完,现在需要重启生效:

  ./bin/solr restart 

  对于一些大的网站而言,重启整个solr回导致其他业务无法搜索,所以可以搞一个zookeep 来一个分布式 管理就可以了

 

 

 五.使用

1.增量导入,在你的solr使用界面上左边下拉框找到discuz 

  下面出现的

  Dataimport: 是执行增量全量导入的

  query:搜索

  analysis:分词

 

 

无法加载图片,根据很难形容,但是打开这个界面就知道了

 

2.搜索打分:有的时候我们除了想根据匹配度排序外,还想根据浏览量、创建时间、是否是vip等综合因素排序,

在curl请求时 请求参数要加上下面的值:

       $params['defType'] = 'edismax' ;

       $params['bf'] = "sum(linear(vip,1000,0),linear(sqrt(log(linear(views,1,2))),100,0),sqrt(log(create)))";

    

  bf里面的参数是solr支持的打分标准的函数,具体使用参考http://mxsfengg.iteye.com/blog/352191 详解  很不完善,后续还会完善,如有问题随时提问

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 



已有 0人发表留言,猛击->> 这里<<-参与讨论


ITeye推荐



Nginx的负载均衡原理

$
0
0

  负载均衡在服务端开发中算是一个比较重要的特性。因为Nginx除了作为常规的Web服务器外,还会被大规模的用于反向代理前端,因为Nginx的异步框架可以处理很大的并发请求,把这些并发请求hold住之后就可以分发给后台服务端(backend servers, 后面简称backend)来做复杂的计算、处理和响应,并且在业务量增加的时候可以方便地扩容后台服务器。
  负载均衡可以分为硬件负载均衡和软件负载均衡,前者一般是专用的软件和硬件相结合的设备,设备商会提供完整成熟的解决方案,通常也会更加昂贵。软件的复杂均衡以Nginx占据绝大多数,本文也是基于其手册做相应的学习研究的。
load-balancing

一、基本简介

  负载均衡涉及到以下的基础知识。
  (1) 负载均衡算法
  a. Round Robin: 对所有的backend轮训发送请求,算是最简单的方式了,也是默认的分配方式;
  b. Least Connections(least_conn): 跟踪和backend当前的活跃连接数目,最少的连接数目说明这个backend负载最轻,将请求分配给他,这种方式会考虑到配置中给每个upstream分配的weight权重信息;
  c. Least Time(least_time): 请求会分配给响应最快和活跃连接数最少的backend;
  d. IP Hash(ip_hash): 对请求来源IP地址计算hash值,IPv4会考虑前3个octet,IPv6会考虑所有的地址位,然后根据得到的hash值通过某种映射分配到backend;
  e. Generic Hash(hash): 以用户自定义资源(比如URL)的方式计算hash值完成分配,其可选consistent关键字支持一致性hash特性;
  (2) 会话一致性
  用户(浏览器)在和服务端交互的时候,通常会在本地保存一些信息,而整个过程叫做一个会话(Session)并用唯一的Session ID进行标识。会话的概念不仅用于购物车这种常见情况,因为HTTP协议是无状态的,所以任何需要逻辑上下文的情形都必须使用会话机制,此外HTTP客户端也会额外缓存一些数据在本地,这样就可以减少请求提高性能了。如果负载均衡可能将这个会话的请求分配到不同的后台服务端上,这肯定是不合适的,必须通过多个backend共享这些数据,效率肯定会很低下,最简单的情况是保证会话一致性——相同的会话每次请求都会被分配到同一个backend上去。
  (3) 后台服务端的动态配置
  出问题的backend要能被及时探测并剔除出分配群,而当业务增长的时候可以灵活的添加backend数目。此外当前风靡的Elastic Compute云计算服务,服务商也应当根据当前负载自动添加和减少backend主机。
  (4) 基于DNS的负载均衡
  通常现代的网络服务者一个域名会关连到多个主机,在进行DNS查询的时候,默认情况下DNS服务器会以round-robin形式以不同的顺序返回IP地址列表,因此天然将客户请求分配到不同的主机上去。不过这种方式含有固有的缺陷:DNS不会检查主机和IP地址的可访问性,所以分配给客户端的IP不确保是可用的(Google 404);DNS的解析结果会在客户端、多个中间DNS服务器不断的缓存,所以backend的分配不会那么的理想。

二、Nginx中的负载均衡

  Nginx中的负载均衡配置在 手册中描述的极为细致,此处就不流水帐了。对于常用的HTTP负载均衡,主要先定义一个upstream作为backend group,然后通过proxy_pass/fastcgi_pass等方式进行转发操作,其中fastcgi_pass几乎算是Nginx+PHP站点的标配了。

2.1 会话一致性

  Nginx中的会话一致性是通过sticky开启的,会话一致性和之前的负载均衡算法之间并不冲突,只是需要在第一次分配之后,该会话的所有请求都分配到那个相同的backend上面。目前支持三种模式的会话一致性:
  (1). Cookie Insertion
  在backend第一次response之后,会在其头部添加一个session cookie,之后客户端接下来的请求都会带有这个cookie值,Nginx可以根据这个cookie判断需要转发给哪个backend了。

1
sticky cookie srv_id expires=1h domain=.example.com path=/;

  上面的srv_id代表了cookie的名字,而后面的参数expires、domain、path都是可选的。
  (2). Sticky Routes
  也是在backend第一次response之后,会产生一个route信息,route信息通常会从cookie/URI信息中提取。

1
sticky route$route_cookie$route_uri;

  这样Nginx会按照顺序搜索$route_cookie、$route_uri参数并选择第一个非空的参数用作route,而如果所有的参数都是空的,就使用上面默认的负载均衡算法决定请求分发给哪个backend。
  (3). Learn
  较为的复杂也较为的智能,Nginx会自动监测request和response中的session信息,而且通常需要回话一致性的请求、应答中都会带有session信息,这和第一种方式相比是不用增加cookie,而是动态学习已有的session。
  这种方式需要使用到zone结构,在Nginx中zone都是共享内存,可以在多个worker process中共享数据用的。(不过其他的会话一致性怎么没用到共享内存区域呢?)

1
2
3
4
5
sticky learn
create=$upstream_cookie_examplecookie
lookup=$cookie_examplecookie
zone=client_sessions:1m
timeout=1h;

2.2 Session Draining

  主要是有需要关闭某些backend以便维护或者升级,这些关键性的服务都讲求gracefully处理的:就是新的请求不会发送到这个backend上面,而之前分配到这个backend的会话的后续请求还会继续发送给他,直到这个会话最终完成。
  让某个backend进入draining的状态,既可以直接修改配置文件,然后按照之前的方式通过向master process发送信号重新加载配置,也可以采用Nginx的on-the-fly配置方式。

1
2
$ curl http://localhost/upstream_conf?upstream=backend
$ curl http://localhost/upstream_conf?upstream=backend\&id=1\&drain=1

  通过上面的方式,先列出各个bacnkend的ID号,然后drain指定ID的backend。通过在线观测backend的所有session都完成后,该backend就可以下线了。

2.3 backend健康监测

  backend出错会涉及到两个参数,max_fails=1 fail_timeout=10s;意味着只要Nginx向backend发送一个请求失败或者没有收到一个响应,就认为该backend在接下来的10s是不可用的状态。
  通过周期性地向backend发送特殊的请求,并期盼收到特殊的响应,可以用以确认backend是健康可用的状态。通过health_check可以做出这个配置。

1
2
3
4
5
6
7
8
9
10
11
match server_ok {
status 200-399;
header Content-Type = text/html;
body !~"maintenance mode";
}
server {
location / {
proxy_pass http://backend;
health_check interval=10 fails=3 passes=2 match=server_ok;
}
}

  上面的health_check是必须的,后面的参数都是可选的。尤其是后面的match参数,可以自定义服务器健康的条件,包括返回状态码、头部信息、返回body等,这些条件是&&与关系。默认情况下Nginx会相隔interval的间隔向backend group发送一个”/“的请求,如果超时或者返回非2xx/3xx的响应码,则认为对应的backend是unhealthy的,那么Nginx会停止向其发送request直到下次改backend再次通过检查。
  在使用了health)check功能的时候,一般都需要在backend group开辟一个zone,在共享backend group配置的同时,所有backend的状态就可以在所有的worker process所共享了,否则每个worker process独立保存自己的状态检查计数和结果,两种情况会有很大的差异哦。

2.4 通过DNS设置HTTP负载均衡

  Nginx的backend group中的主机可以配置成域名的形式,如果在域名的后面添加resolve参数,那么Nginx会周期性的解析这个域名,当域名解析的结果发生变化的时候会自动生效而不用重启。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
http {
resolver 10.0.0.1 valid=300s ipv6=off;
resolver_timeout 10s;
server {
location / {
proxy_pass http://backend;
}
}
upstream backend {
zone backend 32k;
least_conn;
...
server backend1.example.com resolve;
server backend2.example.com resolve;
}
}

  如果域名解析的结果含有多个IP地址,这些IP地址都会保存到配置文件中去,并且这些IP都参与到自动负载均衡。

2.5 TCP/UDP流量的负载均衡

  除了专长的HTTP负载均衡,Nginx还支持TCP和UDP流量的负载均衡,适用于LDAP/MySQL/RTMP和DNS/syslog/RADIUS各种应用场景。这类情况的负载均衡使用stream来配置,Nginx编译的时候需要支持–with-stream选项。查看 手册,其配置原理和参数和HTTP负载均衡差不多。
  因为TCP、UDP的负载均衡都是针对通用程序的,所以之前HTTP协议支持的match条件(status、header、body)是没法使用的。TCP和UDP的程序可以根据特定的程序,采用send、expect的方式来进行动态健康检测。

1
2
3
4
match http {
send"GET / HTTP/1.0\r\nHost: localhost\r\n\r\n";
expect ~*"200 OK";
}

2.6 其他特性

  slow_start=30s:防止新添加/恢复的主机被突然增加的请求所压垮,通过这个参数可以让该主机的weight从0开始慢慢增加到设定值,让其负载有一个缓慢增加的过程。
  max_conns=30:可以设置backend的最大连接数目,当超过这个数目的时候会被放到queue队列中,同时队列的大小和超时参数也可以设置,当队列中的请求数大于设定值,或者超过了timeout但是backend还不能处理请求,则客户端将会收到一个错误返回。通常来说这还是一个比较重要的参数,因为Nginx作为反向代理的时候,通常就是用于抗住并发量的,如果给backend过多的并发请求,很可能会占用后端过多的资源(比如线程、进程非事件驱动),最终反而会影响backend的处理能力。

本文完!

参考

Viewing all 11852 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>