1、搭建服务注册中心
使用过阿里的dubbo应该知道dubbo服务需要一个注册中心,将服务的信息注册到注册中心上,调用远程服务的时候,dubbo会在注册中心上发现服务并进行远程的调用。
与dubbo不同的是,Spring Cloud是一个一站式分布式框架,Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智能路由,微代理,控制总线)
现在我们在spring cloud中使用Eureka搭建一个服务注册中心
- 在maven中添加依赖
org.springframework.boot
spring-boot-starter
org.springframework.cloud
spring-cloud-starter-eureka-server
org.springframework.boot
spring-boot-starter-test
test
- 在spring boot启动类上添加
@EnableEurekaServer
注解,让这个服务为eureka服务
@SpringBootApplication
@EnableEurekaServer
public class EurekaApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaApplication.class, args);
}
}
- 配置application.yml文件
spring:
application:
name: eureka-service
server:
port: 8761
eureka:
client:
register-with-eureka: false #向eureka注册服务
fetch-registry: false #是否本地缓存注册表
-
server.port
表示服务端口 -
spring.application.name
表示服务名称 -
eureka.client.register-with-eureka
表示是否向eureka服务中注册自己 -
eureka.client.fetch-registry
表示是否本地缓存注册表
-
启动服务,浏览器输入http://
就可以看到注册中心了
- 关于搭建高可用注册中心,配置
eureka.instance.hostname
和eureka.client.service-url.defaultZone
就可以了,这里就详细写了
2、注册服务
现在向注册中心注册一个spring cloud服务
- 添加maven依赖
org.springframework.boot
spring-boot-starter-web
org.springframework.cloud
spring-cloud-starter-eureka
- 在spring boot启动类添加
@EnableDiscoveryClient
@SpringBootApplication
@EnableDiscoveryClient
public class ProviderApplicatioin {
public static void main(String[] args) {
SpringApplication.run(ProviderApplicatioin.class, args);
}
}
- 配置application文件
eureka:
instance:
prefer-ip-address: true #注册服务的IP
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka
register-with-eureka: true
-
eureka.instance.prefer-ip-address
表示向eureka注册服务的IP -
eureka.client.serviceUrl.defaultZone
表示eureka服务地址 -
eureka.client.register-with-eureka
表示向eureka注册服务
- 编写controller,创建服务接口
@RestController
public class ProviderController {
private final Logger LOGGER = Logger.getLogger(ProviderController.class);
/**
* get方式接口
* @param request 请求参数
*/
@RequestMapping(value = "/provider", method = RequestMethod.GET)
public String provider(@RequestParam String request) {
LOGGER.info("========================================");
LOGGER.info("provider service 被调用");
LOGGER.info("========================================");
return "provider, " + request;
}
/**
* POST方式接口
* @param reqBody request body
*/
@RequestMapping(value = "/post", method = RequestMethod.POST)
public RespBody post(@RequestBody ReqBody reqBody) {
RespBody respBody = new RespBody();
respBody.setRequest(reqBody.getUsername());
respBody.setResult("yes");
return respBody;
}
}
这里需要说明一下,controller写了POST接口和GET接口模拟业务,将ReqBody
和RespBody
类放在一个公共jar包里面,maven引用,方便后面远程服务调用
ReqBody.java
public class ReqBody implements Serializable{
private String username;
private String password;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
RespBody.java
public class RespBody implements Serializable{
private String result;
private String request;
public String getResult() {
return result;
}
public void setResult(String result) {
this.result = result;
}
public String getRequest() {
return request;
}
public void setRequest(String request) {
this.request = request;
}
}
- 启动服务,可以发现服务中心注册了一个服务
3、服务发现
- 创建项目,添加maven依赖
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-actuator
org.springframework.cloud
spring-cloud-starter-eureka
org.springframework.cloud
spring-cloud-starter-feign
com.hui.wang.spring.cloud
api
1.0-SNAPSHOT
- 在spring boot启动类上添加
@EnableDiscoveryClient
注解 - 提供RestTemplate的Bean,RestTemplate可以帮助我们发起一个GET或者POST请求,在spring boot添加@LoadBalanced注解,表示开启客户端负载均衡。
@SpringBootApplication
@EnableDiscoveryClient
public class ConsumerApplication {
@LoadBalanced
@Bean RestTemplate restTemplate() {
return new RestTemplate();
}
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class, args);
}
}
- 配置application文件
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka
-
eureka.client.serviceUrl.defaultZone
表示注册中心地址
- 编写controller,调用远程服务
@RestController
public class Controller {
private final Logger LOGGER = Logger.getLogger(Controller.class);
@Autowired
private RestTemplate restTemplate;
/**
* GET请求传参数1
*/
@RequestMapping("/consumer/v1")
public String consumerV1() {
return restTemplate.getForEntity("http://provider-server/provider?request={1}", String.class, "test").getBody();
}
/**
* GET请求传参数2
*/
@RequestMapping("/consumer/v2")
public String consumerV2() {
Map map = Maps.newHashMap();
map.put("request","test");
return restTemplate.getForEntity("http://provider-server/provider?request={request}", String.class, map).getBody();
}
/**
* 使用UriComponents构建get请求参数
*/
@RequestMapping(value = "/consumer/v3")
public String consumerV3() {
UriComponents uriComponents = UriComponentsBuilder
.fromUriString("http://provider-server/provider?request={request}")
.build()
.expand("测试")
.encode();
URI uri = uriComponents.toUri();
ResponseEntity responseEntity = restTemplate.getForEntity(uri, String.class);
return responseEntity.getBody();
}
/**
* post请求
*/
@RequestMapping(value = "post")
public RespBody post() {
ReqBody reqBody = new ReqBody();
reqBody.setPassword("hui");
reqBody.setUsername("wang");
ResponseEntity respBodyResponseEntity = restTemplate.postForEntity("http://provider-server/post", reqBody, RespBody.class);
LOGGER.info("respBodyResponseEntity.status = " + respBodyResponseEntity.getStatusCodeValue());
return respBodyResponseEntity.getBody();
}
}
说明:
- 将
restTemplate
注册到controller里面就可以利用restTemplate
调用远程服务了 - 使用
http://
就是远程服务的位置。其中/ provider server name
就是服务提供者的spring server的ID(spring.application.name
);requestMapping
就是服务提供的接口 - 上面controller分别模拟了POST方式和GET方式调用远程服务。
- 调用GET方式的远程服务,使用
restTemplate.getForEntity()
方法即可,关于GET方式的参数,上面给出了两种方式调用 - 调用POST请示的远程服务,使用
restTemplate.postForEntity()
方法即可,上面也给出了方式 -
UriComponents
通过Spring中提供的UriComponents来构建Uri - 其中还有
getForObject
,postForObject
,postForLocation
源码地址