2019独角兽企业重金招聘Python工程师标准>>>

j360-microservice

spring-boot+docker微服务设计之j360-microservice:(欢迎star、fork)

https://github.com/xuminwlt/j360-microservice

前言

自从spring4发布spring boot开始,springboot非常自然的成为了spring的顶级项目,打开spring的网站,springboot也位列第二,在他爹地spring io platform后面,发展到现在springboot已经在很多场景下发挥了巨大的生产力,尤其是通过内置容器的方式,简单一个java -jar xxx.jar便可以发布该工程,随着springboot被越来越多的人使用并且推荐,包括我,springboot为微服务架构方式不再只停留在概念阶段,springboot为创建微服务架构提供了稳定的基础,作为大家耳熟能详的SOA架构,各说纷纭,微服务在我理解范围内,特别是在得到springboot的支持下,微服务更加能体现出分布式服务的精髓,微服务的颗粒度更小,作为单一的功能而言,springboot更加能快速简单的提供服务支撑。

Docker自从14年热吧热吧以来,在今年docker已经占据了所有容器板块的头条位置,docker也很努力,发展迭代马不停蹄。

从分别关注springboot和docker一开始我便一直在思考如何让两个人在一起,满足我的私欲,必须在一起,不为别的,springboot是1,docker是0.

介绍

微服务

微服务的特点是将每个单一服务能够独立提供服务,这个概念和SOA非常相似,就是所有的服务都必须提供服务的方式,在基于springboot的微服务架构中,使用restful的api是官方推荐的接口,也就是基于HTTP协议的通信方式。

微服务使用springmvc可以很好的提供rest服务,而作为客户端可以基于Spring中的RestTemplate进行创建。springboot的就是为服务方和客户端提供良好的支撑。

容器部署

使用docker可以很方便地为springboot提供容器服务,在任何安装jdk的docker环境中,springboot都可以发布。

案例

通过案例来介绍springboot和docker是一件很有意思的事情,本案例j360-microservice通过两个服务来描述快递下单和查询订单的功能,订单的底层服务交给j360-order服务,订单的查询和下单交给j360-express,通过微服务设计的高度可扩展性,j360-order同样还可以处理来源于其他的客户端发来的请求,同样j360-express可以给其他的快递公司发送请求,通过在docker中实现分布式集群部署,体现出了微服务强大的可伸缩性。

工程结构图:

演示界面:

输入快递单号,结果输出快递单的信息

部分代码演示:

j360-order:微服务服务提供方

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<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"><parent><artifactId>j360-microservice</artifactId><groupId>me.j360.boot.microservice</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>j360-order</artifactId><properties><java.version>1.7</java.version></properties><!-- Add typical dependencies for a web application --><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-rest</artifactId></dependency><!--jpa--><dependency><groupId>org.hibernate</groupId><artifactId>hibernate-entitymanager</artifactId></dependency><dependency><groupId>org.hsqldb</groupId><artifactId>hsqldb</artifactId><scope>runtime</scope></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-orm</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><!--使用SpringLoaded工具,war包可以使用,但是必须使用内置的容器,去掉private的scope--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId></dependency></dependencies><!--不是每个人都喜欢继承 spring-boot-starter-parent POM。你可能需要使用公司标准parent,或你可能倾向于显式声明所有Maven配置。如果你不使用 spring-boot-starter-parent ,通过使用一个 scope=import 的依赖,你仍能获取到依赖管理的好处--><dependencyManagement><dependencies><dependency><!-- Import dependency management from Spring Boot --><groupId>org.springframework.boot</groupId><artifactId>spring-boot-dependencies</artifactId><version>1.3.0.BUILD-SNAPSHOT</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement><!-- Package as an executable jar --><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><version>1.3.0.BUILD-SNAPSHOT</version><!--为了在Maven命令行下使用Spring Loaded,你只需将它作为一个依赖添加到Spring Boot插件声明中即可--><dependencies><dependency><groupId>org.springframework</groupId><artifactId>springloaded</artifactId><version>1.2.5.BUILD-SNAPSHOT</version></dependency></dependencies><executions><execution><goals><goal>repackage</goal></goals></execution></executions></plugin><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-surefire-plugin</artifactId><configuration><useSystemClassLoader>false</useSystemClassLoader></configuration></plugin><plugin><artifactId>maven-war-plugin</artifactId><configuration><failOnMissingWebXml>false</failOnMissingWebXml></configuration></plugin></plugins></build><!-- Additional lines to be added here... --><!-- (you don't need this if you are using a .RELEASE version) --><repositories><repository><id>spring-snapshots</id><url>http://repo.spring.io/snapshot</url><snapshots><enabled>true</enabled></snapshots></repository><repository><id>spring-milestones</id><url>http://repo.spring.io/milestone</url></repository></repositories><pluginRepositories><pluginRepository><id>spring-snapshots</id><url>http://repo.spring.io/snapshot</url></pluginRepository><pluginRepository><id>spring-milestones</id><url>http://repo.spring.io/milestone</url></pluginRepository></pluginRepositories>
</project>
package me.j360.boot.microservice.order.web;import me.j360.boot.microservice.order.entity.Express;
import me.j360.boot.microservice.order.repository.ExpressRepository;
import me.j360.boot.microservice.order.validator.ExpressValidator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.hateoas.EntityLinks;
import org.springframework.hateoas.ExposesResourceFor;
import org.springframework.hateoas.Resource;
import org.springframework.hateoas.Resources;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.*;/*** Created with j360-microservice -> me.j360.boot.microservice.order.web.* User: min_xu* Date: 2015/9/27* Time: 21:07* 说明:通过restController实现的restAPI*/
@RestController
@RequestMapping("/expresses")
public class ExpressController {private final ExpressRepository repository;private final ExpressValidator validator;@Autowiredpublic ExpressController(ExpressRepository repository,ExpressValidator validator) {this.repository = repository;this.validator = validator;}@InitBinderprotected void initBinder(WebDataBinder binder) {binder.addValidators(validator);}@RequestMapping(method = RequestMethod.GET)public Iterable findAll() {return repository.findAll();}@RequestMapping(method = RequestMethod.POST)public Express create(@RequestBody Express express) {return repository.save(express);}@RequestMapping(value = "/{id}", method = RequestMethod.GET)public Express find(@PathVariable long id) {Express detail = repository.findOne(id);if (detail == null) {throw new ExpressNotFoundException();} else {return detail;}}@ResponseStatus(HttpStatus.NOT_FOUND)static class ExpressNotFoundException extends RuntimeException {}
}
@Entity
public class Express {@Id@GeneratedValue(strategy = GenerationType.AUTO)private Long id;private BigDecimal cost;private String no;@OneToMany(mappedBy = "express",fetch = FetchType.LAZY)@OrderBy("id desc")private List<Track> tracks;public List<Track> getTracks() {return tracks;}public void setTracks(List<Track> tracks) {this.tracks = tracks;}public String getNo() {return no;}public void setNo(String no) {this.no = no;}public BigDecimal getCost() {return cost;}public void setCost(BigDecimal cost) {this.cost = cost;}public long getId() {return id;}public void setId(long id) {this.id = id;}
}

j360-deliver:用户界面,调用微服务

@Override
public Map getMap(Long id) {ResponseEntity<Express> entity =  restTemplate.getForEntity("http://localhost:8080/expresses/1",Express.class);Express express = entity.getBody();Map<String,Object> map = new HashMap<>();map.put("cost",express.getCost());return map;
}
@Aspect
@Service
public class HystrixAdvice {private static final String GROUP = "express";private static final int TIMEOUT = 60000;private static final Logger logger = LoggerFactory.getLogger(HystrixAdvice.class);/** 定义object需要转化为Object对象,此处省略@Around("execution(* me.j360.boot.microservice.service.ExpressService.findOne(..))")public Object hystrixCommand(final ProceedingJoinPoint pjp){logger.info("log Around method: "+ pjp.getTarget().getClass().getName() + "."+ pjp.getSignature().getName());List<Callable<AsyncResponse>> callables = new ArrayList<Callable<AsyncResponse>>();callables.add(new BackendServiceCallable("express", getExpressMap(pjp)));Map<String, Map<String, Object>> map = HystrixService.doBackendAsyncServiceCall(callables);try {String json = new ObjectMapper().writeValueAsString(map.get("express"));return new ObjectMapper().readValue(json,Express.class);} catch (IOException e) {e.printStackTrace();}return null;}*/@Around("execution(* me.j360.boot.microservice.service.ExpressService.getMap(..))")public Map<String, Object> hystrixCommandMap(final ProceedingJoinPoint pjp){logger.info("log Around method: "+ pjp.getTarget().getClass().getName() + "."+ pjp.getSignature().getName());List<Callable<AsyncResponse>> callables = new ArrayList<Callable<AsyncResponse>>();callables.add(new BackendServiceCallable("express", getExpressMap(pjp)));Map<String, Map<String, Object>> map = HystrixService.doBackendAsyncServiceCall(callables);return  map.get("express");}@Cacheableprivate HystrixCommand<Map<String, Object>> getExpressMap(final ProceedingJoinPoint pjp) {return new HystrixCommand<Map<String, Object>>(HystrixCommand.Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey(GROUP)).andCommandKey(HystrixCommandKey.Factory.asKey("getExpressMap")).andCommandPropertiesDefaults(HystrixCommandProperties.Setter().withExecutionIsolationThreadTimeoutInMilliseconds(TIMEOUT))) {@Overrideprotected Map<String, Object> run() throws Exception {try {return (Map<String, Object>) pjp.proceed();} catch (Throwable throwable) {throwable.printStackTrace();}return new HashMap<String, Object>();}@Overrideprotected Map getFallback() {return new HashMap<String, Object>();}};}}
@Controller
public class ExpressController {@Autowiredprivate ExpressService expressService;@RequestMapping(value = "/",method = RequestMethod.GET)public String index() {return "index";}@RequestMapping(value = "/express",method = RequestMethod.GET)public String express(Model model) {Map<String,Object>  map = expressService.getMap(1l);model.addAttribute("express",map);return "index";}}

此处演示用的是写死的id查找,需要单号需要再封装一个单号查询方法即可。

部署Docker

1、通过maven package分别生成对应的jar文件

2、如果使用docker maven的话,在docker中安装git+maven直接生成jar也可以,这里涉及到持续集成的过程,略过

参考:

Daniel Woods是一位技术狂热者,尤其是在企业级的Java、Groovy,和Grails开发方面。他在JVM软件开发方面已经具有超过十年以上的经验,并且通过对Grails和Ratpack web框架这样的开源项目进行贡献的方式分享他的经验。Dan也是Gr8conf和SpringOne 2GX会议上的演讲者,他在会议上展现了他在JVM的企业级应用架构上的专业知识。

http://www.infoq.com/cn/articles/boot-microservices

转载于:https://my.oschina.net/smartsales/blog/511534

Spring Boot+Docker微服务分布式服务架构设计和部署案例相关推荐

  1. (二)spring cloud微服务分布式云架构 - 整合企业架构的技术点

    spring cloud本身提供的组件就很多,但我们需要按照企业的业务模式来定制企业所需要的通用架构,那我们现在需要考虑使用哪些技术呢? 下面我针对于spring cloud微服务分布式云架构做了以下 ...

  2. Spring Cloud企业微服务分布式云架构技术点整合

    spring cloud本身提供的组件就很多,但我们需要按照企业的业务模式来定制企业所需要的通用架构... 下面我针对于spring cloud微服务分布式云架构做了以下技术总结,希望可以帮助到大家: ...

  3. spring cloud微服务分布式云架构 - 整合企业架构的技术点

    spring cloud本身提供的组件就很多,但我们需要按照企业的业务模式来定制企业所需要的通用架构,那我们现在需要考虑使用哪些技术呢? 下面我针对于spring cloud微服务分布式云架构做了以下 ...

  4. 一文读懂 Spring Boot、微服务架构和大数据治理三者之间的故事

    微服务架构 微服务的诞生并非偶然,它是在互联网高速发展,技术日新月异的变化以及传统架构无法适应快速变化等多重因素的推动下诞生的产物.互联网时代的产品通常有两类特点:需求变化快和用户群体庞大,在这种情况 ...

  5. (二)微服务分布式云架构 - spring cloud整合企业架构的技术点

    spring cloud本身提供的组件就很多,但我们需要按照企业的业务模式来定制企业所需要的通用架构,那我们现在需要考虑使用哪些技术呢? 下面我针对于spring cloud微服务分布式云架构做了以下 ...

  6. (二)spring cloud微服务分布式云架构-整合企业架构的技术点

    spring cloud本身提供的组件就很多,但我们需要按照企业的业务模式来定制企业所需要的通用架构,那我们现在需要考虑使用哪些技术呢?Spring Cloud大型企业分布式微服务云架构源码请加一七九 ...

  7. 一文透析 Spring Boot、微服务架构和大数据治理三者之间的故事

    微服务架构 微服务的诞生并非偶然,它是在互联网高速发展,技术日新月异的变化以及传统架构无法适应快速变化等多重因素的推动下诞生的产物.互联网时代的产品通常有两类特点:需求变化快和用户群体庞大,在这种情况 ...

  8. Spring Cloud与微服务学习总结(8)——Spring Boot、微服务架构和大数据治理三者之间的故事

    前言 微服务的诞生并非偶然,它是在互联网高速发展,技术日新月异的变化以及传统架构无法适应快速变化等多重因素的推动下诞生的产物.互联网时代的产品通常有两类特点:需求变化快和用户群体庞大,在这种情况下,如 ...

  9. spring cloud微服务分布式云架构-整合企业架构的技术点

    spring cloud本身提供的组件就很多,但我们需要按照企业的业务模式来定制企业所需要的通用架构,那我们现在需要考虑使用哪些技术呢?完整项目的源码来源 技术支持一七九一七四三三八零 下面我针对于s ...

最新文章

  1. 17综合案例之淘宝轮播图布局
  2. 重学ES6 函数的扩展(下)
  3. 云技术概况:云计算的优点/特点/类型/服务模式
  4. 笔记本电脑排行_笔记本电脑性价比排行2020
  5. 【Android面试】Android面试题集锦 (陆续更新)
  6. fastapi学习(二):路径参数获取与GET、POST参数获取
  7. chackbox的值 php获取_PHP操作Redis数据库常用方法
  8. keil5 字体颜色设置 背景黑色
  9. 邻接矩阵计算matlab计算,急求各位大神帮忙解决,下面这个邻接矩阵算出它的可达矩阵...
  10. 最伟大的IT人物10强(转)
  11. Wifi热点java_Wifi热点实现文件传输
  12. 使用Andriod Device Moniter时用正则表达式筛选指定日志
  13. python3 socket TCP 服务器 一对多转发信息
  14. Sublime插件安装与提高Verilog编写效率插件推荐
  15. 高级筛选条件为系别为计算机或者数学,电子表格中的高级筛选.doc
  16. STM32F0的BOOT
  17. <Zhuuu_ZZ>HIVE(终)总结大全:是兄弟就来三连我
  18. TypeScript故事—如何使用TypeScript在NPM上发布自定义钩子
  19. 经济学术语解析(一)
  20. 竞争性排斥原理(高斯假说)

热门文章

  1. 5.15 pymysql 模块
  2. 华人“军火专家”——黄仁勋
  3. SDWebImage中文说明
  4. RCP中product文件的用法
  5. Linux多台服务器共用密钥ssh自动登陆
  6. flannel 的连通与隔离 - 每天5分钟玩转 Docker 容器技术(61)
  7. openSUSE 11.2 中文输入法 SCIM 安装
  8. Oracle并行进程小结
  9. 来自mooon的最简单的日志类CSimpleLogger
  10. Visual Studio 2019 16.1 第二个预览版发布