参考博客:
小宝鸽:https://blog.csdn.net/u013142781/article/details/50387583
https://blog.csdn.net/u013142781/article/details/50396621
过滤器:https://blog.csdn.net/u014394255/article/details/53983685
参数:https://www.cnblogs.com/xrq730/p/5316805.html
架构:https://blog.csdn.net/hzzhoushaoyu/article/details/43273099
(对集群服务的)ZooKeeper分布式协调原理
同一个服务的多个节点,在该服务节点下创建临时节点,订阅者使用Watcher监控所有服务节点的字节点列表,新增则通知,故障则自动删除,也会通知(推),在通知回调里再主动拉取列表(拉)
Dubbo的远程服务调用
Spring容器根据Schema扩展解析dubbo标签,创建服务Bean,消费端则创建远程调用代理。服务端在容器启动时到注册中心注册服务信息。消费端只从注册中心获取可用服务端信息,使用负载均衡算法选取一个服务,然后直接调取服务,不走注册中心。采用hession等序列化,在连接上远程调用。实际是远端本地线程接收到连接上的远程参数,调用本地方法,返回结果。
部署dubbo-admin 2.5.4常见异常
Java1.8环境下异常
ERROR context.ContextLoader - Context initialization failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'uriBrokerService': Cannot create inner bean '(inner bean)' of type [com.alibaba.citrus.service.uribroker.impl.URIBrokerServiceImpl$URIBrokerInfo] while setting bean property 'brokers' with key [0]; nested excepti
on is org.springframework.beans.factory.BeanCreationException: Error creating bean with name '(inner bean)#25': Cannot create inner bean 'server' of type [com.alibaba.citrus.service.uribroker.uri.GenericURIBroker] while setting constructor argument; nested exception is org.springframework.beans.fact
ory.BeanCreationException: Error creating bean with name 'server': Error setting property values; nested exception is org.springframework.beans.NotWritablePropertyException: Invalid property 'URIType' of bean class [com.alibaba.citrus.service.uribroker.uri.GenericURIBroker]: Bean property 'URIType'
is not writable or has an invalid setter method. Does the parameter type of the setter match the return type of the getter?
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveInnerBean(BeanDefinitionValueResolver.java:230)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:122)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveManagedList(BeanDefinitionValueResolver.java:287)
解决办法:
方法1:
我使用的是JDK 1.8.0_05, dubbo-admin版本是2.5.4-SNAPSHOT,也遇到了一样的问题。解决方案如@ddatsh:
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、webx已有spring 3以上的依赖,因此注释掉dubbo-admin里面的spring依赖
<!--<dependency>-->
<!--<groupId>org.springframework</groupId>-->
<!--<artifactId>spring</artifactId>-->
<!--</dependency>-->
确定war包解压后lib目录没有spring 3 以下的依赖就行。然后运行正常了。
方法2:
或干脆把环境降级为jdk1.7(不推荐,我1.8按上述办法修改、运行成功了!!)
参考:
https://github.com/apache/incubator-dubbo/issues/50
https://blog.csdn.net/liutengteng130/article/details/47112683
https://blog.csdn.net/blue_dd/article/details/51298438
Maven编译(打包)dubbo-admin 2.5.4异常
[ERROR] Failed to execute goal on project dubbo-admin: Could not resolve dependencies for project com.alibaba:dubbo-admin:war:2.5.4-SNAPSHOT: Could not find artifact com.alibaba:dubbo:jar:2.5.4-SNAPSHOT -> [Help 1] [ERROR] [ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch. [ERROR] Re-run Maven using the -X switch to enable full debug logging. [ERROR] [ERROR] For more information about the errors and possible solutions, please read the following articles: [ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/DependencyResolutionException
原因是maven库里没有该dubbo的jar包
解决办法:
方法1:
到GitHub搜索dubbo 2.5.4整个工程(包含多个子工程,里面就有dubbo-admin)源码,按上述第一个异常修改其中dubbo-admin的pom.xml(为了在jdk1.8下运行不报错),再回到父工程dubbo带pom.xml的根目录执行,不用管中途各种异常,最后会成功。这样修改过的dubbo-admin也会直接打成war包,在其目录下找得到,直接拖到Tomcat下运行,成功。
方法2:
把dubbo-admin项目的pom.xml的
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>${project.parent.version}</version>
</dependency>
改为
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.5.3</version>
</dependency>
重新build即可!
参考:
https://blog.csdn.net/qq_26508409/article/details/78443915?fps=1&locationNum=2
https://blog.csdn.net/zsmissyou/article/details/62445899
https://www.cnblogs.com/xhkj/p/7407092.html
启动dubbo-admin
先启动ZooKeeper再使用Tomcat启动dubbo-admin,到解压的webapps目录找到dubbo-admin->WEB-INF下的dubbo.properties,查看默认用户密码,两个:root/root,和guest/guest
浏览器访问这个项目,输入这两个用户名/密码,成功!
普通Web工程改造为Dubbo服务化分布式工程思路
1.将业务逻辑层及以下的Dao层分离出单独Dubbo服务
a.仍使用Spring整合MyBatis,管理Service,Dao等Model实例的创建与注入
b.Spring主配置文件引入(import)provider.xml配置,用于启动Dubbo服务,因为Dubbo使用Spring的Schema扩展管理
c.可部署为普通工程或Web工程,启动Spring,这样就启动了Dubbo服务,Dubbo服务使用Spring创建服务实体,注入底层依赖,并向ZooKeeper注册服务
2.控制器层留在Web工程中,作为Dubbo消费者调用1中的服务
a.仍使用Spring配置,将Spring主配置文件引入(import)consumer.xml配置,在Web启动Spring时创建Dubbo远程服务代理,在控制器层注入代理,到ZooKeeper订阅所需服务(经测试,消费端是在第一次调用服务时,才访问注册中心,而不是在启动时),获取远程服务调用信息,调用服务时,在服务列表中使用负载均衡算法选取一台机器,如有变更,注册中心基于长连接通知消费端,消费端重新获取服务列表
b.Web工程和普通工程的本质区别,是前者通过Web服务器(Tomcat)启动Web服务(HTTP服务,底层是Socket监听),将URL映射为本地方法调用,这些方法是通过Servlet接口注册到Web服务器的。整合了Spring Web(SpringMVC)后,统一由一个Servlet处理(DispatcherServlet),按照Spring配置解析URL分发请求到Controller.这些Controller是从Spring容器获取并注入依赖的,而Spring容器是Servlet从ServletContext对象中获取的,这个对象在Web服务器启动时由服务器为部署的应用创建,整合Spring时通过启动时的监听器(Listener)创建Spring容器并放入ServletContext中,同时Spring容器也保存一份对ServletContext的引用。
c.如果都部署为普通工程,就需要手动调用Spring API获取服务对象,无法使用HTTP访问(没有HTTP服务监听,也没有URL映射、Servlet调用)。
3.需要一个ZooKeeper注册中心,1启动时向其注册,2从ZooKeeper中获取服务进行服务调用
4.部署时注意:
1中工程是在Maven中使用Dubbo官方主类和打在classpath下的META-INF/spring中的spring配置(使用maven的resource配置,可以配置源和目标位置,包含你想要打包到jar包特定位置的任何class资源和配置文件,记住显式配置就要写全,包含main/java,main/resources等,否则有些情况下会出现无法找到main/java下所需的相关依赖包的情况)打成了jar包,使用命令行java -jar直接启动,提高效率。使用官方主类,记得这样配置maven:
<resources>
<resource>
<targetPath>${project.build.directory}/classes</targetPath>
<directory>src/main/resources</directory>
<filtering>true</filtering>
<includes>
<include>**/*.xml</include>
<include>**/*.properties</include>
</includes>
</resource>
<!-- 结合com.alibaba.dubbo.container.Main -->
<resource>
<targetPath>${project.build.directory}/classes/META-INF/spring</targetPath>
<directory>src/main/resources/spring</directory>
<filtering>true</filtering>
<includes>
<include>spring-context.xml</include>
</includes>
</resource>
</resources>
在目标位置的/META-INF/spring包含了spring-context.xml,而spring-context.xml中这样配置:
<import resource="classpath:spring/spring-mybatis.xml" />
<import resource="classpath:spring/dubbo-provider.xml" />
因为打包到目标位置后,上述两个配置文件已经和/META-INF/spring下的spring-context.xml不在同一个目录了,而是仍在classpath目录,因为/META-INF/spring下没包含它们两个,所以需要使用classpath指定!!
使用Tomcat启动不推荐且依赖报错,因为打包位置不对应。
2中工程在IDEA中部署时提示找不到依赖的配置文件工程中的配置文件,手动拷贝一份过来,在Artifacts中自动生成的普通war可以正常启动,不能打成war:exploded
注意Druid使用配置,原来配置成了非对称加密登录数据库方式,这里去掉,数据源才能正常连接数据库。
测试用户的sha1加密的用户密码可以使用main方法,验证时同样的加密类加密测试明文密码得到(实际就是sha1算法,不是sha1后再hex,和在线工具得到的结果相同),先存入数据库,供正常登录。
RSA非对称加密错误参考:
https://segmentfault.com/q/1010000008473902
https://blog.csdn.net/kzcming/article/details/80109943
1的Jar包之所以在依赖其他jar的情况下能在Windows下的文件夹直接执行,是因为maven配置时使用了插件:
<plugins>
<!-- 打包jar文件时,配置manifest文件,加入lib包的jar依赖 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<classesDirectory>target/classes/</classesDirectory>
<archive>
<manifest>
<mainClass>com.alibaba.dubbo.container.Main</mainClass>
<!-- 打包时 MANIFEST.MF文件不记录的时间戳版本 -->
<useUniqueVersions>false</useUniqueVersions>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
</manifest>
<manifestEntries>
<Class-Path>.</Class-Path>
</manifestEntries>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<type>jar</type>
<includeTypes>jar</includeTypes>
<!--<useUniqueVersions>false</useUniqueVersions>-->
<outputDirectory>
${project.build.directory}/lib
</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
这样会在同一个文件夹中生成lib/目录,包含了所有依赖工程的包和其他jar包,且1的Jar包的META-INF/MANIFEST.MF文件中依赖了lib/下的这些jar包!!所以我们在部署到其他系统时需要把生成的lib/目录也拷贝过去,且和1的Jar包在同一个目录下,才能正确执行!!
1依赖的其他工程jar包,也需要先进行工程maven打包,私有库里才有,这样1打包时才能将这些工程打好的jar包包含到依赖lib/里面来,否则会报错!
2打的是war包,打好的包里已经包含lib/目录,里面有其Web工程依赖的所有包,所以不需要像1那样做!!
但发现spring boot的jar工程,使用spring boot的maven插件,把依赖lib/都打在了jar包里,并在MANIFEST.MF文件中配置了这些依赖信息,不需要像1那样做。
部署脚本:grep -w参数,精确匹配启动的服务名;``反引号获取命令执行结果;awk'print{$2}'获取输出进程号;$!获取进程号
防火墙的端口放行配置(/etc/sysconfig/iptables中添加-A INPUT -m state --state NEW -m tcp -p tcp --dport 8080 -j ACCEPT);重启防火墙(service iptables restart)
Tomcat内存设置(catalina.sh首行JAVA_OPTS='-Xms128m -Xmx512m -XX:PermSize=128m')和线程、连接优化;Tomcat开机启动(/etc/rc.local中加入启动命令)
配置本机主机名:/etc/hosts文件
5.简易监控中心
需要依赖jetty相关lib,可以根据Monitor等接口进行扩展,可以自己写,charts目录需要放在jetty.directory目录下,否则页面访问不了,使用磁盘存储统计信息,注意磁盘规划,集群情况下使用mount挂载共享磁盘
进入conf/dubbo.properties配置监控中心服务(也是一个Dubbo服务)的ZooKeeper地址,启动端口,依赖的jetty端口(不要与已启动的tomcat等冲突)。其他默认。${user.home}代表登录用户家目录
防火墙放行这些端口