结合了网上的两篇博客综合实现了一下整体的过程:
1. Dubbo与zookeeper
Dubbo为什么要与zookeeper/Consule一起使用?
dubbo主要是一个分布式服务框架,致力于提供高性能和透明化的RPC远程服务调用方案,以及SOA服务治理方案。简单的说,dubbo就是个服务框架,如果没有分布式的需求,其实是不需要用的.告别Web Service模式中的WSdl,以服务者与消费者的方式在dubbo上注册.
zookeeper用来注册服务和进行负载均衡,哪一个服务由哪一个机器来提供必需让调用者知道,简单来说就是ip地址和服务名称的对应关系。zookeeper通过心跳机制可以检测挂掉的机器并将挂掉机器的ip和服务对应关系从列表中删除。
看图识物:
上图所示,假如我有四台服务器,每台服务器都提供相同的服务,如果我消费者去掉用的时候,肯定要在四个当中选择某一个去调用,可是选择哪一个就是一个难题,当然这就涉及到负载均衡问题了,或者我们在消费者这边加代码逻辑判断达到负载均衡的效果。还有每次调用的时候都不知道要去掉哪个服务,都要查询当前有哪些服务提供者,这是很耗开销的,当服务提供越来越多的时候,越来越乱。
最终方案:
利用zookeeper生成的节点树,服务器提供者在启动的时候,将提供的服务名称和地址以节点的方式注册都服务器zookeeper服务器配置中心,消费者通过服务器配置中心获取需要的服务名称节点下的服务地址。因为znode有非持久节点的特性,服务器可以动态的从服务配置中心一处,并且触发消费者的watcher方法!!!
消费者只有在第一次调用的时候直接本地缓存服务器列表信息,而不需要重新发起请求到服务器配置中心区获取相应 的服务器列表,直到服务器地址列表有变化(机器下线或者上线),变更之后消费者watcher进行服务地址的重新查询。正是因为这种无中心化的结构,使得服务消费者在服务信息没变更时候,几乎不依赖配置中心,解决了负载均衡设备导致的单点故障的问题,大大减少了服务配置中心的压力
2. Zookeeper的安装
此处以windows环境下为例
注:linux安装参考http://blog.csdn.net/lk10207160511/article/details/50526404
在apache的官方网站提供了好多镜像下载地址,然后找到对应的版本,目前最新的是3.3.6
下载地址:
http://mirrors.cnnic.cn/apache/zookeeper/zookeeper-3.3.6/zookeeper-3.3.6.tar.gz
把下载的zookeeper的文件解压到指定目录
修改conf下增加一个zoo.cfg
内容如下:
# The number of milliseconds of eachtick 心跳间隔毫秒每次
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 gettinganacknowledgement
syncLimit=5
# the directory where the snapshotisstored. //镜像数据位置
dataDir=D:\\data\\zookeeper
#日志位置
dataLogDir=D:\\logs\\zookeeper
# the port at which the clientswillconnect 客户端连接的端口
clientPort=2181
注:如果启动有报错提示cfg文件有错误,可以用zoo_sample.cfg内内容替代也是可以的
进入到bin目录,并且启动zkServer.cmd,这个脚本中会启动一个Java进程
这个时候zookeeper已经安装成功了.
3. 配置dubbo-admin的管理页面
下载dubbo-admin-2.4.1.war包,解压到tomcat中。
如图所示:
修改dubbo.properties文件,里面指向Zookeeper ,使用的是Zookeeper 的注册中心。
然后启动tomcat服务,用户名和密码:root,并访问服务,显示登陆页面,说明dubbo-admin部署成功,如图所示:
在把dubbo-admin.war部署到Tomcat中运行时,可能会存在jdk版本的问题 导致这个dubbo-admin的管理界面跑不起来
解决办法:下载dubbo-admin的源码 引入ide中 更改其中pom文件中的 一些相应的配置.https://blog.csdn.net/wangzi19933/article/details/54139246 这里面提供解决的办法
4. 项目结构划分,我这里划分为4块
4个项目的依赖关系是:common里面暂时存放的只有user一个实体类,可以根据需求在里面加上其他的公共类,分页,验证等,这个项目不依赖其他的项目,其他3个项目都需要依赖它,所有这个项目需要先打包(相信做个maven项目的人应该都会-----如果对项目有所改动的话,需要先 maven clean,然后再maven install);
第二个需要打包的是 app项目,service和web项目都依赖它,然后再打包service项目,最后web项目。
xy-commer-common 项目目录:
User实体类具体代码:
public class User implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
public long id;
public String uname;
public String pwd;
public long ctime;
public String phone;
public String info;
public String img;
//............
}
pom.xml配置 父级xy-commer
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.5</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
</dependency>
<dependency>
<groupId>com.atlassian.commonmark</groupId>
<artifactId>commonmark</artifactId>
<version>0.8.0</version>
</dependency>
<!--过滤emoji字符 -->
<dependency>
<groupId>com.vdurmont</groupId>
<artifactId>emoji-java</artifactId>
<version>3.2.0</version>
</dependency>
</dependencies>
xy-commer-app 项目目录:
Userservice接口 具体代码:
import xy.commer.cloud.entity.User;
public interface UserService {
User findUserById(long id);
}
pom.xml
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>xy-commer-common</groupId>
<artifactId>xy-commer-common</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
xy-commer-service 项目目录:
ServiceMain springboot启动类
package xy.commer.cloud.main;
import java.io.IOException;
import javax.sql.DataSource;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.ImportResource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.dubbo.config.annotation.Service;
/**
*
* service 服务 springboot 核心启动类
*
*/
@SpringBootApplication
@ComponentScan(basePackages = { "com.commer.app.service.impl" }, includeFilters = {
@Filter(classes = { Service.class }) })
@ImportResource(locations = { "classpath:dubboprovider.xml" })
@MapperScan("xy.commer.cloud.main.mapper")
public class ServiceMian {
@Bean(initMethod = "init", destroyMethod = "close")
//数据源以spring.datasource大头
@ConfigurationProperties(prefix = "spring.datasource")
public DataSource dataSource() {
return new DruidDataSource();
}
@Bean
public SqlSessionFactory sqlSessionFactoryBean() throws Exception {
PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(dataSource());
//加载mybatis的映射文件
sqlSessionFactoryBean.setMapperLocations(resolver.getResources("classpath*:/mybatis-mapping/*Mapper.xml"));
return sqlSessionFactoryBean.getObject();
}
public static void main(String[] args) throws IOException {
SpringApplication.run(ServiceMian.class, args);
System.out.println("xy-commer-service-服务运行中...");
System.in.read();
}
}
UserMapper接口:
@Component
public interface UserMapper {
User findUserById(long id);
}
UserServiceImpl:
package xy.commer.cloud.main.service.impl;
import javax.annotation.Resource;
import com.alibaba.dubbo.config.annotation.Service;
import xy.commer.cloud.entity.User;
import xy.commer.cloud.main.mapper.UserMapper;
import xy.commer.cloud.service.UserService;
//因为作为一个dubbo服务提供者,启动时需要知道发布的服务是在哪,不使用dubbo提供的@service注解会出现问题的。
//注意这里是service要引dubbo的
@Service
public class UserServiceImpl implements UserService {
@Resource
UserMapper userMapper;
@Override
public User findUserById(long id) {
return this.userMapper.findUserById(id);
}
}
userMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="xy.commer.cloud.main.mapper.UserMapper">
<select id="findUserById" parameterType="long" resultType="xy.commer.cloud.entity.User">
select * from user where id = #{id}
</select>
</mapper>
application.properti..
#pagehelper
pagehelper.helperDialect=mysql
pagehelper.reasonable=true
pagehelper.support-methods-arguments=true
pagehelper.params=count=countSql
# db config
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.driverClassName=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/spring-boot?useSSL=false&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&autoReconnect=true
spring.datasource.username=root
spring.datasource.password=1234
spring.datasource.initialSize=20
spring.datasource.minIdle=10
spring.datasource.maxActive=100
#port set
server.port=8012
dubbo.配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
<!-- 提供方应用信息,用于计算依赖关系 -->
<dubbo:application name="xy-commer-service" />
<!-- 使用zookeeper注册中心暴露服务地址 -->
<dubbo:registry address="zookeeper://127.0.0.1:2181" />
<!-- 用dubbo协议在20880端口暴露服务 -->
<dubbo:protocol name="dubbo" port="20880" />
<!-- 声明要对外暴漏的接口 -->
<bean id="userService" class="xy.commer.cloud.main.service.impl.UserServiceImpl"></bean>
<dubbo:service interface="xy.commer.cloud.service.UserService"
ref="userService"></dubbo:service>
<!-- 监控中心配置 -->
<!-- <dubbo:monitor protocol="registry"/> -->
<dubbo:annotation />
</beans>
pom.xml
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!-- 集成Dubbo -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.5.3</version>
<exclusions>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.6</version>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
<exclusion>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.github.sgroschupf</groupId>
<artifactId>zkclient</artifactId>
<version>0.1</version>
</dependency>
<!-- mysql驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.0.18</version>
</dependency>
<!-- test -->
<dependency>
<groupId>org.wisdom-framework</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.34_1</version>
</dependency>
<!-- spring-boot mybatis依赖 -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.1.1</version>
</dependency>
<!-- 解析配置文件 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>xy-commer-common</groupId>
<artifactId>xy-commer-common</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>xy-commer-app</groupId>
<artifactId>xy-commer-app</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
然后 启动ServiceMain启动测试一下如果出现以下 说明成功了一小步:
然后是xy-commer-web的 目录结构:
CusrMain:
package xy.commer.cloud.main;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.ImportResource;
import xy.commer.cloud.entity.User;
import xy.commer.cloud.service.UserService;
@SpringBootApplication
@ImportResource(locations = { "classpath:dubbo-consumer.xml" })
public class CustMain {
public static void main(String[] args) {
ApplicationContext tc = SpringApplication.run(CustMain.class, args);
UserService userService = (UserService) tc.getBean("userService");
User user = userService.findUserById(1l);
System.err.println(user.toString());
}
}
application.proper..
#port set
server.port=8011
dubbo.配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
<!-- 消费方应用名,用于计算依赖关系 -->
<dubbo:application name="xy-commer-web" />
<!-- 使用zookeeper注册中心暴露发现服务地址 -->
<dubbo:registry address="zookeeper://127.0.0.1:2181" />
<!-- 开启启动时检测,当没有可用服务时,会报异常,程序中断,为false时,程序不中断,但是调用服务时报异常 -->
<dubbo:consumer check="false" timeout="60000" />
<!-- 监控中心配置 -->
<!-- 生成远程服务代理,可以像使用本地bean一样使用userService 要引用的 接口 -->
<dubbo:reference id="userService"
interface="xy.commer.cloud.service.UserService" check="true"
loadbalance="roundrobin" proxy="jdk" />
</beans>
我觉得 web 服务发现者这边 就列这些就够了 其他的按照个人的业务需求而添加了,然后运行springboot的启动类看结果:前提是服务提供者那边 得先启动:如果直接启动web发现者端 会报错Caused by: java.lang.IllegalStateException: Failed to check the status of the service xy.commer.cloud.service.UserService. No provider available for the service xy.commer.cloud.service.UserService 没有找到服务的提供者
最后附上源码下载地址:https://download.csdn.net/download/wangbo54979/10338460