如何查找服务?如何实现不同服务之间的通行?
Nacos是一个应用于服务注册与发现、配置管理的平台。它孵化于阿里巴巴,成长于十年双十一的洪峰考验,沉淀了简单易用、稳定可靠、性能卓越的核心竞争力。
为什么选择Nacos作为服务中心?
https://github.com/alibaba/nacos/releases
初始化配置
第一步:打开操作系统命令行,登陆mysql 执行sql脚本
执行成功以后,会创建一个nacos_config数据库,打开数据库会看到一些表
第二步:打开/nacos/conf/application.properties里默认配置并进行修改
### If use MySQL as datasource:
spring.datasource.platform=mysql
### Count of DB:
db.num=1
### Connect URL of DB:
db.url.0=jdbc:mysql://127.0.0.1:3306/nacos_config?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC
db.user.0=root
db.password.0=root
查看数据库端口
status;
show global variables like 'port';
第一步:启动Nacos服务
Windows启动命令:
startup.cmd -m standalone
第二步:访问Nacos服务
打开浏览器,输入http://localhost:8848/nacos地址,出现如下登陆页面:
默认账号密码为nacos/nacos.
服务提供者 sca-provider
服务消费者 sca-provider
第一步:创建服务提供者工程 修改pom.xml
01-sca
com.jt
1.0-SNAPSHOT
4.0.0
sca-provider
org.springframework.boot
spring-boot-starter-web
com.alibaba.cloud
spring-cloud-starter-alibaba-nacos-discovery
第二步:创建修改配置文件 application.yml(或者application.properties)
server:
port: 8081
spring:
application:
name: sca-provider #进行服务注册必须配置服务名
cloud:
nacos:
discovery:
server-addr: localhost:8848
第三步:创建启动类
package com.jt;
@SpringBootApplication
public class ProviderApplication {
public static void main(String[] args) {
SpringApplication.run(ProviderApplication.class, args);
}
}
第四步:刷新nacos,检测是否注册成功
如果停掉服务15s,nacos健康实例数为0,如果停掉服务30s,nacos服务自动销毁
前3步步骤同生产者。
第四步: 在sca-provider项目中创建对象,用于提供服务。
package com.jt.provider.controller;
/**定义Controller对象(这个对象在spring mvc中给他的定义是handler),
* 基于此对象处理客户端的请求*/
@RestController
public class ProviderController{
//@Value默认读取项目配置文件中配置的内容
//8080为没有读到server.port的值时,给定的默认值
@Value("${server.port:8080}")
private String server;
//http://localhost:8081/provider/echo/tedu
@GetMapping("/provider/echo/{msg}")
public String doRestEcho1(@PathVariable String msg){
return server+" say hello "+msg;
}
}
第五步:在sca-provider启动类中添加方法
RestTemplate用于进行远程连接
@Bean
public RestTemplate restTemplate(){//基于此对象实现远端服务调用
return new RestTemplate();
}
第六步: 在sca-consumer项目中创建对象,用于调用服务。
package com.jt.consumer.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
/**
* 定义服务消费端Controller,在这个Controller对象
* 的方法中实现对远端服务sca-provider的调用
*/
@RestController
public class ConsumerController {
/**
* 从spring容器获取一个RestTemplate对象,
* 基于此对象实现远端服务调用
*/
@Autowired
private RestTemplate restTemplate;
/**
* 在此方法中通过一个RestTemplate对象调用远端sca-provider中的服务
* @return
* 访问此方法的url: http://localhost:8090/consumer/doRestEcho1
*/
@GetMapping("/consumer/doRestEcho1")
public String doRestEcho01(){
//1.定义要调用的远端服务的url
String url="http://localhost:8081/provider/echo/8090";
//2.基于restTemplate对象中的相关方法进行服务调用
return restTemplate.getForObject(url, String.class);
}
}
第七步: 启动服务进行测试 http://localhost:8090/consumer/doRestEcho1
由于程序可以并发访问 String url="http://localhost:8081/provider/echo/8090"; 无法实现
LoadBalancerClient可以通过服务名称获取服务信息,然后在工程中实现负载均衡。
第一步:修改ConsumerController类,注入LoadBalancerClient对象,并添加doRestEcho2方法,然后进行服务访问.
package com.jt.consumer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.context.annotation.Bean;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import java.util.Random;
@RestController
public class ConsumerController {
//IOC-(资源整合-坐享其成)->Spring框架的目标(资源整合)
//DI-依赖注入(属性注入,构造注入,set注入):注入之前要查找(依赖查找-DL)
@Autowired //属性注入 (但是属性不能使用final修饰)
private RestTemplate restTemplate;
//@Autowired //推荐构造注入 (假如只有一个构造方法autowired也可以省略)
//public ConsumerController(RestTemplate restTemplate){
// this.restTemplate=restTemplate;
//}
@Value("${server.port:8080}")
private String serverPort;
/**
* 基于此对象可以从nacos中动态获取服务列表,
* 并基于内置负载均衡算法获取服务实例
*/
@Autowired
private LoadBalancerClient loadBalancerClient;
/**
* 定义服务调用,在此方法中我们通过restTemplate基于指定url
* 调用远端服务.
* @return
*/
//http://ip:port/consumer/doRestEcho1
@GetMapping("/consumer/doRestEcho1")
public String doRestEcho01(){
//定义远端服务的url地址
String url="http://localhost:8081/provider/echo/{msg}";
//基于RestTemplate借助http协议向远端服务发起Get请求
return restTemplate.getForObject(url,
String.class,serverPort);//String.class为url对应服务的响应结果类型
}
//http://ip:port/consumer/doRestEcho2
@GetMapping("/consumer/doRestEcho2")
public String doRestEcho02(){
//方案1:自己写负载均衡算法
//定义远端服务的url地址
//String url1="http://localhost:8081/provider/echo/{msg}";
//String url2="http://localhost:8082/provider/echo/{msg}";
//String[] urlArray={url1,url2};
//String url=urlArray[new Random().nextInt(urlArray.length)];
//基于RestTemplate借助http协议向远端服务发起Get请求
//return restTemplate.getForObject(url,
//String.class,serverPort);//String.class为url对应服务的响应结果类型
//方案2:从nacos中动态获取服务列表,并基于内置负载均衡算法获取服务实例
//1)基于服务名(这个名字是nacos注册中心中的一个服务名)获取服务实例
ServiceInstance serviceInstance =
loadBalancerClient.choose("sca-provider");
//2)基于服务实例构建远端服务url
String url="http://%s:%s/provider/echo/{msg}";
String ip=serviceInstance.getHost();
int port=serviceInstance.getPort();
url=String.format(url,ip,port);
//3)进行远端服务调用
return restTemplate.getForObject(url,
String.class,serverPort);
}
}
第二步:打开提供者并发端口。
第三步:启用不同端口进行测试。
测试结论:访问是随机访问不同端口,实现负载均衡。