如何架构一个新的综合金融交易系统

 

技术产品需求

客户端网站系统(app),业务系统(接口),运维平台

网站系统:

基础系统:

1.用户(帐户)管理系统 2.商品(行情)管理系统 3.订单(交易管理)系统 4.支付系统5.风控系统

增值系统:

客户服务系统,筛选筛选系统,资讯系统。。。

业务系统:

管理系统:

用户管理系统

运营支撑系统

核心系统:

订单交易系统

查询系统

行情系统

增值系统:

数据统计(报表)系统

客户服务系统

 

技术栈选型

1.前端系统

2.后端系统

2.1 负载均衡及http 服务器接入:nginx

2.2 web 应用容器 SOA 服务 Tomcat + dubbo

2.3 文件服务器

        2.3.1 储存方式
        2.3.2 储存容量
        2.3.3 安全性与存取权限控管
        2.3.4 存取效能

2.4 缓存服务器
         2.4.1 分布式Redis缓存
         2.4.2 Memcache缓存

2.5 消息系统
         2.5.1 ActiveMQ
         2.5.2 分布式消息系统Kafka、Rocketmq等

2.6 数据持久层
         2.6.1 关系型数据库
              (1). Mysql

        2.6.2 Nosql
              (1). MongoDB

python安装

python2 python3 windows 下共存

关于Windows平台上Python2与Python3共存,使用过程中可能会遇到一些问题。关于网上其他的修改python.exe名字的做法都是不合适的。
下面是我从网上搜集过来的正确使用方法,可以完美使用,具体也可以参考官方说明3.4小节有详细说明

关于调用不同版本Python

如果同时安装了Python2和Python3,在安装Python3的时候勾选Install launcher for all users选项,这个选项默认会生成一个Python引导程序。同时最好也加入系统环境变量。

那么在使用的时候可以这样:

  • 使用py -2 hello.py即可调用Python2执行hello.py。py -3 hello.py即可调用Python3来执行hello.py。

  • 在hello.py文件的开头进行标记(可能叫法不对)在文件第一行写上#!python2,或者#!python3这样标记以后,在执行的时候只需要输入py hello.py,会自动调用相应的解释器来执行文件。
    记得#!python2一定要放在第一行。

关于pip的使用
  • 若需要安装Python2的库,执行py -2 -m pip install xxxx即可,xxxx是库的名字。
    若需要安装Python3的库,执行py -3 -m pip install xxxx即可。

java学习路线(转)

比较全,根据自己情况挑着学吧http://blog.csdn.net/pplcheer/article/details/12276999

  • 熟悉一种文本编辑器,比如Vim, Emacs, Notepad++, TextMate等。知道哪些是开源的,哪些是闭源的,哪些要收费。养成不用盗版软件的习惯。

  • 安装JDK(建议用你的Linux发行版自带的软件包管理器安装openjdk,过程中可能需要读发行版特定的文档)

  • 写一个Java的Helloworld程序,并用命令行工具javac编译,再用java命令运行这个程序。过程中熟悉源代码、字节码、虚拟机这些东西,以及Java的包(package)对.class文件所在的路径的影响。如果这两个命令行工具使用熟练了,可以开始选一个喜欢的集成开发环境,比如Eclipse。当然,养成不用盗版软件的习惯。熟悉一下如何建立“工程”,以及快捷键的使用。

  • 学习Java的面向过程编程,包括基本数据结构、表达式、语句、控制流、函数调用。

  • 学习Java的面向对象编程,包括类、引用类型和值类型的区别、成员、方法、访问控制、继承、多态、接口、接口实现。顺便学习一下面向对象的基本思想,即对象、消息、封装、继承、多态等,这些通用的内容不是Java特有的。这时候应该已经涉及了Java的垃圾回收。要留意即使有垃圾回收的情况下也会发生的内存泄露(如自己设计数组容器,元素是引用,逻辑上删除了元素,但并没有清成null)。注意垃圾回收只能回收内存中的对象,除了内存以外,其它资源不能依靠垃圾回收来关闭。比如,文件、管道、Socket、数据库连接等,垃圾回收是不会帮你关闭的。

  • 学习Java的异常处理,但更重要的是学习什么时候用特殊返回值而不使用异常,什么时候应该抛出异常而不处理异常,知道什么是pokemon catch及其危害,了解为什么Java的checked exception是一个糟糕的特性。如果愿意,同时学习一下Java1.7的try-with-resource语句和AutoCloseable接口。

  • 熟悉Java常用的数据结构,如基本的数组类型,以及泛型容器(java.util.*),尤其是java.util.List接口和java.util.ArrayList实现;以及java.util.Map接口和java.util.HashMap实现。(java1.5以前的没有泛型参数的就不用碰了)同时留意一下基本类型int, double等和装箱类型Integer和Double的区别,以及它们是如何自动转换的。

  • 熟悉Java标准库里的各种工具,包括日期时间、字符串格式化、IO等。**知道文件要自己在finally子句中close(),或者用Java1.7的try-with-resource,不要妄想垃圾回收器会帮你关掉文件。

  • 学习一下Java的命名习惯,以及JavaBeans的常规,知道为什么getter/setter比直接操作成员变量好。按这种方式给Java的变量、方法命名。同时看看你的IDE能不能自动帮你生成getter和setter。

  • 使用一个第三方的库(比如Apache Commons Lang通用工具库),让你的程序依赖于它的二进制jar包(而不是直接拷贝源代码),用命令行编译、运行(注意classpath等);也熟悉一下如何用你的集成开发环境添加第三方依赖。感受一下手动管理依赖关系的麻烦。

  • 学习Maven的使用,试着让Maven帮你解决依赖关系,再试着让Maven帮你创建一个Eclipse工程。再试试用Maven打包发布。

  • 学习软件测试,以及JUnit的使用,以及怎么在IDE中使用JUnit。有空看一下coverage工具。

  • 读读四人帮写的《设计模式》(这本书是用C++和Smalltalk语言为例子的,但仍然适合Java)。具体的是这本书,http://www.amazon.com/Design-Patterns-Elements-Reusable-Object-Oriented/dp/0201633612图书馆应该能还借到英文原版,因为我借到过。


接下来就看具体要做哪方面的应用了,看需求。比如(下面的没有顺序)

  1. 关于语言

    • 如果学Java学得不舒服了,学Python。
    • 如果对面向对象编程的概念有点不习惯,学Smalltalk。(Ruby也行,但不如Smalltalk经典。Ruby的文档是一大硬伤。)
    • 如果嫌Java太啰嗦,学Python
    • 如果嫌Java太啰嗦,又想用JVM,自己又有精力,学Scala
    • 如果对对象之间的关系有点晕,学一学UML,以及它的一些图,可以对程序和运行进行直观的建模。你的IDE也许有插件可以生成UML图。但是不要太沉迷于这些方法论。
  2. 调试和辅助工具

    学习一下你的集成开发环境提供的调试工具,加一些断点试试。

    • 试试用jconsole或者VisualVM监控另一个jvm的状态。
    • 用profiling工具寻找程序中慢的地方。Eclipse有profiling工具。VisualVM也有这样的功能。(如果不介意使用闭源软件的话,也试试JProfiler和YourKit)
    • 有的JVM允许在运行时更新代码。Eclipse可以和某些JVM集成。这样你可以频繁修改代码而不用频繁重启JVM。对于某些“重型”工程很有用。(如果不介意使用闭源软件的话,也试试jRebel)
  3. 多线程

    学习Java的多线程编程以及lock、condition的用法(包括传统Java的synchronized语句以及新加的java.util.concurrent.*),学习一下如何让线程停下来,以及为什么要频繁确认isInterrupted()而不要用Thread.stop()。了解一下多核处理器、缓存、内存的关系,以及为什么多线程编程这么难。

    • 如果还舒服,学习一下Runnable的用法,以及自带的Executer等基本多线程工具。
    • 应该已经留意到java.util里面的很多容器不是线程安全的,但是java.util.Collections可以帮你创建一些安全的版本。另外关注一下java.util.concurrent里面有ConcurrentMap等容器可供使用。
    • 如果有空的话,看看memory model(内存一致性模型)和无锁同步(见java memory model和java.util.concurrent.atomic)。
    • 如果还有空,再了解一下除了“共享内存多线程编程”以外有没有别的模型(多进程multi-processing、消息传递message passing等)。
  4. 反射、元编程

    • 学习Java的反射机制,以及Annotation的用法。
    • 如果还舒服,试试java.lang.reflect.Proxy的用法。
    • 如果仍然还舒服,玩一玩CGLib(一个第三方的库)。
  5. 网络编程

    学习一下IP,TCP协议(计算机专业的应该学过,复习一下),学习Socket编程(注意垃圾回收器不会帮你关掉Socket)。

    • 如果不是很关心HTTP,看看java.nio,学习单线程轮询式IO复用(Selector)。
      1. 如果有点不明白nio的意图的话,了解一下c10k问题。 http://www.kegel.com/c10k.html
      2. 如果身体没有异样的话,大概了解一下操作系统(包括C语言)提供的select, poll, epoll, kqueue等接口。
      3. 如果身体仍然没有异样的话,试着用java.nio写一个文件服务器。
      4. 如果还有精力的话,上网扒一扒有没有其他的通信库,如netty等。
    • 如果关心Web还有HTTP,就学习一下HTTP协议,以及用Java进行HTTP的客户端编程。
      1. 如果还舒服,学学HTML,写写HTML的静态网页(不需要Java)
      2. 如果还舒服,用Java写一个基于DOM、XPath或者CSS Selector的网页解析器(爬网页)。
      3. 如果还舒服,学学Java的Servlet接口(先别学jsp)进行Web服务器端编程。学学标准的Servlet容器怎么用,包括web.xml的用法以及listener、filter等概念。以及某个Servlet容器(如Jetty或者Tomcat)的具体用法。
      4. 如果仍然还舒服,试着学一种模板语言(如haml, velocity, freemarker,【还有其他更好的框架吗?我不知道】, String.format,如果真的想学JSP的话JSP倒是也行,但不推荐)。
      5. 如果仍然觉得舒服,学学Spring框架中的Web框架,或者Struts,看你的口味。
      6. 如果还舒服,看看Spring Bean Container以及里面各种乱七八糟的工具。
      7. 如果还舒服,或者有需求,了解一下什么是RESTful Web Service,复习一下HTTP,找找适合的Java工具。
      8. 你可能会觉得Jackson是一个解析JSON用的好用的东西。
  6. 数据库

    学习一下关系数据库(计算机专业的应该学过,复习一下),包括SQL。选一个数据库管理系统熟悉一下(比如MariaDB,或者(如果你不讨厌Oracle的话)用被Oracle收购了的MySQL。先脱离Java单独学学)。然后看它们的官方文档教你怎么用Java连接这种数据库。这中间会涉及到JDBC接口。同时一定要知道SQL注入安全漏洞,以及掌握如何用PreparedStatement防止注入!!。建议看 http://bobby-tables.com/

    • 可能中间会涉及“事务”问题,让你不知不觉地开始去了解java transaction api(JTA)。
    • 如果还舒服,学一学对象关系转换(如Hibernate)。
    • 也可以学学非关系数据库,以及如何用Java访问它们。
  7. 日志记录

    学习一下slf4j和logback的用法。

    • 如果有精力的话,大概了解一下世界上有多少种Java日志框架,以及slf4j是怎么桥接这些框架的。
  8. 构建(build)系统

    学习一下Ant的用法。

    • 如果还舒服的话,学习一下用Ivy从Maven的仓库里下载软件包,解决依赖关系。
  9. 版本控制

    学习一种分布式版本控制器(如Git、Mercurial、Bzr、Darcs等,推荐Git)的基本用法,以及如何用它管理Java工程。希望你已经开始使用Maven了,并且知道为什么把IDE生成的工程文件(如eclipse的.project,.classpath和.metadata)放入版本控制器不好。然后了解一下如何在IDE中使用版本控制(Eclipse自带Git插件)。

    • 如果感觉很舒服的话,为你们实验室搭建一个Linux+SSH+Git服务器,装个GitLab(一种Web界面)。
    • 了解“集中式版本控制器”和“分布式版本控制器”的区别,并说服同事们不要再用SVN、CVS或者SourceSafe等老旧的“集中式版本控制器”了。
    • 开设一个GitHub账户。如果你不喜欢Git,就用BitBucket等。
  10. 持续集成

    自己(或者为你们实验室)搭建一个持续集成(Continuous Integration)服务器,如Jenkins,定期编译你的程序。建议同时使用Git等分布式版本控制器。

    • 如果你做开源软件,试试GitHub和Travis。
  11. 零碎工具

    淘一淘java.nio.files里面有什么好用的东东,然后再淘一淘Apache Commons Lang和Commons IO里有什么好用的工具。Commons Logging就不要再用了,用SLF4j和Logback。

  12. XML

    学学XML、DOM、XPath。XML这东西到处都可能用到。也可以用它写自己的配置文件。

    • 如果觉得不舒服了,就学学JSON和YAML。
    • 如果还是不舒服,就学学文本文件解析。
  13. 语法分析和编译器

    学学Antlr或者别的Parser Generator的用法

    • 如果觉得舒服,自己写一个计算器。
    • 如果还觉得舒服,自己写一种Domain-Specific Language (DSL)。
  14. 高效容器

    学学FastUtil或者Trove,如果你需要进行大量数值运算的话。

  15. 分布式计算

    学学MapReduce的思想以及它的实现。

    • 如果还舒服,学学Scala语言以及号称比MapReduce快得多的Apache Spark。
  16. 进程间通信

    看看ActiveMQ、MINA和RMI。

  17. 其他语言(JVM)

    学习另一门跑在JVM上的语言或者实现(如Groovy、Scala、Clojure、JRuby、Jython、JavaScript……)

  18. 其他语言(非JVM)

    学习另一门通用脚本语言(如Python、Ruby,其实perl也行,但不推荐),知道什么时候Java不是最好的选择。

  19. Java语言和Java虚拟机

    通读一遍(一目十行地读,不用细读)Java Language Specification,以及Java Virtual Machine Specification。

    • 了解以下解释器(interpreter)、编译器(compiler)、即时编译器(just-in-time compiler)和优化器(optimiser)的概念。
    • 如果对编译器的话题不感到畏惧,了解一下method JIT和tracing JIT的概念和区别。
  20. 内存管理

    学学垃圾回收的几种基本算法,包括mark-sweep、mark-compact、semi-space、generational、mark-region等,各自的性能,以及为什么朴素的reference counting是不完整的。知道为什么finalizer性能很糟糕,而且标准并不要求finalizer在程序退出前一定会执行。

    • 如果还舒服,了解一下如何设置Java虚拟机的堆大小限制(如HotSpot虚拟机的-Xmx选项等)。
    • 了解一下Java里的WeakReference以及SoftReference和PhantomReference,以及它们什么时候有用,以及为什么它们实现起来有些困难。
    • 如果有精力,了解一下Hotspot虚拟机的内存管理算法是什么样的。
  21. 动态装载

    学学Java的动态装载(class loading)

    • 如果还舒服的话,学学OSGI以及它的一种实现(如Felix或者Equinox)
    • 如果仍然很舒服的话,学学写基于Eclipse平台的程序。不是Eclipse集成开发环境,只是利用他们的图形框架,写自己的应用程序。
    • 如果还觉得舒服的话,写Eclipse集成开发环境的插件。
  22. 本地/外语接口

    学习一下Java Native Interface(JNI),试着写一个Java和C语言混合编程的程序。

    • 如果觉得不舒服了或者觉得欲仙欲死,就学一学Java Native Access(JNA),试一试不用任何胶水代码而从Java直接装载C库,直接调用C函数。
    • 如果连JNA也懒得学,就学一学SWIG,自动生成绑定。
    • 如果觉得舒服,就学一学Java Virtual Machine Tooling Interface(JVMTI),用C程序来监视JVM的状态。
  23. 密码学

    学一学密码学,包括编码、密码分析、攻击、对称密钥、公钥系统、数字签名、哈希算法等,看看Java有没有实现。

    • 如果觉得有点不舒服(你应该不会觉得舒服吧,除非你是学密码学的,要不然总会觉得自己写的程序有安全漏洞),就写一个“人品计算器”来放松一下,要求每次输入同一个姓名,得到的人品值是固定的,但又要让人无法用别人的人品值猜自己的人品值。
  24. 移动终端

    学一学Android开发。

    • 如果有精力的话,看看Dalvik虚拟机是怎么回事。
    • 建议买一个iPhone或者iPad,或许你再也不想用Android手机或者平板了。
  25. 历史

    如果觉得有些无聊,就去挖一挖历史上比较火的可能和Java相关技术,比如:

    • Applet,想想它比起html5+css3+javascript的缺点在哪里。
    • AWT、Swing,想想为什么很少有人用Java写图形界面程序。你觉得Swing的程序看上去舒服吗?中国人和残疾人喜欢用Swing程序吗?
    • JNDI,想想它比起Spring Bean Container的缺点在哪里。
    • JSP,想想它比起MVC结构的缺点在哪里。
    • WSDL/SOAP,把它们和XML-RPC、RESTful Web Service比较一下。
    • XSLT,以及为什么它是图灵完备的。可是它真的比Java本身更好用吗?
    • Log4j、java.util.logging、Apache Commons Logging,各自有什么问题,以及Log4j的作者本人为什么又开发了SLF4j和Logback?
    • Java最早是为什么设计的?
    • Type erasure是怎么回事?为什么ArrayList<int>不行但ArrayList<Integer>就可以?挖一挖历史。

其实Java不算完全面向对象的语言。Java更偏实用性,很多控制流(if语句、while循环、for循环等)来自面向过程的语言;基本数据类型(int, char, double等)也不是对象。但另一些语言,比如SmallTalk,更偏向纯粹的面向对象的设计,包括基本的数据类型都是对象,if/while/for等也用对象和方法来实现。比如:

基本数据类型也是对象,可以接受消息(即方法),比如:

(a + b) sqrt

这里面,a+b其实是向a发送“+”消息,参数是b。sqrt也是一个消息,发给一个数。

if分支是这样做的:

(x < y) ifTrue: [ 
       max := y. 
       i := j 
     ] ifFalse: [ 
       max := x. 
       i := k 
     ]

ifTrue:ifFalse: 是一个Boolean对象的一个方法,取两个参数,每个是一个“块”,分别在真和假的情况下执行。

还有while循环是这样做的:

[i < 100] whileTrue: [ 
       sum := sum + i. 
       i := i + 1 
     ]

whileTrue是“块”的一个方法,每次对块求值,如果是真,就反复执行第一个参数(也是“块”)。

所以,相对其他面向对象的语言,Java并不算很“面向对象”。所以需要补充一些对面向对象语言的了解。

文/Jabari(简书作者)
原文链接:http://www.jianshu.com/p/d51551b0a8ba
著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。

dubbo系列三—架构

对于架构,我们将从两个层面来理解,一个是屏蔽了细节的使用层面,第二个是关注细节的实现层面。一个外在架构,一个内在的架构,如果我们仅仅是理解下并使用下,那么了解下外在架构就差不多了。而如果需要深入学习使用那么,仅仅了解外在是不够的,我们需要足够多的细节。

外在架构

image

dubbo 主要由三部分组成,服务提供方,服务消费方,注册中心。这是核心的部分,然后是一些外围系统诸如管理,监控等。

Provider :通过容器加载起来服务,然后通过协议将服务注册到注册中心,然后就等待消费方通过预订的协议来调用。

Consumer:消费方也需要向服务注册中心订阅服务,等注册中心将服务信息推送过来之后,消费方就可以透明的通过代理接口通过制定协议及序列化调用服务,并且服务可以是集群的。

Register:注册中心管理服务接口。

更加详细的流程见下图:

image

总结起来dubbo就是个集中管理的分布式服务框架。

架构分层

上述外在架构模型是相对直观,但是其呈现的实现细节较少,现在就来深入的看看其具体实现.

其实不管架构如何变化,其实现目前来说总是脱离不了如下几层:

核心:从上到下依次 1.暴露出来的业务服务接口 2.可选协议的(集群)远程调用3.封装好的网络通讯。

周边:1.服务接口配置管理 2. 服务治理及监控

外在框架其实会把服务接口这一层给讲明白了,同时附带了周边的内容。那么我们就详细看下其具体的分层结构及相互关系:

image

dubbo,框架的10层中分别提供了各自需要关心和扩展的接口,且可灵活的替换对接而不受影响。我们就只将核心的层进行下说明,其他层可以根据官方文档去理解,我们知道核心就是RPC调用及通讯,protocol 就是最核心的那一层,当然我们还要关心集群的实现以及网络通讯。

protocol: 封装了RPC调用,以Invocation和Result为中心,扩展接口为Protocol、Invoker和Exporter。Protocol是服务域,它是Invoker暴露和引用的主功能入口,它负责Invoker的生命周期管理。Invoker是实体域,它是Dubbo的核心模型,其它模型都向它靠扰,或转换成它,它代表一个可执行体,可向它发起invoke调用,它有可能是一个本地的实现,也可能是一个远程的实现,也可能一个集群实现。

transport:抽象mina和netty为统一接口,以Message为中心,扩展接口为Channel、Transporter、Client、Server和Codec。可通过hession,dubbo协议进行序列化通信。

然后我们来看下远程调用的详细过程:

image

dubbo系列一—dubbo-admin

dubbo是个分布式带有服务治理的服务框架,提供高性能的的RPC远程服务调用方案。是阿里巴巴开源的SOA核心框架。学习dubbo最快的上手方式我觉得是先学习其提供的基本例子,而dubbo-admin 就是部署管理这些dubbo服务的,可以提供我们最直观的感受。学习dubbo-admin就只要学习其安装及使用吧。同时zookeeper 作为注册中心为dubbo 提供高可用分布式集群。同时也是dubbo-admin提供管理服务的必要组件。

安装zookeeper

http://ibinguo.net/2014/12/28/zookeeper%E5%AE%89%E8%A3%85%E9%85%8D%E7%BD%AE/

安装dubbo-admin

诸如dubbo官方的帮助文档进行安装,失败了,于是我就想直接下载源码编译好之后安装,发现了如下错误:

ERROR context.ContextLoader - Context initialization failed

经过查询https://github.com/alibaba/dubbo/issues/50,发现我的TOMCAT8,jdk8太新的缘故,最后也找到了解决方式:

1、webx的依赖改为3.1.6版;

    <dependency>
        <groupId>com.alibaba.citrus</groupId>
        <artifactId>citrus-webx-all</artifactId>
        <version>3.1.6</version>
    </dependency>

2、添加velocity的依赖,我用了1.7;

    <dependency>
        <groupId>org.apache.velocity</groupId>
        <artifactId>velocity</artifactId>
        <version>1.7</version>
    </dependency>

3、对依赖项dubbo添加exclusion,避免引入旧spring

    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>dubbo</artifactId>
        <version>${project.parent.version}</version>
        <exclusions>
            <exclusion>
                <groupId>org.springframework</groupId>
                <artifactId>spring</artifactId>
            </exclusion>
        </exclusions>
    </dependency>

4.修改项目属性

image

即可编译完成然后启动完成,当然启动dubbo-admin 前要先启动 zookeeper.

同时也修改了dubbo-admin的监听端口,因为跟zookeeper 的重复了,image

zookeeper安装配置

zookeeper简单的安装配置

准备

新建一个运行用户zookeeper,然后下载zookeeper的稳定版本3.4.5上传到zookeeper用户下,修改环境变量:

[bath]ZOOKEEPER_HOME=$HOME/zookeeper-3.4.5; export ZOOKEEPER_HOME PATH=$PATH:$ZOOKEEPER_HOME/bin:$ZOOKEEPER_HOME/conf;export PATH[/bath]

修改配置

添加配置zoo.cfg

[bath] mv conf/zoo_sample.cfg conf/zoo.cfg[/bath]

# The number of milliseconds of each tick #心跳 tickTime=2000 # The number of ticks that the initial # synchronization phase can take #最长心跳失败次数 initLimit=10 # The number of ticks that can pass between # sending a request and getting an acknowledgement #集群同步响应时间 syncLimit=5 # the directory where the snapshot is stored. # do not use /tmp for storage, /tmp here is just # example sakes. #数据目录 dataDir=/tmp/zookeeper # the port at which the clients will connect #监听端口/连接端口 clientPort=2181 # # Be sure to read the maintenance section of the # administrator guide before turning on autopurge. # # http://zookeeper.apache.org/doc/current/zookeeperAdmin.html#sc_maintenance # # The number of snapshots to retain in dataDir #autopurge.snapRetainCount=3 # Purge task interval in hours # Set to "0" to disable auto purge feature #autopurge.purgeInterval=1

启动

服务端

./zdServer.sh start

客户端

./bin/zkCli.sh -server 127.0.0.1:2181

客户端启动后可以 输入 help 查询相关的命令进行操作

关闭

服务端

./bin/zdServer.sh stop

zookeeper使用场景

zookeeper使用场景

场景一:有一组服务器向客户端提供某种服务(例如:我前面做的分布式网站的服务端,就是由四台服务器组成的集群,向前端集群提供服务),我们希望客户端每次请求服务端都可以找到服务端集群中某一台服务器,这样服务端就可以向客户端提供客户端所需的服务。对于这种场景,我们的程序中一定有一份这组服务器的列表,每次客户端请求时候,都是从这份列表里读取这份服务器列表。那么这分列表显然不能存储在一台单节点的服务器上,否则这个节点挂掉了,整个集群都会发生故障,我们希望这份列表时高可用的。高可用的解决方案是:这份列表是分布式存储的,它是由存储这份列表的服务器共同管理的,如果存储列表里的某台服务器坏掉了,其他服务器马上可以替代坏掉的服务器,并且可以把坏掉的服务器从列表里删除掉,让故障服务器退出整个集群的运行,而这一切的操作又不会由故障的服务器来操作,而是集群里正常的服务器来完成。这是一种主动的分布式数据结构,能够在外部情况发生变化时候主动修改数据项状态的数据机构。Zookeeper框架提供了这种服务。这种服务名字就是:统一命名服务,它和javaEE里的JNDI服务很像。

场景二:分布式锁服务。当分布式系统操作数据,例如:读取数据、分析数据、最后修改数据。在分布式系统里这些操作可能会分散到集群里不同的节点上,那么这时候就存在数据操作过程中一致性的问题,如果不一致,我们将会得到一个错误的运算结果,在单一进程的程序里,一致性的问题很好解决,但是到了分布式系统就比较困难,因为分布式系统里不同服务器的运算都是在独立的进程里,运算的中间结果和过程还要通过网络进行传递,那么想做到数据操作一致性要困难的多。Zookeeper提供了一个锁服务解决了这样的问题,能让我们在做分布式数据运算时候,保证数据操作的一致性。

场景三:配置管理。在分布式系统里,我们会把一个服务应用分别部署到n台服务器上,这些服务器的配置文件是相同的(例如:我设计的分布式网站框架里,服务端就有4台服务器,4台服务器上的程序都是一样,配置文件都是一样),如果配置文件的配置选项发生变化,那么我们就得一个个去改这些配置文件,如果我们需要改的服务器比较少,这些操作还不是太麻烦,如果我们分布式的服务器特别多,比如某些大型互联网公司的hadoop集群有数千台服务器,那么更改配置选项就是一件麻烦而且危险的事情。这时候zookeeper就可以派上用场了,我们可以把zookeeper当成一个高可用的配置存储器,把这样的事情交给zookeeper进行管理,我们将集群的配置文件拷贝到zookeeper的文件系统的某个节点上,然后用zookeeper监控所有分布式系统里配置文件的状态,一旦发现有配置文件发生了变化,每台服务器都会收到zookeeper的通知,让每台服务器同步zookeeper里的配置文件,zookeeper服务也会保证同步操作原子性,确保每个服务器的配置文件都能被正确的更新。

场景四:为分布式系统提供故障修复的功能。集群管理是很困难的,在分布式系统里加入了zookeeper服务,能让我们很容易的对集群进行管理。集群管理最麻烦的事情就是节点故障管理,zookeeper可以让集群选出一个健康的节点作为master,master节点会知道当前集群的每台服务器的运行状况,一旦某个节点发生故障,master会把这个情况通知给集群其他服务器,从而重新分配不同节点的计算任务。Zookeeper不仅可以发现故障,也会对有故障的服务器进行甄别,看故障服务器是什么样的故障,如果该故障可以修复,zookeeper可以自动修复或者告诉系统管理员错误的原因让管理员迅速定位问题,修复节点的故障。大家也许还会有个疑问,master故障了,那怎么办了?zookeeper也考虑到了这点,zookeeper内部有一个“选举领导者的算法”,master可以动态选择,当master故障时候,zookeeper能马上选出新的master对集群进行管理。

web框架基础实现介绍二—Spring

现今,JAVA系的WEB框架基本都已Spring为基础,即使不是直接拿Spring来用,那么也只是换种方式而已。

组成

前面一篇已经基本可以知道Spring的功效:简单说,微内核的IOC框架。

                             image

上层的特性的功能虽然是外围的功能,其实是我们最关心最常用到的功能,经常我们只是按一些教程配置一下然后就能让这些功能开始工作了。但如果只是使用的话我们会对他们如何实现如何一起工作不是很了解,虽然能使用,但是不理解的话就不能举一反三。

再看看底下是核心的几个模块,core是基础支持模块。Context一般来说也是就用基本配置使用,除非有比较深入的使用。Beans是这个框架思想核心中的核心部分,基本上我们都是冲这个来的,因为它是实现IOC的基础,Spring 正是通过把对象包装在 Bean 中而达到对这些对象管理以及一些列额外操作的目的。接下来我们仔细看看这三个核心的模块是如何支撑起SPRING的。

                                 image

关系

bean由beanfactory创建,同时context 继承了beanfactory,同时也继承了core中可以读取配置文件的Resource资源接口,所以根据配置文件,context就可以创建加载各种功能beans了。

直接上图:imageimage

                                         image

https://www.ibm.com/developerworks/cn/java/j-lo-spring-principle/

web框架基础实现介绍一—开篇

其实在以前写网络编程大并发实战的时候就已经讲过IO框架部分,而本次讲的web框架只是把IO收到之后的业务应用处理的框架加进去。

总框架

万变不离其宗,当前框架总体 IO连接处理+业务处理这样的模式。如果是分布式,那么还会加上路由,集群,负载均衡等基础模块,而基于管理方便考虑还会加上配置管理,服务治理等周边模块。本次我们的介绍会屏蔽这些周边东西,直击比较底层的本质。如果要了解这块内容,可以去看看dubbo框架。

                                           image

在这个基础上,目前市面上的成品WEB服务器,一般又会细分出两个,一个是偏向处理连接web服务器如appache、nginx,还一类就是带连接,主要作为应用处理容器的应用服务器如jetty 、tomcat,当前我们要说的是变向后者。而在JAVA系中,作为应用处理的一个核心关键概念就是servlet,那么我们把上面这个图扩展下,就可以比较清晰的了解到这之间的相互关系及各自在这个web框架中的位置作用。

                                       image

左边部分即为tomcat,jetty之类的应用服务,主要功能其实偏向装载servlet的容器,servlet在JAVA中就是处理请求应答业务的模块,而其 connector模块为其弱点,所以一些追求高性能的后台服务就自己搞connector,以NIO,AIO为基础,netty是当前高并发架构后台服务connector常用的NIO框架。同时我们还有右边servlet部分,当然servlet就是处理请求应答的一个东西,接口虽然一致了,但是实现还是有多种多样,所以很多时候servlet也有实现好的基本款供选择,请求的解析,应答的封装这些都帮你搞定了,那么你就可以只专注业务就好了。而阿里的开源框架DUBBO就是基本给你实现了上图中的所有功能。你们只需要写你自己的业务接口服务。

spring

还是得说说spring。我们知道各个部件都准备好了,总得把他们放在一起组装起来——这个其实还是简单的,那么接下来的一个问题,我们还想把各个部件灵活替换——即把相互之间的依赖关系解耦,那么spring这个框架就是这么个功效。当你把一部大炮准备好了之后,你发觉炮管短小,威力不足,OK,通过spring你可以随时很方便的替换上强有力的炮管,威力加强而不影响其他人。这是spring 核心的作用,这也是为什么不管啥框架,都会把他放到spring 上(至少兼容)组装的原因。以 spring为中心,组合上各个后台功能模块,加上合理的设计就组成了我们各式各样的web架构。

                                                 image

Linux下高并发最大连接数限制及解决

转自 http://blog.sae.sina.com.cn/archives/1988

1、修改用户进程可打开文件数限制
在Linux平台上,无论编写客户端程序还是服务端程序,在进行高并发TCP连接处理时,最高的并发数量都要受到系统对用户单一进程同时可打开文件数量的限制(这是因为系统为每个TCP连接都要创建一个socket句柄,每个socket句柄同时也是一个文件句柄)。可使用ulimit命令查看系统允许当前用户进程打开的文件数限制:

[speng@as4 ~]$ ulimit -n
1024

这表示当前用户的每个进程最多允许同时打开1024个文件,这1024个文件中还得除去每个进程必然打开的标准输入,标准输出,标准错误,服务器监听 socket,进程间通讯的unix域socket等文件,那么剩下的可用于客户端socket连接的文件数就只有大概1024-10=1014个左右。也就是说缺省情况下,基于Linux的通讯程序最多允许同时1014个TCP并发连接。

对于想支持更高数量的TCP并发连接的通讯处理程序,就必须修改Linux对当前用户的进程同时打开的文件数量的软限制(soft limit)和硬限制(hardlimit)。其中软限制是指Linux在当前系统能够承受的范围内进一步限制用户同时打开的文件数;硬限制则是根据系统硬件资源状况(主要是系统内存)计算出来的系统最多可同时打开的文件数量。通常软限制小于或等于硬限制。
修改上述限制的最简单的办法就是使用ulimit命令:

[speng@as4 ~]$ ulimit -n

上述命令中,在中指定要设置的单一进程允许打开的最大文件数。如果系统回显类似于“Operation notpermitted”之类的话,说明上述限制修改失败,实际上是因为在中指定的数值超过了Linux系统对该用户打开文件数的软限制或硬限制。因此,就需要修改Linux系统对用户的关于打开文件数的软限制和硬限制。
第一步,修改/etc/security/limits.conf文件,在文件中添加如下行:

speng soft nofile 10240
speng hard nofile 10240

其中speng指定了要修改哪个用户的打开文件数限制,可用’*’号表示修改所有用户的限制;soft或hard指定要修改软限制还是硬限制;10240则指定了想要修改的新的限制值,即最大打开文件数(请注意软限制值要小于或等于硬限制)。修改完后保存文件。
第二步,修改/etc/pam.d/login文件,在文件中添加如下行:

session required /lib/security/pam_limits.so

这是告诉Linux在用户完成系统登录后,应该调用pam_limits.so模块来设置系统对该用户可使用的各种资源数量的最大限制(包括用户可打开的最大文件数限制),而pam_limits.so模块就会从/etc/security/limits.conf文件中读取配置来设置这些限制值。修改完后保存此文件。
第三步,查看Linux系统级的最大打开文件数限制,使用如下命令:

[speng@as4 ~]$ cat /proc/sys/fs/file-max
12158

这表明这台Linux系统最多允许同时打开(即包含所有用户打开文件数总和)12158个文件,是Linux系统级硬限制,所有用户级的打开文件数限制都不应超过这个数值。通常这个系统级硬限制是Linux系统在启动时根据系统硬件资源状况计算出来的最佳的最大同时打开文件数限制,如果没有特殊需要,不应该修改此限制,除非想为用户级打开文件数限制设置超过此限制的值。修改此硬限制的方法是修改/etc/rc.local脚本,在脚本中添加如下行:

echo 22158 > /proc/sys/fs/file-max

这是让Linux在启动完成后强行将系统级打开文件数硬限制设置为22158。修改完后保存此文件。
完成上述步骤后重启系统,一般情况下就可以将Linux系统对指定用户的单一进程允许同时打开的最大文件数限制设为指定的数值。如果重启后用 ulimit-n命令查看用户可打开文件数限制仍然低于上述步骤中设置的最大值,这可能是因为在用户登录脚本/etc/profile中使用ulimit -n命令已经将用户可同时打开的文件数做了限制。由于通过ulimit-n修改系统对用户可同时打开文件的最大数限制时,新修改的值只能小于或等于上次 ulimit-n设置的值,因此想用此命令增大这个限制值是不可能的。所以,如果有上述问题存在,就只能去打开/etc/profile脚本文件,在文件中查找是否使用了ulimit-n限制了用户可同时打开的最大文件数量,如果找到,则删除这行命令,或者将其设置的值改为合适的值,然后保存文件,用户退出并重新登录系统即可。
通过上述步骤,就为支持高并发TCP连接处理的通讯处理程序解除关于打开文件数量方面的系统限制。
2、修改网络内核对TCP连接的有关限制(参考对比下篇文章“优化内核参数”)
在Linux上编写支持高并发TCP连接的客户端通讯处理程序时,有时会发现尽管已经解除了系统对用户同时打开文件数的限制,但仍会出现并发TCP连接数增加到一定数量时,再也无法成功建立新的TCP连接的现象。出现这种现在的原因有多种。
第一种原因可能是因为Linux网络内核对本地端口号范围有限制。此时,进一步分析为什么无法建立TCP连接,会发现问题出在connect()调用返回失败,查看系统错误提示消息是“Can’t assign requestedaddress”。同时,如果在此时用tcpdump工具监视网络,会发现根本没有TCP连接时客户端发SYN包的网络流量。这些情况说明问题在于本地Linux系统内核中有限制。其实,问题的根本原因在于Linux内核的TCP/IP协议实现模块对系统中所有的客户端TCP连接对应的本地端口号的范围进行了限制(例如,内核限制本地端口号的范围为1024~32768之间)。

当系统中某一时刻同时存在太多的TCP客户端连接时,由于每个TCP客户端连接都要占用一个唯一的本地端口号(此端口号在系统的本地端口号范围限制中),如果现有的TCP客户端连接已将所有的本地端口号占满,则此时就无法为新的TCP客户端连接分配一个本地端口号了,因此系统会在这种情况下在connect()调用中返回失败,并将错误提示消息设为“Can’t assignrequested address”。有关这些控制逻辑可以查看Linux内核源代码,以linux2.6内核为例,可以查看tcp_ipv4.c文件中如下函数:

static int tcp_v4_hash_connect(struct sock *sk)

请注意上述函数中对变量sysctl_local_port_range的访问控制。变量sysctl_local_port_range的初始化则是在tcp.c文件中的如下函数中设置:

void __init tcp_init(void)

内核编译时默认设置的本地端口号范围可能太小,因此需要修改此本地端口范围限制。
第一步,修改/etc/sysctl.conf文件,在文件中添加如下行:

net.ipv4.ip_local_port_range = 1024 65000

这表明将系统对本地端口范围限制设置为1024~65000之间。请注意,本地端口范围的最小值必须大于或等于1024;而端口范围的最大值则应小于或等于65535。修改完后保存此文件。
第二步,执行sysctl命令:

[speng@as4 ~]$ sysctl -p

如果系统没有错误提示,就表明新的本地端口范围设置成功。如果按上述端口范围进行设置,则理论上单独一个进程最多可以同时建立60000多个TCP客户端连接。

第二种无法建立TCP连接的原因可能是因为Linux网络内核的IP_TABLE防火墙对最大跟踪的TCP连接数有限制。此时程序会表现为在 connect()调用中阻塞,如同死机,如果用tcpdump工具监视网络,也会发现根本没有TCP连接时客户端发SYN包的网络流量。由于 IP_TABLE防火墙在内核中会对每个TCP连接的状态进行跟踪,跟踪信息将会放在位于内核内存中的conntrackdatabase中,这个数据库的大小有限,当系统中存在过多的TCP连接时,数据库容量不足,IP_TABLE无法为新的TCP连接建立跟踪信息,于是表现为在connect()调用中阻塞。此时就必须修改内核对最大跟踪的TCP连接数的限制,方法同修改内核对本地端口号范围的限制是类似的:
第一步,修改/etc/sysctl.conf文件,在文件中添加如下行:

net.ipv4.ip_conntrack_max = 10240

这表明将系统对最大跟踪的TCP连接数限制设置为10240。请注意,此限制值要尽量小,以节省对内核内存的占用。

第二步,执行sysctl命令:

[speng@as4 ~]$ sysctl -p

如果系统没有错误提示,就表明系统对新的最大跟踪的TCP连接数限制修改成功。如果按上述参数进行设置,则理论上单独一个进程最多可以同时建立10000多个TCP客户端连接。

3、使用支持高并发网络I/O的编程技术
在Linux上编写高并发TCP连接应用程序时,必须使用合适的网络I/O技术和I/O事件分派机制。
可用的I/O技术有同步I/O,非阻塞式同步I/O(也称反应式I/O),以及异步I/O。在高TCP并发的情形下,如果使用同步I/O,这会严重阻塞程序的运转,除非为每个TCP连接的I/O创建一个线程。但是,过多的线程又会因系统对线程的调度造成巨大开销。因此,在高TCP并发的情形下使用同步 I/O是不可取的,这时可以考虑使用非阻塞式同步I/O或异步I/O。非阻塞式同步I/O的技术包括使用select(),poll(),epoll等机制。异步I/O的技术就是使用AIO。
从I/O事件分派机制来看,使用select()是不合适的,因为它所支持的并发连接数有限(通常在1024个以内)。如果考虑性能,poll()也是不合适的,尽管它可以支持的较高的TCP并发数,但是由于其采用“轮询”机制,当并发数较高时,其运行效率相当低,并可能存在I/O事件分派不均,导致部分TCP连接上的I/O出现“饥饿”现象。而如果使用epoll或AIO,则没有上述问题(早期Linux内核的AIO技术实现是通过在内核中为每个 I/O请求创建一个线程来实现的,这种实现机制在高并发TCP连接的情形下使用其实也有严重的性能问题。但在最新的Linux内核中,AIO的实现已经得到改进)。
综上所述,在开发支持高并发TCP连接的Linux应用程序时,应尽量使用epoll或AIO技术来实现并发的TCP连接上的I/O控制,这将为提升程序对高并发TCP连接的支持提供有效的I/O保证。

内核参数sysctl.conf的优化

/etc/sysctl.conf 是用来控制linux网络的配置文件,对于依赖网络的程序(如web服务器和cache服务器)非常重要,RHEL默认提供的最好调整。

推荐配置(把原/etc/sysctl.conf内容清掉,把下面内容复制进去):

net.ipv4.ip_local_port_range = 1024 65536
net.core.rmem_max=16777216
net.core.wmem_max=16777216
net.ipv4.tcp_rmem=4096 87380 16777216
net.ipv4.tcp_wmem=4096 65536 16777216
net.ipv4.tcp_fin_timeout = 10
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_timestamps = 0
net.ipv4.tcp_window_scaling = 0
net.ipv4.tcp_sack = 0
net.core.netdev_max_backlog = 30000
net.ipv4.tcp_no_metrics_save=1
net.core.somaxconn = 262144
net.ipv4.tcp_syncookies = 0
net.ipv4.tcp_max_orphans = 262144
net.ipv4.tcp_max_syn_backlog = 262144
net.ipv4.tcp_synack_retries = 2
net.ipv4.tcp_syn_retries = 2

这个配置参考于cache服务器varnish的推荐配置和SunOne 服务器系统优化的推荐配置。

varnish调优推荐配置的地址为:http://varnish.projects.linpro.no/wiki/Performance

不过varnish推荐的配置是有问题的,实际运行表明“net.ipv4.tcp_fin_timeout = 3”的配置会导致页面经常打不开;并且当网友使用的是IE6浏览器时,访问网站一段时间后,所有网页都会打不开,重启浏览器后正常。可能是国外的网速快吧,我们国情决定需要调整“net.ipv4.tcp_fin_timeout = 10”,在10s的情况下,一切正常(实际运行结论)。

修改完毕后,执行:

/sbin/sysctl -p /etc/sysctl.conf
/sbin/sysctl -w net.ipv4.route.flush=1

命令生效。为了保险起见,也可以reboot系统。

调整文件数:
linux系统优化完网络必须调高系统允许打开的文件数才能支持大的并发,默认1024是远远不够的。

执行命令:

Shell代码
echo ulimit -HSn 65536 >> /etc/rc.local
echo ulimit -HSn 65536 >>/root/.bash_profile
ulimit -HSn 65536