发表于: 2019-10-17 22:44:08

1 1352


一、今天完成的事

把项目中的web、service分离
server1

applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-4.0.xsd">
    <!-- 加载配置文件 -->
    <context:property-placeholder location="classpath:/db.properties"/>
    <context:component-scan base-package="com.ksy"/>
    <bean id="userServiceImpl" class="com.ksy.service.serviceImpl.UserServiceImpl"/>
    <!-- 将一个类发布为一个RMI服务 -->
    <bean id="user" class="org.springframework.remoting.rmi.RmiServiceExporter">
        <!--此处的name是决定helloWorld类中的那个参数,ref是指bean配置文件中的bean名称-->
        <property name="service" ref="userServiceImpl"/>
        <property name="serviceName" value="user"/>
        <property name="serviceInterface" value="com.ksy.service.serviceImpl.UserServiceImpl"/>
        <property name="registryPort" value="8888"/>
    </bean>
    <bean id="studentServiceImpl" class="com.ksy.service.serviceImpl.StudentServiceImpl"/>
    <bean id="student" class="org.springframework.remoting.rmi.RmiServiceExporter">
        <!--此处的name是决定helloWorld类中的那个参数,ref是指bean配置文件中的bean名称-->
        <property name="service" ref="studentServiceImpl"/>
        <property name="serviceName" value="student"/>
        <property name="serviceInterface" value="com.ksy.service.serviceImpl.StudentServiceImpl"/>
        <property name="registryPort" value="8888"/>
    </bean>
    <bean id="professionServiceImpl" class="com.ksy.service.serviceImpl.ProfessionServiceImpl"/>
    <bean id="profession" class="org.springframework.remoting.rmi.RmiServiceExporter">
        <!--此处的name是决定helloWorld类中的那个参数,ref是指bean配置文件中的bean名称-->
        <property name="service" ref="professionServiceImpl"/>
        <property name="serviceName" value="profession"/>
        <property name="serviceInterface" value="com.ksy.service.serviceImpl.ProfessionServiceImpl"/>
        <property name="registryPort" value="8803"/>
    </bean>
    <!--配置数据源-->
    <bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close">
        <property name="driverClassName" value="${jdbc.driver}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.name}"/>
        <property name="password" value="${jdbc.password}"/>
        <property name="maxTotal" value="${jdbc.maxActive}"/>
        <property name="maxWaitMillis" value="${jdbc.maxWait}"/>
        <property name="maxIdle" value="${jdbc.maxIdle}"/>
    </bean>
    <!--mybatis与spring的整合,不需要mybatis自己的配置映射文件-->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <!--配置连接数据库数据源-->
        <property name="dataSource" ref="dataSource"/>
        <!--配置Mapper文件所在位置-->
        <property name="mapperLocations" value="classpath:mapper/*.xml"/>
        <!--mybatis打印sql语句-->
        <property name="configLocation" value="classpath:mybatis-config.xml"></property>
    </bean>
    <!--Dao接口所在包名,spring会扫描basePackage并自动装配-->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="cn.wp.dao"/>
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
    </bean>
    <!--service层扫描-->
    <context:component-scan base-package="com.ksy.service"/>
    <bean id="memcachedPool" class="com.danga.MemCached.SockIOPool"
          factory-method="getInstance" init-method="initialize" destroy-method="shutDown">
        <constructor-arg value="neeaMemcachedPool"/>
        <!-- 可以配置多服务器负载均衡 -->
        <property name="servers">
            <list>
                <value>127.0.0.1:11211</value>
            </list>
        </property>
        <!-- 初始连接数 -->
        <property name="initConn" value="20"/>
        <!-- 最小连接数 -->
        <property name="minConn" value="10"/>
        <!-- 最大连接数 -->
        <property name="maxConn" value="100"/>
        <!-- 连接池守护线程的睡眠时间 -->
        <property name="maintSleep" value="3000"/>
        <property name="nagle" value="false"/>
        <property name="socketTO" value="3000"/>
    </bean>
    <bean id="memcachedClient" class="com.danga.MemCached.MemCachedClient">
        <constructor-arg value="neeaMemcachedPool"/>
    </bean>
</beans>
修改掉原项目中的serviceImpl

加入server配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd">
    <!--客户端一-->
    <bean id="user" class="org.springframework.remoting.rmi.RmiProxyFactoryBean">
        <property name="serviceInterface" value="com.ksy.service.UserService"/>
        <property name="serviceUrl" value="rmi://127.0.0.1:8803/user"/>
    </bean>
    <bean id="student" class="org.springframework.remoting.rmi.RmiProxyFactoryBean">
        <property name="serviceInterface" value="com.ksy.service.StudentService"/>
        <property name="serviceUrl" value="rmi://127.0.0.1:8803/student"/>
    </bean>
    <bean id="profession" class="org.springframework.remoting.rmi.RmiProxyFactoryBean">
        <property name="serviceInterface" value="com.ksy.service.ProfessionService"/>
        <property name="serviceUrl" value="rmi://127.0.0.1:8803/profession"/>
    </bean>
</beans>
可惜报错了,没有成功启动server,找了半天没没解决
二、遇到的问题
三、收获

什么是分布式系统?

要理解分布式系统,主要需要明白一下2个方面:
1.分布式系统一定是由多个节点组成的系统。
其中,节点指的是计算机服务器,而且这些节点一般不是孤立的,而是互通的。
2.这些连通的节点上部署了我们的节点,并且相互的操作会有协同。
分布式系统对于用户而言,他们面对的就是一个服务器,提供用户需要的服务而已,而实际上这些服务是通过背后的众多服务器组成的一个分布式系统,因此分布式系统看起来像是一个超级计算机一样。
例如淘宝,平时大家都会使用,它本身就是一个分布式系统,我们通过浏览器访问淘宝网站时,这个请求的背后就是一个庞大的分布式系统在为我们提供服务,整个系统中有的负责请求处理,有的负责存储,有的负责计算,最终他们相互协调把最后的结果返回并呈现给用户。
使用分布式系统主要有特点:
    1.增大系统容量。 我们的业务量越来越大,而要能应对越来越大的业务量,一台机器的性能已经无法满足了,我们需要多台机器才能应对大规模的应用场景。所以,我们需要垂直或是水平拆分业务系统,让其变成一个分布式的架构。
    2.加强系统可用。 我们的业务越来越关键,需要提高整个系统架构的可用性,这就意味着架构中不能存在单点故障。这样,整个系统不会因为一台机器出故障而导致整体不可用。所以,需要通过分布式架构来冗余系统以消除单点故障,从而提高系统的可用性。
    3.因为模块化,所以 系统模块重用度更高
    4.因为软件服务模块被拆分,开发和发布速度可以并行而变得更快
    5.系统扩展性更高
    6.团队协作流程也会得到改善
分布式系统的类型有三种:
    1.分布式处理,但只有一个总数据库,没有局部数据库
    2.分层式处理,每一层都有自己的数据库
    3.充分分散的分布式网络,没有中央控制部分,各节点之间的联系方式又可以有多种,如松散的联接,紧密的联接,动态的联接,广播通知式的联接等
什么是 JAVA 分布式应用?
一个大型的系统往往被分为几个子系统来做,一个子系统可以部署在一台机器的多个 JVM 上,也可以部署在多台机器上。但是每一个系统不是独立的,不是完全独立的。需要相互通信,共同实现业务功能。
一句话来说:分布式就是通过计算机网络将后端工作分布到多台主机上,多个主机一起协同完成工作。
实现分布式主要的方式
分布式应用用到的技术: 网络通信,基于消息方式的系统间通信和基于远程调用的系统间通信。
缺点: 就是会增加技术的复杂度。
基于消息的系统通信方式,主要是利用的网络协议,比如 TCP/IP 协议。
系统间的通信还需要对数据进行处理,比如同步 IO 和异步 IO。
远程调用实现系统间的通信:通过调用本地的java接口的方法来透明的调用远程java的实现。具体的细节有框架来实现。
基于Java自身技术实现消息方式的系统间通信:
基于Java自身包实现消息方式的系统间通信的方式有:
TCP/IP+BIO、TCP/IP+NIO、UDP/IP+BIO以及UDP/IP+NIO 4种方式
TCP/IP+BIO 在 Java 中可基于 Socket、ServerSocket 来实现 TCP/IP+BIO 的系统间通信。
Socket 主要用于实现建立连接及网络 IO 的操作,ServerSocket 主要用于实现服务器端端口的监听及 Socket 对象的获取。
多个客户端访问服务器端的情况下,会遇到两个问题:建立多个 socket 的,占用过多的本地资源,服务器端要承受巨大的来访量;创建过多的 socket,占用过多的资源,影响性能。
通常解决这种问题的办法是,使用 连接池,既能限制连接的数量,又能避免创建的过程,可以很大的提高性的问题。缺点就是竞争量大的时候造成激烈的竞争和等待。需要注意的是,要设置超时时间,如果不这样的话,会造成无限制的等待。
为了解决这个问题,采用一连接一线程的方式,同时也会带来副作用,内存占用过多。
TCP/IP 异步通信: JAVA NIO 通道技术实现。

RMI与RPC的区别

  • RPC(Remote Procedure Call Protocol)远程过程调用协议,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。RPC不依赖于具体的网络传输协议,tcp、udp等都可以。
  • 由于存在各式各样的变换和细节差异,相应的RPC也派生出了各式远程过程通信协议。RPC是跨语言的通信标准,SUN和微软都有其实现,比如:RMI可以被看作SUN对RPC的Java版本(实现),而微软的DCOM就是建立在ORPC协议之上。
  • 一言以蔽之,RPC是协议,而无论是SUN的RMI还是微软的DCOM都是对该协议的不同实现,二者都为编程人员提供了应用PRC技术的程序接口(API)
  • 1、方法调用方式不同:
    • RMI调用方法,RMI中是通过在客户端的Stub对象作为远程接口进行远程方法的调用。每个远程方法都具有方法签名。如果一个方法在服务器上执行,但是没有相匹配的签名被添加到这个远程接口(stub)上,那么这个新方法就不能被RMI客户方所调用。
    • RPC调用函数,RPC中是通过网络服务协议向远程主机发送请求,请求包含了一个参数集和一个文本值,通常形成“classname.methodname(参数集)”的形式。这就向RPC服务器表明,被请求的方法在“classname”的类中,名叫“methodname”。然后RPC服务器就去搜索与之相匹配的类和方法,并把它作为那种方法参数类型的输入。这里的参数类型是与RPC请求中的类型是匹配的。一旦匹配成功,这个方法就被调用了,其结果被编码后通过网络协议发回。
  • 2、适用语言范围不同:
    • RMI只用于Java,支持传输对象。
    • RPC是基于C语言的,不支持传输对象,是网络服务协议,与操作系统和语言无关。
  • 3、调用结果的返回形式不同:
    • RMI是面向对象的,Java是面向对象的,所以RMI的调用结果可以是对象类型或者基本数据类型。
    • RPC的结果统一由外部数据表示(External Data Representation,XDR)语言表示,这种语言抽象了字节序类和数据类型结构之间的差异。只有由XDR定义的数据类型才能被传递,可以说RMI是面向对象方式的Java RPC。
四、明天的计划



返回列表 返回列表
评论

    分享到