微服务的设计理念在我的理解就是将服务粒子化,并对服务统一进行管理,利用http协议进行数据通信,使得restful风格的接口也能被网关很好的管理,对负载上的优点在于它将各个模块的服务分布在不同的服务器或是不同的端口上,我们能更好的选择可用性,一致性与分区容忍性其中两种实现,目的很明确。
之前我们在玩springboot时,两个不同的模块之间的通信缺少统一化的管理,如果单一的某一模块宕机挂掉,我们也不知道不容易做出应对,这一块服务都不能使用,而springcloud则是多个结点符合数据一致性,保证我们服务的正常运行,不会因为某一个节点上服务的挂掉影响整个应用的使用。其次,对于服务的管理方面而言,springcloud集成了很多优秀的开源组件,今天我学习的就是服务注册中心中的Eureka客户端。
服务发现是基于微服务的体系结构的主要宗旨之一。尝试手动配置每个客户端或某种形式的约定可能很困难并且很脆弱。Eureka是Netflix Service Discovery服务器和客户端。可以将服务器配置和部署为高可用性,每个服务器将有关已注册服务的状态复制到其他服务器。
一个比较简单的springcloud微服务项目的架构大致如下图:
我们都能看出来每一个服务组件功能性组件都需要在我们的服务注册中心进行注册,在我今天的测试项目中,只有两个模块product模块与order模块,以及我们的服务发现Eureka模块。
首先搭建一个父工程Spring_cloud:
pom文件:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>spring_cloud</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
<modules>
<module>product</module>
<module>eureka</module>
<module>order</module>
</modules>
<!-- 管理版本统一管理和spring相关的依赖
注意boot的版本要与cloud版本兼容
-->
<parent>
<artifactId>spring-boot-starter-parent</artifactId>
<groupId>org.springframework.boot</groupId>
<version>2.6.7</version>
</parent>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.24</version>
<scope>provided</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>2021.0.3</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<repositories>
<repository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>http://repo.spring.io/libs-snapshot-local</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>http://repo.spring.io/libs-milestone-local</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
<repository>
<id>spring-releases</id>
<name>Spring Releases</name>
<url>http://repo.spring.io/libs-release-local</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>http://repo.spring.io/libs-snapshot-local</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</pluginRepository>
<pluginRepository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>http://repo.spring.io/libs-milestone-local</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
然后创建我们的product模块:
pom文件导入三个依赖:
<!--数据库驱动依赖-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!--mp依赖-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.2</version>
</dependency>
<!--引入EurekaClient-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
创建entity层:
实体类
@Data
@TableName("tb_products")
public class Product {
@TableId
private int Id;
private String productName;
private int status;
private BigDecimal price;
private String productDesc;
private int inventory;
}
创建mapper层:
接口
@Mapper
public interface ProductMapper extends BaseMapper<Product> {
}
?创建service层:
接口
public interface ProductService extends IService<Product> {
}
实现类?
@Service
@Slf4j
public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product>
implements ProductService {
@Autowired
private ProductMapper productMapper;
private final QueryWrapper<Product> wrapper = new QueryWrapper<>();
/**
* 按照Id查询商品
*
* @param id id
* @return Product
*/
public Product getProductById(int id) {
try {
wrapper.eq("id", id);
return productMapper.selectOne(wrapper);
} catch (Exception e) {
log.info("商品查询模块查询商品id越界");
return null;
}
}
}
创建controller层:
controller
@RestController
@RequestMapping("product")
public class ProductController {
@Autowired
private ProductServiceImpl productService;
/**
* 根据id获取商品信息
*
* @param id 商品id
* @return 实体
*/
@RequestMapping(value = "/{id}", method = RequestMethod.GET)
public Product getProductById(@PathVariable("id") Integer id) {
return productService.getProductById(id);
}
}
创建starter启动类:
@SpringBootApplication
@Slf4j
public class ProductServiceStarter {
public static void main(String[] args) {
SpringApplication.run(ProductServiceStarter.class,args);
log.info("productService模块启动成功");
}
}
?配置application.yml文件:
server:
port: 9001
spring:
application:
name: product
datasource:
url: jdbc:mysql://localhost:3306/shop
username: root
password: ******
type: com.zaxxer.hikari.HikariDataSource
mybatis-plus:
configuration:
map-underscore-to-camel-case: false
#配置Eureka
eureka:
client:
service-url:
defaultZone: http://localhost:9000/eureka/ #多个eurekaserver之间用,隔开
instance:
prefer-ip-address: true #使用ip地址注册
instance-id: ${spring.cloud.client.ip-address}:${server.port} #向注册中心中注册服务id
?之后创建order模块:
pom文件导入三个依赖:
<!-- 数据库驱动依赖-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!--mp依赖-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.2</version>
</dependency>
<!--引入EurekaClient-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
</dependencies>
创建entity实体层:
实体
@Data
public class Product {
private int Id;
private String productName;
private int status;
private BigDecimal price;
private String productDesc;
private int inventory;
}
?创建controller层:
controller
@RestController
@RequestMapping("order")
public class OrderController {
@Autowired(required = true)
private RestTemplate restTemplate;
@RequestMapping(value = "/buy/{id}",method = RequestMethod.GET)
public Product getProductById(@PathVariable("id")int id) {
Product product = null;
product =restTemplate.getForObject("http://localhost:9001/product/"+id,Product.class);
return product;
}
}
?创建starter启动类:
@SpringBootApplication
@Slf4j
public class OrderServiceStarter {
@Bean
@LoadBalanced
public RestTemplate restTemplate(RestTemplateBuilder builder){
return builder.build();
}
public static void main(String[] args) {
SpringApplication.run(OrderServiceStarter.class,args);
log.info("OrderServer模板启动成功");
}
}
?配置application.yml:
server:
port: 9002
spring:
cloud:
loadbalancer:
retry:
enabled: true
application:
name: order
datasource:
url: jdbc:mysql://localhost:3306/shop
username: root
password: 123456
type: com.zaxxer.hikari.HikariDataSource
mybatis-plus:
configuration:
map-underscore-to-camel-case: false
#配置Eureka
eureka:
client:
service-url:
defaultZone: http://localhost:9000/eureka/ #多个eurekaserver之间用,隔开
instance:
prefer-ip-address: true #使用ip地址注册
?创建Eureka模块:
pom文件导入一个依赖:
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
</dependencies>
?创建starter启动类启动Euureka客户端服务器:
@Slf4j
@SpringBootApplication
//开启Eureka服务
@EnableEurekaServer
public class EurekaStarter {
public static void main(String[] args) {
SpringApplication.run(EurekaStarter.class,args);
log.info("Eureka服务成功启动");
}
}
配置application.yml文件:
#模拟两个EurekaServer
#端口9000 , 8000
#两个server需要相互注册
spring:
application:
name: eureka
server:
port: 9000 #端口
#配置eureka server
eureka:
instance:
lease-renewal-interval-in-seconds: 10 #加快服务连接
client:
register-with-eureka: true #是否将自己注册到注册中心
fetch-registry: false #是否从eureka中获取注册信息
service-url: #配置暴露给Eureka Client的请求地址
defaultZone: http://127.0.0.1:9000/eureka/
server:
enable-self-preservation: false #关闭自我保护
eviction-interval-timer-in-ms: 4000 #剔除服务间隔
?最后是测试项目的结果:
访问本机的? ip:9002/order/buy/1 成功访问到product服务的url获取到数据库数据并由实体传输给页面渲染,但是问题也有,服务的注册时间太长,服务调用的响应除了第一次较快其余都不行,今天很晚了,明天看看文档接着研究吧!
晚安啦~~~
|