Dubbo+Zookeeper+Nginx 集群和负载均衡(一)

1.概述
Dubbo 是Alibaba开源的分布式服务框架,它最大的特点是按照分层的方式来架构,使用这种方式可以使各个层之间解耦合(或者最大限度地松耦合)。从服务模型的角度来看,Dubbo采用的是一种非常简单的模型,要么是提供方提供服务,要么是消费方消费服务,所以基于这一点可以抽象出服务提供方(Provider)和服务消费方(Consumer)两个角色。
ZooKeeper 是 Apache 的一个顶级项目,为分布式应用提供高效、高可用的分布式协调服务,提供了诸如数据发布/订阅、负载均衡、命名服务、分布式协调/通知和分布式锁等分布式基础服务。由于 ZooKeeper 便捷的使用方式、卓越的性能和良好的稳定性,被广泛地应用于诸如 Hadoop、HBase、Kafka 和 Dubbo 等大型分布式系统中。
Nginx 是一款自由的、开源的、高性能的HTTP服务器和反向代理服务器;同时也是一个IMAP、POP3、SMTP代理服务器;Nginx可以作为一个HTTP服务器进行网站的发布处理,另外Nginx可以作为反向代理进行负载均衡的实现。

2.应用场景

当网站规模变大,通常会进行服务拆分,各个服务独立部署,通过远程调用方式协同工作;为了保证稳定性,每个服务不会只使用一台服务器,也会作为一个集群存在,那么这个子集群同样需要一个负载均衡器,可以使用Nginx。但随着整个系统的演进, 服务的数量会增加 、每个服务集群中的服务器数量会增加。

这时就会有一些小麻烦,例如

(1)配置维护的成本变高,因为节点太多。

(2)单点故障的风险增加了,因为热点服务的访问量很高,如果这个服务集群内的负载均衡服务出现问题,这个服务将失效。
第一个问题,可以通过自己开发程序解决,但只是降低复杂度,并没有实际解决 。
第二个问题,可以通过双机高可用部署方案,使用另一台nginx负载均衡服务器随时待命,只是成本较高。
而ZooKeeper作为服务的注册和变更通知中心,解决了Nginx负载均衡方案带来的问题。

ZooKeeper负载均衡的实现思路

把ZooKeeper作为一个服务的注册中心,在其中登记每个服务,每台服务器知道自己是属于哪个服务,在服务器启动时,自己向所属服务进行登记,这样,一个树形的服务结构就呈现出来了。
服务的调用者到注册中心里面查找,能提供所需服务的服务器列表,然后自己根据负载均衡算法,从中选取一台服务器进行连接。
调用者取到服务器列表后,就可以缓存到自己内部,省得下次再取,当服务器列表发生变化,例如某台服务器宕机下线,或者新加了服务器,ZooKeeper会自动通知调用者重新获取服务器列表。

3.目标

这篇博客介绍的是服务层面用Dubbo+Zookeeper实现分布式服务,然后Http web层用 Nginx 实现高可用集群方案。

4.准备工作
Linux服务器一台:192.168.1.125

4.1 在一台服务器上安装3个zkServer,构建伪集群模式

安装和配置:
Zookeeper官网:http://zookeeper.apache.org/releases.html
找到一个稳定版的进行安装:
# wget http://mirrors.hust.edu.cn/apache/zookeeper/zookeeper-3.4.11/zookeeper-3.4.11.tar.gz
解压:# tar -zxvf zookeeper-3.4.11.tar.gz
创建一个zookeeper文件夹:# mkdir zookeeper
在同一个机器中配置三个实例:
# cp -r /root/zookeeper-3.4.11 /root/zookeeper/zkServer1
# cp -r /root/zookeeper-3.4.11 /root/zookeeper/zkServer2
# cp -r /root/zookeeper-3.4.11 /root/zookeeper/zkServer3

配置第一个zkServer:
# cd zookeeper/zkServer1/conf
# cp zoo_sample.cfg zoo.cfg
# vi zoo.cfg
配置内容:

tickTime=2000                               #心跳检测的时间间隔(毫秒),缺省:2000
initLimit=5                                 #初次同步的阶段(followers连接到leader的阶段),允许的时长(tick数量),缺省:10
syncLimit=2                                 #允许followers同步到ZooKeeper的时长(tick数量),缺省:5
dataDir=/root/zookeeper/zkServer1/data      #数据(比如所管理的配置文件)的存放路径,初始时应该为空
dataLogDir=/root/zookeeper/zkServer1/logs   #日志文件存放路径
clientPort=2181                             #服务器对外服务端口,一般设置为2181 
server.1=127.0.0.1:2287:3387                #server.X:X是ensemble中一个服务器的id,后面指定该server的hostname、第一个端口号用于ZooKeeper之间的通信、第二个端口用于和其他应用之间的通信
server.2=127.0.0.1:2288:3388
server.3=127.0.0.1:2289:3389  

注意:
因为是在一台机器上模拟集群,所以端口不能重复,这里用2181~2183,2287~2289,以及3387~3389相互错开。
另外每个zkServer的instance,都需要设置独立的数据存储目录、日志存储目录,
所以dataDir、dataLogDir这两个节点对应的目录,需要手动先创建好。

配置第二个zkServer:
# cd zookeeper/zkServer2/conf
# cp zoo_sample.cfg zoo.cfg
修改:dataDir=/root/zookeeper/zkServer2/data
修改:dataLogDir=/root/zookeeper/zkServer2/logs
修改:clientPort=2182
其他的配置与zServer1的相同

配置第三个zkServer:
# cd zookeeper/zkServer3/conf
# cp zoo_sample.cfg zoo.cfg
修改:dataDir=/root/zookeeper/zkServer3/data
修改:dataLogDir=/root/zookeeper/zkServer3/logs
修改:clientPort=2183
其他的配置与zServer1的相同

创建myid文件:
在dataDir所配置的目录下,创建一个data文件夹,在data文件夹下创建一个名为myid的文件,在该文件的第一行写上一个数字,和zoo.cfg中当前机器的编号对应上。
# cd zookeeper/zkServer1
# mkdir data
# cd data
# echo "1" > myid
zkServer2中myid内容为2,zkServer3中myid内容为3。

启动Zookeeper所有服务:
分别进入三个zkServer bin目录下,启动服务。
# ./zkServer.sh start
# /root/zookeeper/zkServer1/bin/zkServer.sh start
# /root/zookeeper/zkServer2/bin/zkServer.sh start
# /root/zookeeper/zkServer3/bin/zkServer.sh start
启动成功后,查看状态:
# jps
# ./zServer.sh status

4.2 配置Dubbo管理项目
Dubbo项目官网:http://dubbo.apache.org
下载Dubbo项目源码:https://github.com/apache/incubator-dubbo/archive/dubbo-2.6.0.zip
这里写图片描述

这里我们只用dubbo-admin进行项目管理

这里写图片描述
dubbo-admin下的一个dubbo.properties文件配置了指向zookeeper的参数:
这里写图片描述
dubbo-admin我们将发布到Linux服务器上面,默认端口与zookeeper是一致的所以不用修改,用户名/密码使用默认的root/root。

启动cmd窗口,进入dubbo-admin目录下,将dubbo-admin项目打包:
> mvn install -Dmaven.test.skip=true
这里写图片描述
显示DUILD SUCCESS打包成功,可以在dubbo-admin的target目录下找到【dubbo-admin-2.6.0.war】文件:
这里写图片描述
将打包好的war文件放到Linux服务器上的Tomcat的webapps目录下,启动Tomcat,Tomcat启动时会自动解压该war包的
# /root/apache-tomcat-7.0.14/bin/./startup.sh
这里写图片描述

输入这个Tomat的访问网址 http://192.168.1.125:8088/dubbo-admin-2.6.0 (端口号注意修改成自己改的那个),登陆密码都是就是上面配置文件中的root
这里写图片描述

4.3 创建提供者
1.创建公用接口项目Dubbo-service,创建两个provider (Dubbo-provider,Dubbo–provider2)
这里写图片描述
service包,公用接口,maven基础java包,不需要加入任何依赖,也不需要加入任何配置文件,2个provider包引入dubbo,zookeeper,log4依赖。下面给出其中一个的pom实例,copy请自行修改artifactId。

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.tianwen</groupId>
  <artifactId>Dubbo-provider</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>jar</packaging>

  <dependencies>
        <dependency>
            <groupId>com.tianwen</groupId>
            <artifactId>Dubbo-service</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>  
        <dependency>  
            <groupId>com.alibaba</groupId>  
            <artifactId>dubbo</artifactId>  
            <version>2.6.0</version>  
        </dependency>  
        <dependency>  
            <groupId>org.apache.zookeeper</groupId>  
            <artifactId>zookeeper</artifactId>  
            <version>3.3.3</version>  
        </dependency>  

        <!-- 日志相关 -->  
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>

        <dependency>  
            <groupId>org.slf4j</groupId>  
            <artifactId>slf4j-api</artifactId>  
            <version>1.7.5</version>  
        </dependency>  

        <!-- zookeeper client依赖,用于向zookeeper注册服务 -->  
        <dependency>  
            <groupId>com.github.sgroschupf</groupId>  
            <artifactId>zkclient</artifactId>  
            <version>0.1</version>  
        </dependency>
  </dependencies>

<build>
        <!-- 输出文件名 -->
        <finalName>dubbo-provider</finalName>

        <resources>
            <resource>
                <targetPath>${project.build.directory}/classes</targetPath>
                <directory>src/main/resources</directory>
                <filtering>true</filtering>
                <includes>
                    <include>**/*.xml</include>
                    <include>**/*.properties</include>
                </includes>
                <excludes>
                    <!-- spring配置文件由下面的配置:拷贝到META-INF/spring中 -->
                    <exclude>spring/*.xml</exclude>
                </excludes>
            </resource>
            <!-- com.alibaba.dubbo.container.Main加载spring配置文件的路径 META-INF/spring -->
            <resource>
                <targetPath>${project.build.directory}/classes/META-INF/spring</targetPath>
                <directory>src/main/resources/spring</directory>
                <filtering>true</filtering>
                <includes>
                    <include>*.xml</include>
                </includes>
            </resource>
        </resources>

        <!-- 解决Maven在Eclipse内执行的执行了一系列的生命周期引起冲突 -->
        <pluginManagement>
            <plugins>
                <plugin>
                    <groupId>org.eclipse.m2e</groupId>
                    <artifactId>lifecycle-mapping</artifactId>
                    <version>1.0.0</version>
                    <configuration>
                        <lifecycleMappingMetadata>
                            <pluginExecutions>
                                <pluginExecution>
                                    <pluginExecutionFilter>
                                        <groupId>org.apache.maven.plugins</groupId>
                                        <artifactId>maven-dependency-plugin</artifactId>
                                        <versionRange>[2.0,)</versionRange>
                                        <goals>
                                            <goal>copy-dependencies</goal>
                                        </goals>
                                    </pluginExecutionFilter>
                                    <action>
                                        <ignore/>
                                    </action>
                                </pluginExecution>
                            </pluginExecutions>
                        </lifecycleMappingMetadata>
                    </configuration>
                </plugin>

            </plugins>
        </pluginManagement>


        <plugins>
            <!-- 资源文件拷贝插件 -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-resources-plugin</artifactId>
                <version>2.7</version>
                <configuration>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>

            <!-- java编译插件 -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.2</version>
                <configuration>
                    <source>1.7</source>
                    <target>1.7</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>

            <!-- 打包jar文件时,配置manifest文件,加入lib包的jar依赖 -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <version>2.6</version>
                <configuration>
                    <classesDirectory>target/classes/</classesDirectory>
                    <archive>
                        <manifest>
                            <!-- 打包时 MANIFEST.MF文件不记录的时间戳版本 -->
                            <useUniqueVersions>false</useUniqueVersions>
                            <!-- 添加Class-Path -->
                            <addClasspath>true</addClasspath>
                            <!-- Class-Path添加前缀 -->
                            <classpathPrefix>lib/</classpathPrefix>
                            <!-- 指定Main-Class -->
                            <mainClass>com.alibaba.dubbo.container.Main</mainClass>
                        </manifest>
                    </archive>
                </configuration>
            </plugin>

            <!-- 拷贝依赖的jar包到lib目录 -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-dependency-plugin</artifactId>
                <version>2.10</version>
                <executions>
                    <execution>
                        <id>copy</id>
                        <phase>package</phase>
                        <goals>
                            <goal>copy-dependencies</goal>
                        </goals>
                        <configuration>
                            <outputDirectory>
                                <!-- 拷贝依赖到lib文件夹 -->
                                ${project.build.directory}/lib
                            </outputDirectory>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

</project>

2.在service公有服务接口包中新建接口DemoService,内容很简单,就包含一个测试接口

package com.tianwen.service;

public interface DemoService {

    String sayHello(String name);
}

3.provider 提供者需要实现这个公用接口以向消费者提供服务,两个provider基本是一样的

  • provider:DemoServiceImpl.java实现公有接口 DemoService
package com.tianwen.service.impl;

import com.alibaba.dubbo.rpc.RpcContext;
import com.tianwen.service.DemoService;

public class DemoServiceImpl implements DemoService{

    public String sayHello(String name) {
        return "Hello " + name + ", response form provider: " + RpcContext.getContext().getLocalAddress();
    }

}

4.到这里提供者代码层面基本完了,该项目增加配置文件,在resources目录下新建2个配置文件:
spring-provider.xml(dubbo 提供者配置文件,重要),log4.properties

  • log4.properties:
###set log levels###
log4j.rootLogger=info, stdout
###output to the console###
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=[%d{dd/MM/yy hh:mm:ss:sss z}] %t %5p %c{2}: %m%n
  • Dubbo-provider: spring-provider.xml
 <?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements.  See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License.  You may obtain a copy of the License at

     http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
       xmlns="http://www.springframework.org/schema/beans"
       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="demo-provider"/>

    <!-- 使用zookeeper广播注册中心暴露服务地址 -->  
    <dubbo:registry protocol="zookeeper" address="192.168.1.125:2181,192.168.1.125:2182,192.168.1.125:2183"/>

    <!-- 用dubbo协议在20880端口暴露服务 -->  
    <dubbo:protocol name="dubbo" port="20880"/>

     <!-- 和本地bean一样实现服务 -->  
    <bean id="demoService" class="com.tianwen.service.impl.DemoServiceImpl"/>

    <!-- 声明需要暴露的服务接口 -->  
    <dubbo:service interface="com.tianwen.service.DemoService" ref="demoService"/>

</beans>
  • Dubbo-provider2:spring-provider.xml
 <?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements.  See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License.  You may obtain a copy of the License at

     http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
       xmlns="http://www.springframework.org/schema/beans"
       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="demo-provider"/>

    <!-- 使用zookeeper广播注册中心暴露服务地址 -->  
    <dubbo:registry protocol="zookeeper" address="192.168.1.125:2181,192.168.1.125:2182,192.168.1.125:2183"/>

    <!-- 用dubbo协议在20881端口暴露服务 -->  
    <dubbo:protocol name="dubbo" port="20881"/>

     <!-- 和本地bean一样实现服务 -->  
    <bean id="demoService" class="com.tianwen.service.impl.DemoServiceImpl"/>

    <!-- 声明需要暴露的服务接口 -->  
    <dubbo:service interface="com.tianwen.service.DemoService" ref="demoService"/>

</beans>

注意:2个provider的应用名一样,因为模拟集群负载均衡,所以对Dubbo来说是一个服务。
2个provider的端口需不一样,因为是同一台机子模拟2个服务,如果是多台就无所谓了。
dubbo:Service须保持一致,因为2个provider负载均衡是模拟一个服务,所以提供的服务外面看来须一样。

4.使用 maven 打包项目,并发布至Linux服务器:
Eclipse 项目上点 Run As -> Maven build ,Goals 栏填 package,编译完成后,将在 target 目录中看到两个 jar 包及 lib 目录: dubbo-provider.jar 为包含了第三方类库的完整 jar 包,可单独部署 dubbo-provider.jar 为不包含第三方类库的 jar 包,结合 lib 目录可部署。
创建一个provider文件夹:# mkdir provider
将lib目录和dubbo-provider.jar 上传至provider目录下(注意lib目录一定要和jar放在一起),# cd provider,启动服务# java -jar dubbo-provider.jar
这里写图片描述
Dubbo service server started 服务启动成功。
这里写图片描述
从Dubbo管理中心可以看到服务已经注册成功,我们按照同样的方法发布Dubbo-provider2。
这里写图片描述

4.4 创建消费者,这里创建2个Spring mvc web项目来充当消费的角色。
两个消费者(Dubbo-consumer,Dubbo-consumer2)一样,就是服务实现不一样来测试负载均衡,还有个消费者配置文件不一样。
这里写图片描述

1、两个消费者POM.xml基本是一样的,标准的Spring mvc web项目,需要引入dubbo,zookeeper,公有服务service,Spring mvc系列,log4系列。下面给出其中一个的pom实例,copy请自行修改artifactId。

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.tianwen</groupId>
  <artifactId>Dubbo-consumer</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>war</packaging>
  <dependencies>
   <dependency>
            <groupId>com.tianwen</groupId>
            <artifactId>Dubbo-service</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>  
        <dependency>  
            <groupId>com.alibaba</groupId>  
            <artifactId>dubbo</artifactId>  
            <version>2.6.0</version>  
        </dependency>  
        <dependency>  
            <groupId>org.apache.zookeeper</groupId>  
            <artifactId>zookeeper</artifactId>  
            <version>3.3.3</version>  
        </dependency>  

        <!-- 日志相关 -->  
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>

        <dependency>  
            <groupId>org.slf4j</groupId>  
            <artifactId>slf4j-api</artifactId>  
            <version>1.7.5</version>  
        </dependency>  

        <!-- zookeeper client依赖,用于向zookeeper注册服务 -->  
        <dependency>  
            <groupId>com.github.sgroschupf</groupId>  
            <artifactId>zkclient</artifactId>  
            <version>0.1</version>  
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>4.3.6.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>4.3.6.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>4.3.6.RELEASE</version>
        </dependency>
    </dependencies> 

 <build>
    <plugins>
            <!-- tomcat7 启动所需jar包 -->
            <plugin>
                <groupId>org.apache.tomcat.maven</groupId>
                <artifactId>tomcat7-maven-plugin</artifactId>
                <version>2.1</version>
                <configuration>
                    <!--端口 -->
                    <port>8083</port>
                    <!--注意名称 -->
                    <path>/</path>
                    <uriEncoding>UTF-8</uriEncoding>
                    <!--注意此名字 启动时会用到 -->
                    <server>tomcat7</server>
                </configuration>
            </plugin>
    </plugins>
 </build> 
</project>

2、两个web项目的主要配置文件,共4个:web.xml、spring-web.xml、spring-consumer.xml、log4j.properties。
这里我只贴出web.xml、spring-web.xml、spring-consumer.xml。

  • web.xml:
 <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns="http://java.sun.com/xml/ns/javaee"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
         id="WebApp_ID" version="3.0">
    <display-name>Dubbo-consumer</display-name>

    <servlet>
        <servlet-name>springMvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:spring/spring-*.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>springMvc</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

    <!-- UTF-8 -->
    <filter>
        <filter-name>EncodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
    </filter>

    <filter-mapping>
        <filter-name>EncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>


    <!-- Log4j配置 -->
    <context-param>
        <param-name>log4jConfigLocation</param-name>
        <param-value>classpath:log4j.properties</param-value>
    </context-param>

    <!-- 加载log4j配置文件 -->
    <listener>
        <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
    </listener>

    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>
</web-app>
  • spring-web.xml:
 <?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:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                           http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd 
                           http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd 
                           http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd">

    <!-- 自动扫描controller包,实现支持注解的IOC -->
    <context:component-scan base-package="com.tianwen.common" />
    <context:component-scan base-package="com.tianwen.core.*.controller" />


    <!-- 配置JSP视图解析器 -->
    <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
        <property name="prefix" value="/WEB-INF/views/jsp/" />
        <property name="suffix" value=".jsp" />
        <property name="order" value="1" />
    </bean>

    <mvc:annotation-driven >
    <!-- 消息转换器 -->
    <mvc:message-converters register-defaults="true">
      <bean class="org.springframework.http.converter.StringHttpMessageConverter">
        <property name="supportedMediaTypes" value="text/html;charset=UTF-8"/>
      </bean>
    </mvc:message-converters>
  </mvc:annotation-driven>
  <mvc:resources location="/resources/" mapping="/resources/**" />
</beans>
  • spring-consumer.xml:(两个项目只需改一下消费方应用名即可,其他配置相同)
 <?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements.  See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License.  You may obtain a copy of the License at

     http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
       xmlns="http://www.springframework.org/schema/beans"
       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="demo-consumer"/>

    <!-- 使用zookeeper广播注册中心暴露服务地址 -->  
    <dubbo:registry protocol="zookeeper" address="192.168.1.125:2181,192.168.1.125:2182,192.168.1.125:2183"/>

     <!-- 生成远程服务代理,可以和本地bean一样使用demoService -->
    <dubbo:reference id="demoService" check="false" interface="com.tianwen.service.DemoService"/>

</beans>

3、现在我们新建个controller,就弄个接口,调用提供者的远程服务。

  • Dubbo-consumer UserController.java:
package com.tianwen.core.user.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;


import com.tianwen.service.DemoService;

@Scope("prototype")
@Controller
@RequestMapping(value = "/user")
public class UserController {

    @Autowired
    private DemoService demoService;

    @RequestMapping(value = "/test")  
    @ResponseBody  
    public String testDubbo(){  
        String str = demoService.sayHello("我是消费者1号!");
        System.out.println(str);
        return str;
    }
}
  • Dubbo-consumer2 UserController.java:
package com.tianwen.core.user.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;


import com.tianwen.service.DemoService;

@Scope("prototype")
@Controller
@RequestMapping(value = "/user")
public class UserController {

    @Autowired
    private DemoService demoService;

    @RequestMapping(value = "/test")  
    @ResponseBody  
    public String testDubbo(){  
        String str = demoService.sayHello("我是消费者2号!");
        System.out.println(str);
        return str;
    }
}
  • index.jsp:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<html>
<head>

</head>
<body>
<a href="/user/test">Dubbo测试1</a>
</body>
</html>

4、接下来我们在Linux准备两个Tomcat,配置成不同的端口(8081,8082),将两个consumer项目打包,发布至Tomcat中,通过IP地址访问。
这里写图片描述
到这里,我们已经实现了Dubbo+Zookeeper的分布式服务,下一步,加入nginx 实现http层面的负载均衡。

4.5 Nginx配置
下载安装好Nginx后,修改conf目录下的nginx.conf

    upstream dubbo-test-server {          # 配置负载均衡
    server  127.0.0.1:8081 weight=10;     # 服务器地址
    server  127.0.0.1:8082 weight=10; 
    }

    #下面是server虚拟主机的配置
    server {
        listen       80;                  #监听端口
        server_name  localhost;           #域名

        #charset koi8-r;

        #access_log  logs/host.access.log  main;

        location / {
           proxy_pass http://dubbo-test-server;
        }

    }

检查配置文件ngnix.conf的正确性:# /usr/local/webserver/nginx/sbin/nginx -t
这里写图片描述
启动 Nginx:# /usr/local/webserver/nginx/sbin/nginx
这里写图片描述

评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值