前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >微服务架构案例(04):中间件集成,公共服务封装

微服务架构案例(04):中间件集成,公共服务封装

作者头像
知了一笑
发布2019-11-06 11:40:47
1.3K0
发布2019-11-06 11:40:47
举报
文章被收录于专栏:知了一笑

一、中间件简介

中间件是基础软件的一类, 属于复用性极高的软件。处于操作系统软件与应用程序的之间。是一种独立的系统软件,也可以是公共的服务程序,分布式架构系统借助中间件,可以在不同的技术之间共享资源,或者不同的服务直接传递信息。中间件位操作系统之上,管理计算机资源和网络通讯。是连接两个独立应用程序或独立系统的软件,例如:

  1. 消息队列中间件,在两个服务之间进行异步的消息传递;
  2. 数据缓存中间件,缓存整合系统的热点数据,提高程序的响应速度;
  3. Nginx中间件,提供负载均衡,服务代理,等功能;

二、公共服务简介

公共服务,顾名思义就是系统内通用的服务,例如用户身份验证,消息发送,监控预警,网关服务等。

该案例的中间件和公共服务,都是基于Feign接口统一的方式提供服务。

三、中间件集成

1、消息中间件

  • RocketMq简介

RocketMq 是一款分布式、队列模型的消息中间件,有两个核心角色:消息生产者和消息消费者。作为高并发系统的核心组件之一,能够帮助业务系统解构提高系统稳定性。

  • 应用流程
  1. 消息生产者
代码语言:javascript
复制
@Component
public class MsgSendService {
    @Resource
    private ProducerConfig producerConfig ;
    public void sendMsg (MsgWrap msgWrap) {
        producerConfig.sendMsg(msgWrap.getGroup(),msgWrap.getTopic(),
                               msgWrap.getTag(),msgWrap.getContent());
    }
}
  1. 消息消费者
代码语言:javascript
复制
@Component
@Consumer(group = MsgRoute.husky_group_1,
          topic = MsgRoute.husky_topic_1 ,
          tag = MsgRoute.husky_tag_1)
public class UserSearchListener implements MsgReadService {
    @Resource
    private BookEsAnalyFeign bookEsAnalyFeign ;
    @Override
    public void readMsg(String msg) throws Exception {
        LOGGER.info("【用户搜索消息监听 Msg】:{}",msg) ;
        // 转发请求数据分析服务
        bookEsAnalyFeign.sendBookEsMsg(msg);
    }
}
  1. 提供Feign接口
代码语言:javascript
复制
@RestController
public class UserSearchController implements UserSearchFeign {
    @Resource
    private SendMsgService sendMsgService ;
    @Override
    public void sendBookSearch(String msgContent) {
        MsgWrap msgWrap = new MsgWrap() ;
        msgWrap.setContent(msgContent);
        msgWrap.setGroup(MsgRoute.husky_group_1);
        msgWrap.setTopic(MsgRoute.husky_topic_1);
        msgWrap.setTag(MsgRoute.husky_tag_1);
        sendMsgService.sendMsg(msgWrap);
    }
}

2、缓存中间件

  • Redis简介

Redis 是一个基于内存的高性能key-value数据库。对高并发系统提供各种场景的支撑:热点数据缓存,计数器,流量削峰等。

  • 应用流程
  1. 封装操作方法
代码语言:javascript
复制
@Service
public class RedisServiceImpl implements RedisService {
    @Resource
    private RedisTemplate<Object,Object> redisTemplate ;
    @Override
    public boolean set(Object key, Object value) {
        boolean redisFlag = true ;
        try {
            redisTemplate.opsForValue().set(key,value);
        } catch (Exception e){
            redisFlag = false ;
            e.printStackTrace();
        }
        return redisFlag ;
    }
    @Override
    public boolean set(Object key,Object value, long expire) {
        boolean redisFlag = true ;
        try {
            redisTemplate.opsForValue().set(key,value,expire,TimeUnit.SECONDS);
        } catch (Exception e){
            redisFlag = false ;
            e.printStackTrace();
        }
        return redisFlag ;
    }
    @Override
    public String get(Object key) {
        String value = null ;
        try {
            value = String.valueOf(redisTemplate.opsForValue().get(key)) ;
        } catch (Exception e){
            e.printStackTrace();
        }
        return value ;
    }
}
  1. 提供Feign服务
代码语言:javascript
复制
@RestController
public class RedisController implements RedisFeign {
    @Resource
    private RedisService redisService ;
    @Override
    public boolean set (String key, String value) {
        return redisService.set(key,value) ;
    }
    @Override
    public boolean setTimeOut (String key, String value,long expire){
        return redisService.set(key,value,expire) ;
    }
    @Override
    public String get (String key) {
        return redisService.get(key) ;
    }
}

3、搜素中间件

  • ES搜索简介

ElasticSearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful的 web接口。是当前流行的企业级搜索引擎。

  • 应用流程
  1. 封装操作方法
代码语言:javascript
复制
@Service
public class BookInfoEsServiceImpl implements BookInfoEsService {
    @Resource
    private BookInfoRepository bookInfoRepository ;
    @Override
    public void batchSave(List<EsBookInfo> bookInfoList) {
        bookInfoRepository.saveAll(bookInfoList) ;
    }
    @Override
    public List<EsBookInfo> queryList() {
        Iterable<EsBookInfo> bookInfoIterable = bookInfoRepository.findAll() ;
        List<EsBookInfo> esBookInfoList = Lists.newArrayList(bookInfoIterable) ;
        if (esBookInfoList == null){
            esBookInfoList = new ArrayList<>() ;
        }
        return esBookInfoList;
    }
    @Override
    public List<EsBookInfo> getByKeyWord(String keyWord) {
        QueryStringQueryBuilder builder = new QueryStringQueryBuilder(keyWord);
        Iterable<EsBookInfo> bookInfoIterable = bookInfoRepository.search(builder) ;
        List<EsBookInfo> esBookInfoList = Lists.newArrayList(bookInfoIterable) ;
        if (esBookInfoList == null){
            esBookInfoList = new ArrayList<>() ;
        }
        return esBookInfoList ;
    }
}
  1. 提供Feign服务
代码语言:javascript
复制
@RestController
public class BookInfoEsController implements BookInfoEsFeign {
    @Resource
    private BookInfoEsService bookInfoEsService ;
    @Override
    public void batchSave(List<EsBookInfo> bookInfoList) {
        bookInfoEsService.batchSave(bookInfoList);
    }
    @Override
    public List<EsBookInfo> queryList() {
        return bookInfoEsService.queryList();
    }
    @Override
    public List<EsBookInfo> getByKeyWord(String keyWord) {
        return bookInfoEsService.getByKeyWord(keyWord);
    }
}

4、定时器中间件

  • Quartz 简介

Quartz是由Java编写的开源任务调度的框架,通过触发器设置作业定时运行规则,控制任务的执行时间。其中quartz集群通过故障切换和负载平衡的功能,能给调度器带来高可用性和伸缩性。

  • 应用流程
代码语言:javascript
复制
@Component("SendMsgJob")
public class SendMsgJob implements TaskJobService {
    @Resource
    private SendEmailFeign sendEmailFeign ;
    @Override
    public void run(String param) {
        String nowDate = TimeUtil.formatDate(new Date(),TimeUtil.FORMAT_01) ;
        LOGGER.info("SendMsgJob Execute Time:{}",nowDate);
        sendEmailFeign.sendEmail("","定时邮件通知",""+nowDate);
    }
}

四、公共服务管理

1、Token服务

  • Token服务简介

通过一个公共的Token管理服务,对访问系统的用户身份做管理:身份令牌创建,校验,刷新等。

  • 应用流程
  1. 封装操作方法
代码语言:javascript
复制
@Service
public class UserTokenServiceImpl implements UserTokenService {
    @Resource
    private UserBaseMapper userBaseMapper ;
    @Resource
    private RedisFeign redisFeign ;
    @Override
    public String getToken(String userName, String passWord) throws Exception {
        UserBaseExample example = new UserBaseExample() ;
        example.createCriteria().andUserNameEqualTo(userName) ;
        UserBase userBase = selectByExample(example) ;
        if (userBase != null){
            String secrete = userBase.getPassWord() ;
            if (secrete.equals(passWord)) {
                // 返回 Token
                String value = userBase.getId().toString() ;
                String publicKeyStr = RsaCryptUtil.getKey(RsaCryptUtil.PUB_KEY) ;
                String token = RsaCryptUtil.encrypt(RsaCryptUtil.createPublicKey(publicKeyStr),value.getBytes()) ;
                String key = RedisUtil.formatUserTokenKey(userBase.getId()) ;
                redisFeign.setTimeOut(key,token, Constant.USER_TOKEN_EXPIRE) ;
                return token ;
            }
        }
        return null;
    }
    @Override
    public Integer verifyToken(String token) throws Exception {
        String privateKeyStr = RsaCryptUtil.getKey(RsaCryptUtil.PRI_KEY) ;
        String userId = RsaCryptUtil.decrypt(RsaCryptUtil.createPrivateKey(privateKeyStr),
                             RsaCryptUtil.parseBase64Binary(token));
        return Integer.parseInt(userId) ;
    }
    @Override
    public boolean refreshToken(String token) throws Exception {
        Integer userId = verifyToken(token) ;
        if (userId > 0 ){
            String key = RedisUtil.formatUserTokenKey(userId) ;
            // 判断Token 是否过期
            String cacheToken = redisFeign.get(key) ;
            if (StringUtils.isEmpty(cacheToken)){
                return false ;
            }
            redisFeign.setTimeOut(key,token, Constant.USER_TOKEN_EXPIRE) ;
            return true ;
        }
        return false ;
    }
}
  1. 提供Feign服务
代码语言:javascript
复制
@FeignClient("MOPSZ-BASIS-TOKEN")
public interface UserTokenFeign {
    /**
     * 获取 TOKEN
     */
    @PostMapping("/token/getToken")
    RespObject getToken (@RequestParam("userName") String userName,
                         @RequestParam("passWord") String passWord) ;
    /**
     * 验证 TOKEN
     */
    @PostMapping("/token/verifyToken")
    RespObject verifyToken (@RequestParam("token") String token) ;
    /**
     * 刷新 TOKEN
     */
    @PostMapping("/token/refreshToken")
    boolean refreshToken (@RequestParam("token") String token) ;
}

2、消息服务

  • Msg服务简介

在一个复杂的系统中,消息通知是一个必备模块,一般封装方式主要从下面两个方式入手,消息类型:用户消息,系统消息等,消息接收方式:邮件,短信,应用端等。

  • 应用流程
  1. 封装邮件发送
代码语言:javascript
复制
@Service
public class SendEmailServiceImpl implements SendEmailService {
    @Override
    public void sendEmail(String receive, String title, String msg) {
        try {
            EmailUtil.sendEmail01(receive,title,msg);
        } catch (Exception e){
            e.printStackTrace() ;
            LOGGER.info("邮件发送失败:{}",e.getMessage());
        }
    }
}
  1. 提供Feign服务
代码语言:javascript
复制
@FeignClient("MOPSZ-BASIS-MSGBOX")
public interface SendEmailFeign {
    /**
     * 发送Email
     */
    @PostMapping("/msgBox/sendEmail")
    void sendEmail (@RequestParam("receive") String receive,
                      @RequestParam("title") String title,
                      @RequestParam("msg") String msg) ;
}

五、源代码地址

代码语言:javascript
复制
GitHub·地址
https://github.com/cicadasmile/husky-spring-cloud
GitEE·地址
https://gitee.com/cicadasmile/husky-spring-cloud
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-11-05,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 知了一笑 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 二、公共服务简介
  • 三、中间件集成
    • 1、消息中间件
      • 2、缓存中间件
        • 3、搜素中间件
          • 4、定时器中间件
          • 四、公共服务管理
            • 1、Token服务
              • 2、消息服务
              • 五、源代码地址
              相关产品与服务
              云数据库 Redis®
              腾讯云数据库 Redis®(TencentDB for Redis®)是腾讯云打造的兼容 Redis 协议的缓存和存储服务。丰富的数据结构能帮助您完成不同类型的业务场景开发。支持主从热备,提供自动容灾切换、数据备份、故障迁移、实例监控、在线扩容、数据回档等全套的数据库服务。
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档