springboot + mybatis + mysql + dubbo+ zookeeper一个简单的分布式搭建过程

结合了网上的两篇博客综合实现了一下整体的过程:

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

猜你喜欢

转载自blog.csdn.net/wangbo54979/article/details/79879460