Dubbo+Zookeeper

如果产品服务的业务量不是很大,业务又不是特别繁杂,功能模块的拆分颗粒度就不需要太细,也就没必要上微服务。因为微服务的运维治理复杂度及服务器资源开销代价是难以想象的。

本编简述下如何使用Dubbo+Zookeeper即可实现传统的分布式服务,并且支持高并发高可用场景下的动态扩容。


有关Dubbo的介绍,就无需多言了,它是一款高性能、轻量级的开源Java RPC框架(Remote Procedure Call Protocol 远程过程调用协议),它提供了三大核心能力:面向接口的远程方法调用,智能容错和负载均衡,以及服务自动注册和发现。

准备工作:

  1. 搭建springboot脚手架并成功运行,可参考历史分享springboot+mybatis

  2. 启动Zookeeper服务(作为Dubbo的服务注册协调中心)(搭建配置ZK服务,后续会在运维章节另行讲述)

1. maven添加Dubbo及ZK依赖

<properties>    <zk-curator.version>4.0.1</zk-curator.version></properties>    <dependencies>    <!--dubbo-->    <dependency>        <groupId>com.alibaba.boot</groupId>        <artifactId>dubbo-spring-boot-starter</artifactId>        <version>0.2.0</version>    </dependency>        <!--zookeeper-->    <dependency>        <groupId>org.apache.zookeeper</groupId>        <artifactId>zookeeper</artifactId>        <version>3.4.13</version>    </dependency>    <dependency>        <groupId>com.github.sgroschupf</groupId>        <artifactId>zkclient</artifactId>        <version>0.1</version>    </dependency>        <!--zk-lock-->    <dependency>        <groupId>org.apache.curator</groupId>        <artifactId>curator-framework</artifactId>        <version>${zk-curator.version}</version>    </dependency>    <dependency>        <groupId>org.apache.curator</groupId>        <artifactId>curator-recipes</artifactId>        <version>${zk-curator.version}</version>    </dependency></dependencies>

2.Dubbo配置

2.1 yml

#dubbodubbo:  application:    name: demo-user  registry:    address: zookeeper://192.168.2.7:2181?backup=192.168.2.8:2181,192.168.2.9:2181    file: /dubbo/demo-user/cache    protocol: zookeeper    check: false  protocol:    name: dubbo    port: 28102  scan:    base-packages: com.demo.user.service.dubbo  consumer:    check: false    timeout: 10000    retries: 0    #ZK locklock:  zk-servers: 192.168.2.7:2181,192.168.2.8:2181,192.168.2.9:2181

2.2 开启dubbo服务注解扫描

import com.alibaba.dubbo.config.spring.context.annotation.EnableDubbo;import org.springframework.boot.autoconfigure.SpringBootApplication;@EnableDubbo@SpringBootApplicationpublic class DemoUserApplication {    public static void main(String[] args) {        SpringApplication.run(DemoUserApplication.class, args);    }}

3.Dubbo调用

3.1 dubbo service provider

import lombok.extern.slf4j.Slf4j;import com.alibaba.dubbo.config.annotation.Service;@Slf4j@Service // 注意该@Service注解是alibaba包下的,不要错引用了Spring包下的public class UserDubboServiceImpl implements UserDubboService {}

3.2 dubbo service consumer

import com.alibaba.dubbo.config.annotation.Reference;import lombok.extern.slf4j.Slf4j;import org.springframework.stereotype.Service;@Slf4j@Servicepublic class OrderServiceImpl extends BaseServiceImpl<Order>         implements OrderService {            @Reference // 引用注入dubbo服务service bean     private UserDubboService userDubboService;}

4.ZK分布式锁

4.1 zk lock 配置

import lombok.extern.slf4j.Slf4j;import org.apache.curator.framework.CuratorFramework;import org.apache.curator.framework.CuratorFrameworkFactory;import org.apache.curator.framework.recipes.locks.InterProcessSemaphoreMutex;import org.apache.curator.framework.state.ConnectionState;import org.apache.curator.framework.state.ConnectionStateListener;import org.apache.curator.retry.ExponentialBackoffRetry;import org.springframework.beans.factory.InitializingBean;import org.springframework.beans.factory.annotation.Value;import org.springframework.context.annotation.Configuration;import java.util.concurrent.TimeUnit;/** * 分布式锁: * 注意该锁不能重入,即不可有嵌套锁*/@Slf4j@Configuration  // 注意该组件需被springboot扫描注册成beanpublic class DistributedLock implements InitializingBean {​    private static CuratorFramework curator = null;    private static ThreadLocal<InterProcessSemaphoreMutex> localLock = new ThreadLocal<>();    @Value("${lock.zk-servers}")    private String zkServers;    private static final String basePath = "/lock/";​

    /**
     * bean添加到spring容器后,在完成bean实例化后才会执行该方法    
    */    @Override    
    public void afterPropertiesSet() {        if (curator == null) {            curator = CuratorFrameworkFactory.builder().sessionTimeoutMs(30000).connectionTimeoutMs(30000)                    .retryPolicy(new ExponentialBackoffRetry(1000, Integer.MAX_VALUE)).connectString(zkServers).build();            curator.getConnectionStateListenable().addListener(new ZKListener());            curator.start();        }    }    /**     * 不等待,遇锁直接退出     *     * @param key     * @return     */    public static boolean acquire(String key) {        try {            InterProcessSemaphoreMutex lock = new InterProcessSemaphoreMutex(DistributedLock.curator, basePath + key);            lock.acquire();            localLock.set(lock);        } catch (Exception e) {            log.warn("DistributedLock acquire error", e);            return false;        }        return true;    }    /**     * 排队等待     *     * @param key     * @param timeout     * @return     */    public static boolean acquire(String key, long timeout) {        try {            InterProcessSemaphoreMutex lock = new InterProcessSemaphoreMutex(DistributedLock.curator, basePath + key);            lock.acquire(timeout, TimeUnit.SECONDS);            localLock.set(lock);        } catch (Exception e) {            log.warn("DistributedLock acquire error", e);            return false;        }        return true;    }    /**     * 排队等待     *     * @param key     * @param timeout     * @return     */    public static boolean acquire(String key, long timeout, TimeUnit unit) {        try {            InterProcessSemaphoreMutex lock = new InterProcessSemaphoreMutex(DistributedLock.curator, basePath + key);            lock.acquire(timeout, unit);            localLock.set(lock);        } catch (Exception e) {            log.warn("DistributedLock acquire error", e);            return false;        }        return true;    }    /**     * 释放锁     */    public static void release() {        try {            InterProcessSemaphoreMutex lock = localLock.get();            if (lock != null && lock.isAcquiredInThisProcess()) {                lock.release();            }        } catch (Exception e) {            log.warn("DistributedLock release error", e);        }    }    /**     * zk监听器     */    public class ZKListener implements ConnectionStateListener {        @Override        public void stateChanged(CuratorFramework client, ConnectionState state) {            if (ConnectionState.LOST.equals(state)) {                // 连接丢失                log.warn("==ZK LOCK== DistributedLock lost session with zookeeper");            } else if (ConnectionState.CONNECTED.equals(state)) {                // 连接新建                log.warn("==ZK LOCK== DistributedLock connected with zookeeper");            } else if (ConnectionState.RECONNECTED.equals(state)) {                // 重新连接                log.warn("==ZK LOCK== DistributedLock reconnected with zookeeper");            }        }    }    /**     * 分布式锁业务类型     */    public enum LockType {        PRODUCT_INVENTORY    }}

4.2 zk lock 使用

    // 加锁,    String lockKey = DistributedLock.LockType.PRODUCT_INVENTORY + "/" + productId;    try{        if(DistributedLock.acquire(lockKey, 3)){           // todo something 抢购排队下单,扣减商品库存        }    }catch(Exception e){        log.error("userId = {}, couponId = {}, 下单失败:{}", userId, productId, e.getMessage());        throw new Exception("下单失败", e);    }finally{        DistributedLock.release();    }    // service 方法中抛出异常,回滚事务    throw new CommonException("下单失败");

5.CAP理论

一个分布式系统最多只能同时满足一致性(Consistency)、可用性(Availability)和分区容错性(Partition tolerance)这三项中的两项,也即不可能三角CAP理论。

既然是分布式服务,自然需要具备分区容错性。除此之外,用户更多的是需要服务的可用性,至于一致性方面,目前常用的折中解决方案是,选择最终一致性​。​

以上关于后端服务常用的框架技术及一些相关中间件都已整理完毕,后续会更新基于SpringCloud Alibaba的微服务有关章节。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值