文档章节

保障服务的持续高可用、高性能及负载均衡

杨尚川
 杨尚川
发布于 2016/09/24 21:54
字数 938
阅读 2201
收藏 41

保障服务的持续高可用、高性能及负载均衡

高可用: 服务多副本
高性能: 超时限制
负载均衡: 环形队列

已经实现的功能:
1. HTTP调用方式的搜索服务
2. REDIS访问

一句话说明白这个项目的原理:

后端有多个一模一样的搜索,还有多个一模一样的REDIS,中间层的业务逻辑不直接调用搜索和REDIS,而是通过这个组件来调用

在WEB项目中的使用方法

1. 编译依赖:

    git clone https://github.com/ysc/high-availability.git
    cd high-availability
    mvn install

2. 在 pom.xml 中指定以下依赖:

    <dependency>
        <groupId>org.apdplat.service</groupId>
        <artifactId>high-availability</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>

3. 在 src/main/resources 目录下新建目录 conf, 然后在 conf 目录下新建文件 conf.txt, 加入如下配置项:

    #search api depends on these servers
    search.api.server.urls=http://192.168.0.100:8080/search.jsp, http://192.168.0.101:8080/search.jsp
    #timeout config to guarantee response time
    search.api.timeout.seconds=1
    #whether output status to log in every unavailable urls valid process
    status.log.enabled=true
    #unavailable schedule initial delay seconds
    unavailable.schedule.initial.delay.seconds=60
    #unavailable schedule period seconds
    unavailable.schedule.period.seconds=60
    #redis servers
    redis.servers=192.168.0.102:6379:b01cbe1209a545a7cdb, 192.168.0.103:6379:b01cbe1209a545a7cdb

    redis.pool.blockWhenExhausted=false
    redis.pool.jmxEnabled=false
    redis.pool.lifo=true
    redis.pool.maxIdle=500
    redis.pool.maxTotal=500
    redis.pool.maxWaitMillis=500
    redis.pool.minEvictableIdleTimeMillis=1800000
    redis.pool.minIdle=0
    redis.pool.numTestsPerEvictionRun=3
    redis.pool.softMinEvictableIdleTimeMillis=1800000
    redis.pool.testOnBorrow=true
    redis.pool.testWhileIdle=true
    redis.pool.timeBetweenEvictionRunsMillis=-1
    redis.pool.readTimeoutMillis=2000

4. 在 web.xml 中配置一个监听器:

    <listener>
        <listener-class>org.apdplat.data.visualization.container.HighAvailabilityListener</listener-class>
    </listener>

5. 监听器 HighAvailabilityListener.java 类的代码如下:

    public class HighAvailabilityListener  implements ServletContextListener {
        private static final Logger LOGGER = LoggerFactory.getLogger(HighAvailabilityListener.class);

        @Override
        public void contextInitialized(ServletContextEvent sce) {
            String conf = sce.getServletContext().getRealPath("/WEB-INF/classes/conf/");
            LOGGER.info("启动搜索服务, 监控配置目录: {}", conf);
            ConfWatcher.startWatch(conf);
            sce.getServletContext().setAttribute("SearchAPI", new SearchAPIImpl());
        }

        @Override
        public void contextDestroyed(ServletContextEvent sce) {
            LOGGER.info("停止搜索服务");
            SearchAPI searchAPI = (SearchAPI)sce.getServletContext().getAttribute("SearchAPI");
            if(searchAPI != null){
                searchAPI.close();
            }
            LOGGER.info("停止监控配置目录");
            ConfWatcher.stopWatch();
        }
    }

6. 在 jsp 中调用搜索服务:

    SearchAPI searchAPI = (SearchAPI) application.getAttribute("SearchAPI");
    if(searchAPI == null) {
        out.println("搜索服务未启动");
        return;
    }
    String keyword = request.getParameter("kw") == null ? "CCTV-1" : request.getParameter("kw");
    int topN = 5;
    try{
        topN = Integer.parseInt(request.getParameter("topN"));
    }catch (Exception e){
        //
    }
    String result = null;
    long start = System.currentTimeMillis();
    result = searchAPI.search(keyword, topN);
    String cost = Utils.getTimeDes(System.currentTimeMillis()-start);
    // 如果想知道搜索服务的状态
    String status = searchAPI.getStatus().replace("\n", "<br/>").replace("\t", "&nbsp; &nbsp; &nbsp; &nbsp; ");

7. 获取REDIS连接:

    String DETECT_KEY = "redis_ha_detector";

    Jedis jedis = null;
    try{
        jedis = JedisAPI.getInstance().getJedis();
        // 如果所有REDIS服务都不可用, 则返回null
        if(jedis != null) {
            jedis.set(DETECT_KEY, String.valueOf(System.currentTimeMillis()));
            System.out.println(jedis.get(DETECT_KEY));
            System.out.println("REDIS服务状态:\n" + JedisAPI.getInstance().getStatus());
        }
    }finally {
        if(jedis != null){
            // 返回连接用完后必须要关闭, 调用close方法
            jedis.close();
        }
    }    

在非WEB项目中的使用方法

1. 编译依赖:

    git clone https://github.com/ysc/high-availability.git
    cd high-availability
    mvn install

2. 在 pom.xml 中指定以下依赖:

    <dependency>
        <groupId>org.apdplat.service</groupId>
        <artifactId>high-availability</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>

3. 新建目录 conf, 然后在 conf 目录下新建文件 conf.txt, 加入如下配置项:

    #search api depends on these servers
    search.api.server.urls=http://192.168.0.100:8080/search.jsp, http://192.168.0.101:8080/search.jsp
    #timeout config to guarantee response time
    search.api.timeout.seconds=1
    #whether output status to log in every unavailable urls valid process
    status.log.enabled=true
    #unavailable schedule initial delay seconds
    unavailable.schedule.initial.delay.seconds=60
    #unavailable schedule period seconds
    unavailable.schedule.period.seconds=60
    #redis servers
    redis.servers=192.168.0.102:6379:b01cbe1209a545a7cdb, 192.168.0.103:6379:b01cbe1209a545a7cdb

    redis.pool.blockWhenExhausted=false
    redis.pool.jmxEnabled=false
    redis.pool.lifo=true
    redis.pool.maxIdle=500
    redis.pool.maxTotal=500
    redis.pool.maxWaitMillis=500
    redis.pool.minEvictableIdleTimeMillis=1800000
    redis.pool.minIdle=0
    redis.pool.numTestsPerEvictionRun=3
    redis.pool.softMinEvictableIdleTimeMillis=1800000
    redis.pool.testOnBorrow=true
    redis.pool.testWhileIdle=true
    redis.pool.timeBetweenEvictionRunsMillis=-1
    redis.pool.readTimeoutMillis=2000

4. 将conf目录加入classpath:

    java -cp conf:xxx-1.0-SNAPSHOT-jar-with-dependencies.jar 

5. 启动搜索服务并监控配置目录的代码如下:

    Path conf = Paths.get(ConfWatcher.class.getResource("/conf/").getPath());
    LOGGER.info("启动搜索服务, 监控配置目录: {}", conf);
    ConfWatcher.startWatch(conf);
    SearchAPI searchAPI = new SearchAPIImpl();

6. 调用搜索服务:

    String keyword = "CCTV-1";
    int topN = 5;

    String result = null;
    long start = System.currentTimeMillis();
    result = searchAPI.search(keyword, topN);
    String cost = Utils.getTimeDes(System.currentTimeMillis()-start);

    // 如果想知道搜索服务的状态
    String status = searchAPI.getStatus();

7. 获取REDIS连接:

    String DETECT_KEY = "redis_ha_detector";

    Jedis jedis = null;
    try{
        jedis = JedisAPI.getInstance().getJedis();
        // 如果所有REDIS服务都不可用, 则返回null
        if(jedis != null) {
            jedis.set(DETECT_KEY, String.valueOf(System.currentTimeMillis()));
            System.out.println(jedis.get(DETECT_KEY));
            System.out.println("REDIS服务状态:\n" + JedisAPI.getInstance().getStatus());
        }
    }finally {
        if(jedis != null){
            // 返回连接用完后必须要关闭, 调用close方法
            jedis.close();
        }
    }

目录结构

.
├── README.md
├── pom.xml
└── src
    └── main
        ├── java
        │   └── org
        │       └── apdplat
        │           └── service
        │               ├── api
        │               │   ├── JedisAPI.java
        │               │   └── SearchAPI.java
        │               ├── configration
        │               │   ├── ConfManager.java
        │               │   ├── ConfTools.java
        │               │   └── ConfWatcher.java
        │               ├── impl
        │               │   └── SearchAPIImpl.java
        │               └── utils
        │                   └── TimeUtils.java
        └── resources
            └── conf
                ├── conf.production.txt
                └── conf.txt

12 directories, 11 files

© 著作权归作者所有

杨尚川

杨尚川

粉丝 1103
博文 220
码字总数 1624053
作品 12
东城
架构师
私信 提问
服务持续高性能运行均衡工具--high-availability

high-availability 保障服务的持续高可用、高性能及负载均衡。 高可用: 服务多副本 高性能: 超时限制 负载均衡: 环形队列 已经实现的功能: 1. HTTP调用方式的搜索服务 2. REDIS访问 一句话说...

杨尚川
2016/09/25
1K
0
转(探讨分布式系统与集群的区别)

简单说,分布式是以缩短单个任务的执行时间来提升效率的,而集群则是通过提高单位时间内执行的任务数来提升效率。   例如:如果一个任务由10个子任务组成,每个子任务单独执行需1小时,则在...

小洋哥
2014/05/21
179
1
分布式与集群的联系与区别

一句话概括:分布式是以缩短单个任务的执行时间来提升效率的,而集群则是通过提高单位时间内执行的任务数来提升效率。 例如:如果一个任务由10个子任务组成,每个子任务单独执行需1小时,则在...

Max_zhao
2017/05/05
0
0
分布式系统与集群的区别

简单说,分布式是以缩短单个任务的执行时间来提升效率的,而集群则是通过提高单位时间内执行的任务数来提升效率。   例如:如果一个任务由10个子任务组成,每个子任务单独执行需1小时,则在...

origin
2016/12/26
44
0
微博开源轻量级 RPC 框架:Motan

概述 motan是一套高性能、易于使用的分布式远程服务调用(RPC)框架。 功能 支持通过spring配置方式集成,无需额外编写代码即可为服务提供分布式调用能力。 支持集成consul、zookeeper等配置服...

oschina
2016/04/25
41
0

没有更多内容

加载失败,请刷新页面

加载更多

golang-字符串-地址分析

demo package mainimport "fmt"func main() {str := "map.baidu.com"fmt.Println(&str, str)str = str[0:5]fmt.Println(&str, str)str = "abc"fmt.Println(&s......

李琼涛
今天
4
0
Spring Boot WebFlux 增删改查完整实战 demo

03:WebFlux Web CRUD 实践 前言 上一篇基于功能性端点去创建一个简单服务,实现了 Hello 。这一篇用 Spring Boot WebFlux 的注解控制层技术创建一个 CRUD WebFlux 应用,让开发更方便。这里...

泥瓦匠BYSocket
今天
8
0
从0开始学FreeRTOS-(列表与列表项)-3

FreeRTOS列表&列表项的源码解读 第一次看列表与列表项的时候,感觉很像是链表,虽然我自己的链表也不太会,但是就是感觉很像。 在FreeRTOS中,列表与列表项使用得非常多,是FreeRTOS的一个数...

杰杰1号
今天
9
0
Java反射

Java 反射 反射是框架设计的灵魂(使用的前提条件:必须先得到代表的字节码的 Class,Class 类 用于表示.class 文件(字节码)) 一、反射的概述 定义:JAVA 反射机制是在运行状态中,对于任...

zzz1122334
今天
7
0
聊聊nacos的LocalConfigInfoProcessor

序 本文主要研究一下nacos的LocalConfigInfoProcessor LocalConfigInfoProcessor nacos-1.1.3/client/src/main/java/com/alibaba/nacos/client/config/impl/LocalConfigInfoProcessor.java p......

go4it
昨天
9
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部