发表于: 2019-10-17 22:44:08
1 1352
一、今天完成的事
把项目中的web、service分离
server1
.png)
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
.png)
加入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,找了半天没没解决
.png)
二、遇到的问题
三、收获
什么是分布式系统?
要理解分布式系统,主要需要明白一下2个方面:
1.分布式系统一定是由多个节点组成的系统。
其中,节点指的是计算机服务器,而且这些节点一般不是孤立的,而是互通的。
2.这些连通的节点上部署了我们的节点,并且相互的操作会有协同。
分布式系统对于用户而言,他们面对的就是一个服务器,提供用户需要的服务而已,而实际上这些服务是通过背后的众多服务器组成的一个分布式系统,因此分布式系统看起来像是一个超级计算机一样。
例如淘宝,平时大家都会使用,它本身就是一个分布式系统,我们通过浏览器访问淘宝网站时,这个请求的背后就是一个庞大的分布式系统在为我们提供服务,整个系统中有的负责请求处理,有的负责存储,有的负责计算,最终他们相互协调把最后的结果返回并呈现给用户。
.png)
使用分布式系统主要有特点:
1.增大系统容量。 我们的业务量越来越大,而要能应对越来越大的业务量,一台机器的性能已经无法满足了,我们需要多台机器才能应对大规模的应用场景。所以,我们需要垂直或是水平拆分业务系统,让其变成一个分布式的架构。
2.加强系统可用。 我们的业务越来越关键,需要提高整个系统架构的可用性,这就意味着架构中不能存在单点故障。这样,整个系统不会因为一台机器出故障而导致整体不可用。所以,需要通过分布式架构来冗余系统以消除单点故障,从而提高系统的可用性。
3.因为模块化,所以 系统模块重用度更高
4.因为软件服务模块被拆分,开发和发布速度可以并行而变得更快
5.系统扩展性更高
6.团队协作流程也会得到改善
分布式系统的类型有三种:
1.分布式处理,但只有一个总数据库,没有局部数据库
2.分层式处理,每一层都有自己的数据库
3.充分分散的分布式网络,没有中央控制部分,各节点之间的联系方式又可以有多种,如松散的联接,紧密的联接,动态的联接,广播通知式的联接等
什么是 JAVA 分布式应用?
一个大型的系统往往被分为几个子系统来做,一个子系统可以部署在一台机器的多个 JVM 上,也可以部署在多台机器上。但是每一个系统不是独立的,不是完全独立的。需要相互通信,共同实现业务功能。
一句话来说:分布式就是通过计算机网络将后端工作分布到多台主机上,多个主机一起协同完成工作。
实现分布式主要的方式
分布式应用用到的技术: 网络通信,基于消息方式的系统间通信和基于远程调用的系统间通信。
缺点: 就是会增加技术的复杂度。
基于消息的系统通信方式,主要是利用的网络协议,比如 TCP/IP 协议。
系统间的通信还需要对数据进行处理,比如同步 IO 和异步 IO。
远程调用实现系统间的通信:通过调用本地的java接口的方法来透明的调用远程java的实现。具体的细节有框架来实现。
.png)
基于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。
四、明天的计划
评论