700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > Spring Boot+Docker微服务分布式服务架构设计和部署案例

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

时间:2019-01-31 08:26:01

相关推荐

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

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

j360-microservice

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

/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自从热吧热吧以来,在今年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

<?xmlversion="1.0"encoding="UTF-8"?><projectxmlns="/POM/4.0.0"xmlns:xsi="/2001/XMLSchema-instance"xsi:schemaLocation="/POM/4.0.0/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><!--Addtypicaldependenciesforawebapplication--><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-parentPOM。你可能需要使用公司标准parent,或你可能倾向于显式声明所有Maven配置。如果你不使用spring-boot-starter-parent,通过使用一个scope=import的依赖,你仍能获取到依赖管理的好处--><dependencyManagement><dependencies><dependency><!--ImportdependencymanagementfromSpringBoot--><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><!--Packageasanexecutablejar--><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><version>1.3.0.BUILD-SNAPSHOT</version><!--为了在Maven命令行下使用SpringLoaded,你只需将它作为一个依赖添加到SpringBoot插件声明中即可--><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><!--Additionallinestobeaddedhere...--><!--(youdon'tneedthisifyouareusinga.RELEASEversion)--><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>

packageme.j360.boot.microservice.order.web;importme.j360.boot.microservice.order.entity.Express;importme.j360.boot.microservice.order.repository.ExpressRepository;importme.j360.boot.microservice.order.validator.ExpressValidator;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.hateoas.EntityLinks;importorg.springframework.hateoas.ExposesResourceFor;importorg.springframework.hateoas.Resource;importorg.springframework.hateoas.Resources;importorg.springframework.http.HttpEntity;importorg.springframework.http.HttpStatus;importorg.springframework.http.ResponseEntity;importorg.springframework.stereotype.Controller;importorg.springframework.web.bind.WebDataBinder;importorg.springframework.web.bind.annotation.*;/***Createdwithj360-microservice->me.j360.boot.microservice.order.web.*User:min_xu*Date:/9/27*Time:21:07*说明:通过restController实现的restAPI*/@RestController@RequestMapping("/expresses")publicclassExpressController{privatefinalExpressRepositoryrepository;privatefinalExpressValidatorvalidator;@AutowiredpublicExpressController(ExpressRepositoryrepository,ExpressValidatorvalidator){this.repository=repository;this.validator=validator;}@InitBinderprotectedvoidinitBinder(WebDataBinderbinder){binder.addValidators(validator);}@RequestMapping(method=RequestMethod.GET)publicIterablefindAll(){returnrepository.findAll();}@RequestMapping(method=RequestMethod.POST)publicExpresscreate(@RequestBodyExpressexpress){returnrepository.save(express);}@RequestMapping(value="/{id}",method=RequestMethod.GET)publicExpressfind(@PathVariablelongid){Expressdetail=repository.findOne(id);if(detail==null){thrownewExpressNotFoundException();}else{returndetail;}}@ResponseStatus(HttpStatus.NOT_FOUND)staticclassExpressNotFoundExceptionextendsRuntimeException{}}

@EntitypublicclassExpress{@Id@GeneratedValue(strategy=GenerationType.AUTO)privateLongid;privateBigDecimalcost;privateStringno;@OneToMany(mappedBy="express",fetch=FetchType.LAZY)@OrderBy("iddesc")privateList<Track>tracks;publicList<Track>getTracks(){returntracks;}publicvoidsetTracks(List<Track>tracks){this.tracks=tracks;}publicStringgetNo(){returnno;}publicvoidsetNo(Stringno){this.no=no;}publicBigDecimalgetCost(){returncost;}publicvoidsetCost(BigDecimalcost){this.cost=cost;}publiclonggetId(){returnid;}publicvoidsetId(longid){this.id=id;}}

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

@OverridepublicMapgetMap(Longid){ResponseEntity<Express>entity=restTemplate.getForEntity("http://localhost:8080/expresses/1",Express.class);Expressexpress=entity.getBody();Map<String,Object>map=newHashMap<>();map.put("cost",express.getCost());returnmap;}

@Aspect@ServicepublicclassHystrixAdvice{privatestaticfinalStringGROUP="express";privatestaticfinalintTIMEOUT=60000;privatestaticfinalLoggerlogger=LoggerFactory.getLogger(HystrixAdvice.class);/**定义object需要转化为Object对象,此处省略@Around("execution(*me.j360.boot.microservice.service.ExpressService.findOne(..))")publicObjecthystrixCommand(finalProceedingJoinPointpjp){logger.info("logAroundmethod:"+pjp.getTarget().getClass().getName()+"."+pjp.getSignature().getName());List<Callable<AsyncResponse>>callables=newArrayList<Callable<AsyncResponse>>();callables.add(newBackendServiceCallable("express",getExpressMap(pjp)));Map<String,Map<String,Object>>map=HystrixService.doBackendAsyncServiceCall(callables);try{Stringjson=newObjectMapper().writeValueAsString(map.get("express"));returnnewObjectMapper().readValue(json,Express.class);}catch(IOExceptione){e.printStackTrace();}returnnull;}*/@Around("execution(*me.j360.boot.microservice.service.ExpressService.getMap(..))")publicMap<String,Object>hystrixCommandMap(finalProceedingJoinPointpjp){logger.info("logAroundmethod:"+pjp.getTarget().getClass().getName()+"."+pjp.getSignature().getName());List<Callable<AsyncResponse>>callables=newArrayList<Callable<AsyncResponse>>();callables.add(newBackendServiceCallable("express",getExpressMap(pjp)));Map<String,Map<String,Object>>map=HystrixService.doBackendAsyncServiceCall(callables);returnmap.get("express");}@CacheableprivateHystrixCommand<Map<String,Object>>getExpressMap(finalProceedingJoinPointpjp){returnnewHystrixCommand<Map<String,Object>>(HystrixCommand.Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey(GROUP)).andCommandKey(HystrixCommandKey.Factory.asKey("getExpressMap")).andCommandPropertiesDefaults(HystrixCommandProperties.Setter().withExecutionIsolationThreadTimeoutInMilliseconds(TIMEOUT))){@OverrideprotectedMap<String,Object>run()throwsException{try{return(Map<String,Object>)pjp.proceed();}catch(Throwablethrowable){throwable.printStackTrace();}returnnewHashMap<String,Object>();}@OverrideprotectedMapgetFallback(){returnnewHashMap<String,Object>();}};}}

@ControllerpublicclassExpressController{@AutowiredprivateExpressServiceexpressService;@RequestMapping(value="/",method=RequestMethod.GET)publicStringindex(){return"index";}@RequestMapping(value="/express",method=RequestMethod.GET)publicStringexpress(Modelmodel){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和Ratpackweb框架这样的开源项目进行贡献的方式分享他的经验。Dan也是Gr8conf和SpringOne 2GX会议上的演讲者,他在会议上展现了他在JVM的企业级应用架构上的专业知识。

/cn/articles/boot-microservices

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。