Microservice architecture case (04): middleware integration, public service encapsulation

Posted by nincha on Mon, 04 Nov 2019 22:50:33 +0100

Source code: GitHub point here || GitEE point here

Update progress (6 sections in total):

01: brief introduction of project technology selection and schematic description of structure
02: business architecture design, system hierarchical management
03: database selection, business data design and planning
04: middleware integration, public service management

I. Introduction to middleware

Middleware is a kind of basic software, which belongs to software with high reusability. Between the operating system software and the application. It is a kind of independent system software, also can be a public service program. With the help of middleware, distributed architecture system can share resources among different technologies, or different services can directly transmit information. It manages computer resources and network communication on the middleware operating system. Software that connects two independent applications or systems, such as:

  1. Message queue middleware is used to deliver messages asynchronously between two services;
  2. Data cache middleware, cache and integrate the hot data of the system, improve the response speed of the program;
  3. Nginx middleware provides load balancing, service agent and other functions;

II. Introduction to public services

Public service, as the name implies, is a general service in the system, such as user authentication, message sending, monitoring and early warning, gateway service, etc.

The middleware and public services in this case are based on the unified way of Feign interface to provide services.

III. middleware integration

1. Message middleware

  • About RocketMq

RocketMq is a distributed, queue model of message middleware, which has two core roles: Message producer and message consumer. As one of the core components of high concurrency system, it can help business system deconstruct and improve system stability.

  • Application process
  1. Message producer
@Component
public class MsgSendService {
    @Resource
    private ProducerConfig producerConfig ;
    public void sendMsg (MsgWrap msgWrap) {
        producerConfig.sendMsg(msgWrap.getGroup(),msgWrap.getTopic(),
                               msgWrap.getTag(),msgWrap.getContent());
    }
}
  1. Message consumer
@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("[User search message listening Msg]: {}",msg) ;
        // Forwarding request data analysis service
        bookEsAnalyFeign.sendBookEsMsg(msg);
    }
}
  1. Provide Feign interface
@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. Cache Middleware

  • Redis introduction

Redis is a memory based high-performance key value database. It provides support for various scenarios of high concurrency system: hot data cache, counter, traffic peak clipping, etc.

  • Application process
  1. Packaging operation method
@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. Provide Feign services
@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. Sosu Middleware

  • Introduction to ES search

ElasticSearch is a Lucene based search server. It provides a distributed multi-user full-text search engine based on RESTful web interface. Is the current popular enterprise search engine.

  • Application process
  1. Packaging operation method
@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. Provide Feign services
@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);
    }
}

Timer Middleware

  • About Quartz

Quartz is an open source task scheduling framework written by Java. It sets job timing rules through triggers to control the execution time of tasks. Through the function of failover and load balancing, quartz cluster can bring high availability and scalability to the scheduler.

  • Application process
@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("","Scheduled email notification",""+nowDate);
    }
}

IV. public service management

1. Token service

  • Token service introduction

Through a public Token management service, the identity of users accessing the system is managed: identity Token creation, verification, refresh, etc.

  • Application process
  1. Packaging operation method
@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)) {
                // Return to 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) ;
            // Judge whether the Token is expired
            String cacheToken = redisFeign.get(key) ;
            if (StringUtils.isEmpty(cacheToken)){
                return false ;
            }
            redisFeign.setTimeOut(key,token, Constant.USER_TOKEN_EXPIRE) ;
            return true ;
        }
        return false ;
    }
}
  1. Provide Feign services
@FeignClient("MOPSZ-BASIS-TOKEN")
public interface UserTokenFeign {
    /**
     * Get TOKEN
     */
    @PostMapping("/token/getToken")
    RespObject getToken (@RequestParam("userName") String userName,
                         @RequestParam("passWord") String passWord) ;
    /**
     * Verify TOKEN
     */
    @PostMapping("/token/verifyToken")
    RespObject verifyToken (@RequestParam("token") String token) ;
    /**
     * Refresh TOKEN
     */
    @PostMapping("/token/refreshToken")
    boolean refreshToken (@RequestParam("token") String token) ;
}

2. Message service

  • Introduction to Msg service

In a complex system, message notification is a necessary module. Generally, the encapsulation method starts from the following two ways: message type: user message, system message, etc., message receiving method: email, SMS, application end, etc.

  • Application process
  1. Encapsulate mail delivery
@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("Failed to send message:{}",e.getMessage());
        }
    }
}
  1. Provide Feign services
@FeignClient("MOPSZ-BASIS-MSGBOX")
public interface SendEmailFeign {
    /**
     * Send Email
     */
    @PostMapping("/msgBox/sendEmail")
    void sendEmail (@RequestParam("receive") String receive,
                      @RequestParam("title") String title,
                      @RequestParam("msg") String msg) ;
}

V. source code address

GitHub·address
https://github.com/cicadasmile/husky-spring-cloud
GitEE·address
https://gitee.com/cicadasmile/husky-spring-cloud

Topics: Programming github Database Redis Spring