问题背景:由于之前的项目赶的匆忙,所以把所有功能的代码都整合在了一起,以致于耦合度太高,造成了牵一发动全身的情况,所以现在时间相对充分,就将之前的项目拆分成微服务管理。
原项目其实并非springboot项目,而是Spring项目,因为要拆出来做成springBoot,这里就不说Spring的事情了。
最终项目结构:
我这里只做个demo,所以在原项目基础上做的,这里拆出来了三个module分别为注册中心,服务提供者和服务调用者。所谓SpringCloud微服务,就要每一个模块都要成为独立的服务,各自运行,互不影响才可以,之前互通数据通过调用接口完成,下面详细介绍一下三个模块:
注册中心eureka
注册中心也是一个独立运行的服务,它的任务就是作为一个总中心,一个地址薄,它让服务调用者和提供者并不需要知道谁是谁,对于调用者来说,对上暗号就行了,只要你暗号对了,我就在你这拿我需要的东西,至于你是谁,换没换人,几个人,我都不管,反正我只管去注册中心拿对上暗号的人的地址,要东西。而对于提供者,也不用告诉调用者我准备好了,你来拿吧,而是只去注册中心做个登记,我能服务了,给我挂上牌子。这样服务之间的管理就容易多了。
具体新建步骤如下:
- 右键项目目录,点击添加module,使用springInitializr方式创建,选择maven或gradle项目(根据个人需要)然后选择SpringCloud eureka新建,这样会自总引入依赖,省去了自己写pom的时间。
- 修改springboot的配置文件,application.properties或者application.yml,我这里用的是yml
# 端口号
server:
port: 8761
# 配置注册服务中心
eureka:
instance:
hostname: localhost
# 配置关闭自我保护,并按需配置Eureka Server清理无效节点的时间间隔。
server:
enable-self-preservation: false
eviction-interval-timer-in-ms: 6000
peer-node-read-timeout-ms: 90000
response-cache-update-interval-ms: 5000
client:
# 表明自己不是一个客户端,并且不进行自注册
register-with-eureka: false
fetch-registry: false
# 注册中心的访问地址
service-url:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
# 配置应用程序名称
spring:
application:
name: cloud-eureka
- 在启动类上添加@EnableEurekaServer,表明自己是注册中心。
@SpringBootApplication
@EnableEurekaServer
public class EurekaApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaApplication.class, args);
}
}
到这里,注册中心就写完了,很简单是吧!运行之后打开浏览器,访问http://localhost:8761/ 就能看到界面
可以看到这里还没有服务器注册进来,下一步,写服务提供者。
服务提供者
我这里写的equipment是因为我拆了以前代码的一个设备相关的功能出来。
- 新建和eureka一样,使用springInitializr新建,但最后要选web,毕竟你最后做出来的项目要是一个web服务。引入web的依赖才对。
- 迁移你的代码,包括controller,service,dao等,直到这个项目可以跑起来,访问localhost能出来数据,当然有页面最好,就是最起码保证这个项目成功运行了。
- 引入springcloud。当它作为一个单独服务跑起来之后,已经是一个成熟的服务了,但是还没去注册中心报道,别人还不知道你能干活了,所以引入springcloud依赖,准备注册。我这里写的是gradle的,maven的百度一下吧
compile 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-client:2.2.1.RELEASE'
- 修改springboot配置文件,找一下注册中心在哪,再告诉注册中心我叫啥:
server:
port: 8081
# 配置应用程序名称
spring:
application:
name: cloud-core #很重要,这个是暗号,对了才能找到
# eureka配置 客户端配置,注册到服务中心
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
name很重要,调用者是通过name找到服务的,所以一定要写
- 同样在启动类加注解,但不是Server是Client,@EnableEurekaClient,证明自己是一个client
@SpringBootApplication
@EnableEurekaClient
public class EquipmentApplication {
public static void main(String[] args) {
SpringApplication.run(EquipmentApplication.class, args);
}
}
如果你刚刚的注册中心还在运行,就可以运行了,运行之后除了访问自己的端口,独立完成自己的业务逻辑之后,还能在eureka界面看到这个服务
服务调用者
原本这里应该是由原来的项目做调用的,但原来的项目的spring的,而且太庞大,所以我单独写了一个服务,只做调用。
- 还是一样,新建module,选择web
- 先写代码,创建controller,service文件夹
@Autowired
private ConsumerService consumerService;
@RequestMapping("/selectAllEquipment")
@ResponseBody
public Map<String, Object> selectAllEquipment(HttpServletRequest request, Integer equipTypeId){
return consumerService.selectAllEquipment(request,equipTypeId,);
}
@Autowired
private LoadBalancerClient loadBalancerClient;
@Override
public Map<String, Object> selectAllEquipment(HttpServletRequest request,Integer equipTypeId) {
//主要是这一步,使用负载均衡策略找到对应提供方的地址,choose方法的参数是服务提供方配置的服务名
ServiceInstance instance = this.loadBalancerClient.choose("cloud-core");
StringBuffer sb = new StringBuffer();
// 拼接出来请求地址
sb.append("http://").append(instance.getHost()).append(":").append(instance.getPort()).append("/selectAllEquipment");
RestTemplate template = new RestTemplate();
MultiValueMap<String, Object> paramMap = new LinkedMultiValueMap<String, Object>();
paramMap.add("equipTypeId","116");
HttpEntity<MultiValueMap<String, Object>> httpEntity = new HttpEntity<MultiValueMap<String, Object>>(paramMap,new HttpHeaders());
// 第一个参数,我们拼接的url,第二个参数,请求参数
ResponseEntity<Object> response =template.postForEntity(sb.toString(), httpEntity, Object.class);
return (Map<String, Object>) response.getBody();
}
- 看下这部分代码,使用的是ribbon负载均衡去做的,choose就是去注册中心找地址的,参数就是上面我说特别重要的那个暗号,通过名字去找提供者,找到之后,如果是多台机,会返回一个符合负载均衡策略的最佳ip和端口,将得到的结果拼接成url去做请求,将结果返回。当然这里结果一般是要拿出来处理的,我这里只是个demo,拿出来能看到数据就行了。
- 还没结束,同样要改配置:
spring:
application:
name: consumer
server:
port: 8082
eureka: #这个参数是写的注册中心的地址,就是说明我要去哪找地址簿
client:
service-url:
defaultZone: http://localhost:8761/eureka/
- 启动类加注解,还是client,@EnableEurekaClient
这时候启动之后,去eureka看界面,也会显示多一个client,然后访问你定义的路由,就能获取到和equipment返回一样的结果。
到这服务就拆完了,其实整个拆的工作量只在写springboot的具体逻辑代码上,至于springcloud,就只是加了几行配置,写了几个注解而已,还是很好实现的。