在前后端分离架构中,服务层被拆分成了很多的微服务,微服务的信息如何管理?SpringCloud中提供服务注册中心来管理微服务信息。为什么要用注册中心?1、微服务数量众多,要进行远程调用就需要知道服务端的ip地址和端口,注册中心帮助我们管理这些服务的ip和端口。2、微服务会实时上报自己的状态,注册中心统一管理这些微服务的状态,将存在问题的服务踢出服务列表,客户端获取到可用的服务进行调用。
SpringCloudEureka是对Netflix公司的Eureka的二次封装,它实现了服务治理的功能,SpringCloudEureka提供服务端与客户端,服务端即是Eureka服务注册中心,客户端完成微服务向Eureka服务的注册与发现。服务端和客户端均采用Java语言编写。下图显示了EurekaServer与EurekaClient的关系:
1、EurekaServer是服务端,负责管理各各微服务结点的信息和状态。
2、在微服务上部署EurekaClient程序,远程访问EurekaServer将自己注册在EurekaServer。3、微服务需要调用另一个微服务时从EurekaServer中获取服务调用地址,进行远程调用。
EurekaServer高可用环境需要部署两个Eurekaserver,它们互相向对方注册。如果在本机启动两个Eureka需要注意两个EurekaServer的端口要设置不一样,这里我们部署一个EurekaServer工程,将端口可配置,制作两个EurekaServer启动脚本,启动不同的端口,如下图:
包结构:com.xuecheng.govern.center
在EurekaServer工程添加:
启动2:
在前后端分离架构中,服务层被拆分成了很多的微服务,服务与服务之间难免发生交互,比如:课程发布需要调用CMS服务生成课程静态化页面,本节研究微服务远程调用所使用的技术。下图是课程管理服务远程调用CMS服务的流程图:
工作流程如下:
1、cms服务将自己注册到注册中心。2、课程管理服务从注册中心获取cms服务的地址。3、课程管理服务远程调用cms服务。
负载均衡是微服务架构中必须使用的技术,通过负载均衡来实现系统的高可用、集群扩容等功能。负载均衡可通过硬件设备及软件来实现,硬件比如:F5、Array等,软件比如:LVS、Nginx等。如下图是负载均衡的架构图:
上图是服务端负载均衡,客户端负载均衡与服务端负载均衡的区别在于客户端要维护一份服务列表,Ribbon从EurekaServer获取服务列表,Ribbon根据负载均衡算法直接请求到具体的微服务,中间省去了负载均衡服务。如下图是Ribbon负载均衡的流程图:
1、在消费微服务中使用Ribbon实现负载均衡,Ribbon先从EurekaServer中获取服务列表。2、Ribbon根据负载均衡的算法去调用微服务。
1、在客户端添加Ribbon依赖:这里在课程管理服务配置ribbon依赖
1)启动两个cms服务,注意端口要不一致
2)定义RestTemplate,使用@LoadBalanced注解在课程管理服务的启动类中定义RestTemplate
@Bean@LoadBalancedpublicRestTemplaterestTemplate(){returnnewRestTemplate(newOkHttp3ClientHttpRequestFactory());}3)测试代码在课程管理服务工程创建单元测试代码,远程调用cms的查询页面接口:
Feign是Netflix公司开源的轻量级rest客户端,使用Feign可以非常方便的实现Http客户端。SpringCloud引入Feign并且集成了Ribbon实现客户端负载均衡调用。
1、在客户端添加依赖在课程管理服务添加下边的依赖:
@FeignClient(value=XcServiceList.XC_SERVICE_MANAGE_CMS)publicinterfaceCmsPageClient{@GetMapping("/cms/page/get/{id}")publicCmsPagefindById(@PathVariable("id")Stringid);}3、启动类添加@EnableFeignClients注解
4、测试
@RunWith(SpringRunner.class)@SpringBootTestpublicclassFeignTest{@AutowiredCmsPageClientcmsPageClient;@TestpublicvoidtestFeign(){//通过服务id调用cms的查询页面接口CmsPagecmsPage=cmsPageClient.findById("5a754adf6abb500ad05688d9");System.out.println(cmsPage);}}Feign工作原理如下:1、启动类添加@EnableFeignClients注解,Spring会扫描标记了@FeignClient注解的接口,并生成此接口的代理对象2、@FeignClient(value=XcServiceList.XC_SERVICE_MANAGE_CMS)即指定了cms的服务名称,Feign会从注册中心获取cms服务列表,并通过负载均衡算法进行服务调用。3、在接口方法中使用注解@GetMapping("/cms/page/get/{id}"),指定调用的url,Feign将根据url进行远程调用。
我们在编写一个页面时需要知道哪些信息是静态信息,哪些信息为动态信息,下图是页面的设计图:
1、配置静态资源虚拟主机静态资源虚拟主机负责处理课程详情、公司信息、老师信息、统计信息等页面的请求:将课程资料中的“静态页面目录”中的目录拷贝到F:/develop/xuecheng/static下在nginx中配置静态虚拟主机如下:
#静态资源服务upstreamstatic_server_pool{server127.0.0.1:91weight=10;}门户静态资源路径门户中的一些图片、样式等静态资源统一通过/static路径对外提供服务,在www.xuecheng.com虚拟主机中配置如下:
1、响应结果类型
@Data@ToString@NoArgsConstructorpublicclassCourseViewimplementsSerializable{CourseBasecourseBase;//基础信息CourseMarketcourseMarket;//课程营销CoursePiccoursePic;//课程图片TeachplanNodeTeachplanNode;//教学计划}2、请求类型
String:课程id
3、接口定义如下
@ApiOperation("课程视图查询")publicCourseViewcourseview(Stringid);Dao需要对course_base、course_market、course_pic、teachplan等信息进行查询,新建课程营销的dao,其它dao已经存在不用再建。
使用test-freemarker工程测试模板编写模板过程采用test-freemarker工程测试模板。将course.ftl拷贝到test-freemarker工程的resources/templates下,并在test-freemarker工程的controller中添加测试方法
第一步:将模板文件上传到GridFS中由于本教学项目中模板管理模块没有开发,所以我们使用Junit代码向GridFS中保存:
//文件存储2@TestpublicvoidtestStore2()throwsFileNotFoundException{Filefile=newFile("C:\\Users\\admin\\Desktop\\course.ftl");FileInputStreaminputStream=newFileInputStream(file);//保存模版文件内容GridFSFilegridFSFile=gridFsTemplate.store(inputStream,"课程详情模板文件","");StringfileId=gridFSFile.getId().toString();System.out.println(fileId);}保存成功需要记录模板文件的id,即上边代码中的fileId。第二步:向cms_template表添加模板记录(请不要重复添加)使用Studio3T连接mongodb,向cms_template添加记录:
课程预览功能将使用cms系统提供的页面预览功能,业务流程如下:1、用户进入课程管理页面,点击课程预览,请求到课程管理服务2、课程管理服务远程调用cms添加页面接口向cms添加课程详情页面3、课程管理服务得到cms返回课程详情页面id,并拼接生成课程预览Url4、课程管理服务将课程预览Url给前端返回5、用户在前端页面请求课程预览Url,打开新窗口显示课程详情内容
CMS已经提供了页面预览功能,课程预览功能要使用CMS页面预览接口实现,下边通过cms页面预览接口测试课程预览的效果。1、向cms_page表插入一条页面记录或者从cms_page找一个页面进行测试。注意:页面配置一定要正确,需设置正确的模板id和dataUrl。如下,是一条页面的记录。
由于Nginx先请求cms的课程预览功能得到html页面,再解析页面中的ssi标签,这里必须保证cms页面预览返回的页面的Content-Type为text/html;charset=utf-8在cms页面预览的controller方法中添加:
cms服务对外提供添加页面接口,实现:如果不存在页面则添加,否则就更新页面信息。此接口由课程管理服务在课程预览时调用。
@ApiOperation("保存页面")publicCmsPageResultsave(CmsPagecmsPage);Service//添加页面,如果已存在则更新页面publicCmsPageResultsave(CmsPagecmsPage){//校验页面是否存在,根据页面名称、站点Id、页面webpath查询CmsPagecmsPage1=cmsPageRepository.findByPageNameAndSiteIdAndPageWebPath(cmsPage.getPageName(),cmsPage.getSiteId(),cmsPage.getPageWebPath());if(cmsPage1!=null){//更新returnthis.update(cmsPage1.getPageId(),cmsPage);}else{//添加returnthis.add(cmsPage);}}Controller@Override@PostMapping("/save")publicCmsPageResultsave(@RequestBodyCmsPagecmsPage){returnpageService.save(cmsPage);}课程预览服务端Api定义此Api是课程管理前端请求服务端进行课程预览的Api请求:课程Id响应:课程预览Url
1、定义响应类型
@Data@ToString@NoArgsConstructorpublicclassCoursePublishResultextendsResponseResult{StringpreviewUrl;publicCoursePublishResult(ResultCoderesultCode,StringpreviewUrl){super(resultCode);this.previewUrl=previewUrl;}}2、接口定义如下
@ApiOperation("预览课程")publicCoursePublishResultpreview(Stringid);创建FeignClient在课程管理工程创建CMS服务的FeignClient,通过此Client远程请求cms添加页面。
@FeignClient(value=XcServiceList.XC_SERVICE_MANAGE_CMS)publicinterfaceCmsPageClient{//保存页面@PostMapping("/cms/page/save")publicCmsPageResultsave(@RequestBodyCmsPagecmsPage);}