SpringCloud学习-1
SpringCloud学习第一天
服务间调用
先实现一个小案例:创建两个项目user-service(服务提供方)和consumer(服务消费方),在user-service项目中查询数据库获取user信息,在consumer项目中调用user-service中的服务获取到user信息。将两个项目创建到一个聚合工程下,创建springCloudDemo父工程,pom文件部分代码如下:
<modules>
<module>user-service</module>
<module>consumer</module>
</modules>
<packaging>pom</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>10.0.2</java.version>
<spring-cloud.version>Finchley.SR1</spring-cloud.version>
<mapper.starter.version>2.0.3</mapper.starter.version>
<mysql.version>5.1.32</mysql.version>
</properties>
<dependencyManagement>
<!-- 子工程手动继承 -->
<dependencies>
<!-- springCloud -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- 通用mapper -->
<dependency>
<groupId>tk.mybatis</groupId>
<artifactId>mapper-spring-boot-starter</artifactId>
<version>${mapper.starter.version}</version>
</dependency>
<!-- mysql驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<!-- 子工程自动继承 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
在springCloudDemo父工程中新建Module子工程,创建user-service项目,user-service主要实现通过主键id查询数据库获取user信息,部分代码如下:
User
@Table(name= "user")
@Data
public class User {
@Id // 主键
@KeySql(useGeneratedKeys = true)
private Long id;
// 用户名
private String username;
// 密码
private String password;
// 姓名
@Transient
private String name;
}
UserDao
为了方便这里使用了通用mapper
@Repository
public interface UserDao extends Mapper<User>{
}
UserService
@Service
public class UserService {
@Autowired
private UserDao userDao;
public User queryById(Long id) {
User user = userDao.selectByPrimaryKey(id);
return user;
}
}
UserController
@RestController
@RequestMapping("user")
public class UserController {
@Autowired
private UserService userService;
@GetMapping("/{id}")
public User queryById(@PathVariable("id") Long id) {
User user = userService.queryById(id);
return user;
}
}
启动服务,访问http://localhost:8081/user/1可以获取到用户信息。
创建consumer项目,通过调用user-service中的服务,获取user信息,这里使用的是Spring的RestTemplate来实现,代码如下:
启动类中注册RestTemplate Bean
@SpringBootApplication
public class ConsumerApplication {
@Bean
public RestTemplate restTemplate(){
return new RestTemplate(); // restTemplate获取到可以调用其他服务器接口的实例对象
}
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class);
}
}
ConsumerController
@RestController
@RequestMapping("consumer")
public class ConsumerController {
@Autowired
private RestTemplate restTemplate;
@GetMapping("{id}")
public String queryById(@PathVariable("id") Long id) {
String url = "http://localhost:8081/user/"+id;
String user = restTemplate.getForObject(url, String.class);
return user
}
}
同时启动两个项目,访问localhost:8082/consumer/1,可以调用user-service项目中的接口,获取到user信息。
上面的小案例实现了服务之间的调用,但是存在很大的问题,调用方写死了服务方的ip地址,难以维护,无法做集群,无法管理服务等问题,因此开始学习SpringCloud注册中心Eureka。
Eureka
Eureka为注册中心,用于注册所有的服务项目,统一管理,并与服务间维持心跳,检测服务是否宕机,也可以实现服务的集群管理,下面优化上面案例的服务调用。
在springCloudDemo父工程中新建一个eureka-server项目,引入依赖
<dependencies>
<dependency>
<!-- Eureka 服务端 -->
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
</dependencies>
启动类
@EnableEurekaServer // 标记是eureka注册中心的服务
@SpringBootApplication
public class EurekaServer {
public static void main(String[] args) {
SpringApplication.run(EurekaServer.class);
}
}
application.yml
server:
port: 10001
spring:
application:
name: eureka-server # 服务的名称,不配置eureka服务不显示名称,会出现unknown
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:10001/eureka # eureka服务注册的地址,向自己注册,eureka本身也是一个服务,也会注册到注册中心
修改之前的user-service和consumer项目
1、引入依赖
<dependencies>
<!-- Eureka client依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
</dependencies>
2、yml
# user-service
server:
port: 8081
spring:
application:
name: user-service
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:10001/eureka
# consumer
server:
port: 8082
spring:
application:
name: consumer-client
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:10001/eureka
3、启动类加注解
@EnableDiscoveryClient // 标识为注册服务端的客户端
将以上三个项目启动,访问eureka-server项目localhost:10001可以看到注册服务列表中有三个服务,修改ConsumerController.java,动态获取调用服务的url
ConsumerController
@RestController
@RequestMapping("consumer")
public class ConsumerController {
@Autowired
private RestTemplate restTemplate;
@Autowired
private DiscoveryClient discoveryClient; // 使用DiscoveryClient获取eureka实例对象
@GetMapping("{id}")
public String queryById(@PathVariable("id") Long id) {
// 根据服务id获取实例,服务id:yml中的name
List<ServiceInstance> instances = discoveryClient.getInstances("user-service");
// 从实例中取出ip和端口,取第一个
ServiceInstance instance = instances.get(0);
// 拼接url
String url = "http://"+instance.getHost()+":"+instance.getPort()+"/user/" + id;
// String url = "http://localhost:8081/user/"+id;
String user = restTemplate.getForObject(url, String.class);
return user
}
}
以上根据服务名称获取服务instances,获取动态服务地址,重新启动consumer服务访问localhost:8082/consumer/1,可以调用到user-service项目中的接口,获取到user信息。
实现eureka集群
修改eureka-server的yml文件
server:
port: 10002
spring:
application:
name: eureka-server
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:10001/eureka #将10002的eureka注册到10001,将10001的eureka注册到10002
重新开启一个tomcat启动,修改user-service和consumer项目yml,增加一个eureka注册地址http://127.0.0.1:10002/eureka
# user-service
server:
port: 8081
spring:
application:
name: user-service
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:10001/eureka,http://127.0.0.1:10002/eureka
# consumer
server:
port: 8082
spring:
application:
name: consumer-client
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:10001/eureka,http://127.0.0.1:10002/eureka
重新启动user-service和consumer项目,此时locahost:10001和localhost:10002都可以访问到服务列表,localhost:8082/consumer/1也可以成功调用接口,此时关闭一台eureka服务,仍然可以访问,实现了eureka集群。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话