使用SpringCloud
进行分布式调用
搭建eureka
注册中心
既然是要搭建微服务那自然少不了注册中心了,之前讲的dubbo
采用的是zookeeper
作为注册中心,SpringCloud
则采用的是Netflix Eureka
来做服务的注册与发现。
新建一个项目sbc-service
,目录结构如下:
springBoot03.jpg
核心的pom.xml
<dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka-server</artifactId> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>1.2.1</version> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Brixton.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
非常easy,只需要引入eureka
的依赖即可。
然后在入口类加入一个注解@EnableEurekaServer
,即可将该项目作为服务注册中心:
package com.crossoverJie.service; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; @EnableEurekaServer @SpringBootApplication public class EurekaApplication { private final static Logger logger = LoggerFactory.getLogger(EurekaApplication.class); public static void main(String[] args) { SpringApplication.run(EurekaApplication.class, args); logger.info("SpringBoot Start Success"); } }
接着修改配置文件application.properties
:
server.port=8888 # 不向注册中心注册自己 eureka.client.register-with-eureka=false # 不需要检索服务 eureka.client.fetch-registry=false eureka.client.serviceUrl.defaultZone=http://localhost:${server.port}/eureka/
配置一下端口以及注册中心的地址即可。
然后按照正常启动springBoot
项目一样启动即可。
在地址栏输入http://localhost:8888看到一下界面:
springBoot04.jpg
当然现在在注册中心还看不到任何一个应用,下面需要将上文的sbc-user,sbc-order
注册进来。
向注册中心注册服务提供者
只需要在application.properties
配置文件中加上注册中心的配置:
eureka.client.serviceUrl.defaultZone=http://localhost:8888/eureka/
并在sbc-order
的主类中加入@EnableDiscoveryClient
注解即可完成注册服务。
启动注册中心以及应用,在注册中心看到一下界面则成功注册:
springBoot05.jpg
消费注册中心的服务
服务是注册上去了,自然是需要消费了,这里就简单模拟了在调用http://localhost:8080/user/getUser
这个接口的时候getUser
接口会去调用order
的getOrder
服务。
这里会用到另一个依赖:
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-ribbon</artifactId> </dependency>
他可以帮我们做到客户端负载,具体使用如下:
- 加入ribbon依赖。
- 在主类中开启
@LoadBalanced
客户端负载。
- 创建
restTemplate
类的实例
@Bean @LoadBalanced public RestTemplate restTemplate() { return new RestTemplate(); }
- 使用
restTemplate
调用远程服务:
@Autowired private RestTemplate restTemplate; @RequestMapping(value = "/getUser",method = RequestMethod.POST) public UserRes getUser(@RequestBody UserReq userReq){ OrderNoReq req = new OrderNoReq() ; req.setReqNo("1213"); //调用远程服务 ResponseEntity<Object> res = restTemplate.postForEntity("http://sbc-order/order/getOrderNo", req, Object.class); logger.info("res="+JSON.toJSONString(res)); logger.debug("入参="+ JSON.toJSONString(userReq)); UserRes userRes = new UserRes() ; userRes.setUserId(123); userRes.setUserName("张三"); userRes.setReqNo(userReq.getReqNo()); userRes.setCode(StatusEnum.SUCCESS.getCode()); userRes.setMessage("成功"); return userRes ; }
由于我的远程接口是post
,所以使用了postForEntity()
方法,如果是get
就换成getForEntity()
即可。
注意这里是使用应用名
sbc-order(配置于sbc-order的application.properties中)
来进行调用的,并不是一个IP地址。
启动注册中心、两个应用。
用PostMan
调用getUser
接口时控制台打印:
2017-06-27 00:18:04.534 INFO 63252 --- [nio-8080-exec-3] c.c.sbcuser.controller.UserController : res={"body":{"code":"4000","message":"appID不能为空","reqNo":"1213"},"headers":{"X-Application-Context":["sbc-order:8181"],"Content-Type":["application/xml;charset=UTF-8"],"Transfer-Encoding":["chunked"],"Date":["Mon, 26 Jun 2017 16:18:04 GMT"]},"statusCode":"OK","statusCodeValue":200}
由于并没有传递appId
所以order
服务返回了一个错误,也正说明是远程调用到了该服务。
总结
ps:这里只是简单使用了
ribbon
来进行服务调用,但在实际的开发中还是比较少的使用这种方式来调用远程服务,而是使用Feign
进行声明式调用,可以简化客户端代码,具体使用方式请持续关注。
本次算是springBoot+springCloud
的入门,还有很多东西没有讲到,之后我将会根据实际使用的一些经验继续分享SpringCloud
这个新兴框架。
个人博客地址:crossoverjie.top。