基本介绍:
Eureka Server(Eureka 服务端)是Netflix开源的一款用于构建分布式系统中的服务发现和注册中心的组件。它在微服务架构中扮演着关键的角色,允许不同的微服务应用程序注册自己,并查询其他服务的位置信息,以便它们可以相互通信。
以下是关于Eureka Server的一些重要介绍和特点:
-
服务注册和发现:Eureka Server允许微服务应用程序在启动时将自己注册到Eureka注册中心,以便其他服务可以发现它们。注册的服务可以提供有关其名称、IP地址、端口和健康状态等信息。
-
健康检查:Eureka Server支持对注册的服务进行健康检查,以便在服务不可用时将其从注册表中移除。这有助于避免将请求路由到不可用的服务实例。
-
客户端负载均衡:Eureka客户端库可用于在微服务消费者之间实现负载均衡。消费者可以从Eureka Server中获取可用服务实例的列表,并选择一个进行调用。
-
自我保护机制:Eureka Server具有自我保护机制,可以在某些情况下防止服务注册表中的整体故障。如果Eureka Server在一段时间内无法收到心跳信号,它不会立即删除该服务,而是将其标记为"不健康",并继续提供服务。这有助于防止因网络故障或其他问题导致的误删除服务。
-
集群支持:Eureka Server支持构建高可用性集群,其中多个Eureka Server实例一起工作,以确保可用性和冗余。
-
Spring Cloud集成:Eureka Server通常与Spring Cloud一起使用,以便轻松构建和管理微服务架构。Spring Cloud提供了对Eureka的集成支持,使开发者能够更容易地使用Eureka进行服务注册和发现。
Eureka Client是一个用于与Eureka Server进行通信的库或模块,通常用于微服务架构中的服务提供者和服务消费者。Eureka Client允许微服务应用程序向Eureka Server注册自己并查询其他已注册的服务的位置信息,以便实现服务的发现和负载均衡。
以下是关于Eureka Client的一些重要信息和功能:
-
服务注册:服务提供者(通常是一个微服务应用程序)使用Eureka Client来向Eureka Server注册自己。注册包括提供服务的名称、IP地址、端口号以及其他元数据信息。一旦注册,其他服务就可以通过Eureka Server发现并调用该服务。
-
服务发现:服务消费者使用Eureka Client来从Eureka Server中获取可用服务实例的列表。Eureka Client通过查询Eureka Server来获取这些信息,并维护本地缓存以实现快速访问。消费者可以根据服务的名称来发现可用的服务实例,并选择一个实例进行调用。
-
负载均衡:Eureka Client通常与负载均衡器结合使用,以确保请求均匀地分配到多个服务实例中。通过从Eureka Server获取实例列表并使用负载均衡策略选择实例,Eureka Client可以帮助分散服务调用的负载,提高系统性能和可用性。
-
健康检查:Eureka Client定期向Eureka Server发送心跳信号,以表明它仍然处于活动状态。Eureka Server可以使用这些心跳信号来检测服务实例的健康状况,并在需要时将其标记为不健康或下线。
-
故障转移:如果Eureka Client无法连接到Eureka Server,它会尝试与其他Eureka Server实例建立连接(如果配置了多个)。这有助于提高系统的可用性,即使一个Eureka Server实例不可用,服务注册和发现仍然可以正常工作。
-
Spring Cloud集成:Eureka Client通常与Spring Cloud一起使用,以便轻松构建和管理微服务架构。Spring Cloud提供了对Eureka Client的集成支持,使开发者能够更容易地将服务注册到Eureka Server和发现其他服务。
Eureka Client 代码实现
基本结构:
-
创建 Module ,pom.xml
<dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId><version>2.0.2.RELEASE</version></dependency>
</dependencies>
-
创建配置文件 application.yml,添加 Eureka Client 相关配置
server:port: 8010
spring:application:name: provider
eureka:client:service-url:defaultZone: http://localhost:8761/eureka/instance:prefer-ip-address: true
属性说明:
spring.application.name
:当前服务注册在 Eureka Server 上的名称。
eureka.client.service-url.defaultZone
:注册中心的访问地址。
eureka.instance.prefer-ip-address
:是否将当前服务的 IP 注册到 Eureka Server。
-
创建启动类
package com.southwind;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class ProviderApplication {public static void main(String[] args) {SpringApplication.run(ProviderApplication.class,args);}
}
-
实体类
package com.southwind.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {private long id;private String name;private int age;
}
-
Repository
package com.southwind.repository;
import com.southwind.entity.Student;
import java.util.Collection;
public interface StudentRepository {public Collection<Student> findAll();public Student findById(long id);public void saveOrUpdate(Student student);public void deleteById(long id);
}
-
RepositoryImpl
package com.southwind.repository.impl;
import com.southwind.entity.Student;
import com.southwind.repository.StudentRepository;
import org.springframework.stereotype.Repository;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
@Repository
public class StudentRepositoryImpl implements StudentRepository {
private static Map<Long,Student> studentMap;
static {studentMap = new HashMap<>();studentMap.put(1L,new Student(1L,"张三",22));studentMap.put(2L,new Student(2L,"李四",23));studentMap.put(3L,new Student(3L,"王五",24));}
@Overridepublic Collection<Student> findAll() {return studentMap.values();}
@Overridepublic Student findById(long id) {return studentMap.get(id);}
@Overridepublic void saveOrUpdate(Student student) {studentMap.put(student.getId(),student);}
@Overridepublic void deleteById(long id) {studentMap.remove(id);}
}
-
Handler
package com.southwind.controller;
import com.southwind.entity.Student;
import com.southwind.repository.StudentRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.Collection;
@RestController
@RequestMapping("/student")
public class StudentHandler {@Autowiredprivate StudentRepository studentRepository;
@GetMapping("/findAll")public Collection<Student> findAll(){return studentRepository.findAll();}
@GetMapping("/findById/{id}")public Student findById(@PathVariable("id") long id){return studentRepository.findById(id);}
@PostMapping("/save")public void save(@RequestBody Student student){studentRepository.saveOrUpdate(student);}
@PutMapping("/update")public void update(@RequestBody Student student){studentRepository.saveOrUpdate(student);}
@DeleteMapping("/deleteById/{id}")public void deleteById(@PathVariable("id") long id){studentRepository.deleteById(id);}
}
运行启动类,先运行Eurek启动类:
访问8761端口:
RestTemplate基本介绍:
在Spring Cloud中,RestTemplate
是一个常用的HTTP客户端工具,用于在微服务架构中进行服务间的通信。Spring Cloud通过提供一些额外的功能来增强RestTemplate
,以便更轻松地与分布式系统中的微服务进行交互。以下是一些关于在Spring Cloud中使用RestTemplate
的注意事项:
-
负载均衡: Spring Cloud集成了负载均衡器Ribbon,可以让
RestTemplate
自动选择要调用的服务实例。您可以使用服务的名称而不是硬编码的URL来发送请求。例如:restTemplate.getForObject("http://my-service/api/resource", String.class);
在这个例子中,
my-service
是服务的名称,Ribbon会自动选择一个可用的实例进行调用。 -
服务发现: Spring Cloud集成了Eureka或其他服务注册中心,可以让
RestTemplate
自动发现可用的服务实例。这意味着您不需要手动配置每个服务的主机和端口,而是使用服务的名称来访问它们。 -
请求拦截器: Spring Cloud允许您添加拦截器来处理请求和响应,例如添加身份验证信息、记录请求日志等。这可以通过实现
ClientHttpRequestInterceptor
接口来实现。 -
错误处理: 在Spring Cloud中,
RestTemplate
通常会捕获HTTP错误,并将它们封装为HttpClientErrorException
(如4xx错误)或HttpServerErrorException
(如5xx错误)等异常。这样,您可以更容易地处理HTTP错误。 -
配置管理: 使用Spring Cloud Config,您可以在不同的环境中为
RestTemplate
配置不同的属性,如超时时间、连接池大小等。 -
断路器模式: Spring Cloud集成了Hystrix,可以通过
@HystrixCommand
注解来保护RestTemplate
的调用,以便在服务不可用时进行降级或错误处理。
RestTemplate 的使用
结构图:
-
什么是 RestTemplate?
RestTemplate 是 Spring 框架提供的基于 REST 的服务组件,底层是对 HTTP 请求及响应进行了封装,提供了很多访问 RETS 服务的方法,可以简化代码开发。
-
如何使用 RestTemplate?
1、创建 Maven 工程,pom.xml。
2、创建实体类
package com.southwind.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {private long id;private String name;private int age;
}
3、Handler
package com.southwind.controller;
import com.southwind.entity.Student;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import java.util.Collection;
@RestController
@RequestMapping("/rest")
public class RestHandler {@Autowiredprivate RestTemplate restTemplate;
@GetMapping("/findAll")public Collection<Student> findAll(){return restTemplate.getForEntity("http://localhost:8010/student/findAll",Collection.class).getBody();}
@GetMapping("/findAll2")public Collection<Student> findAll2(){return restTemplate.getForObject("http://localhost:8010/student/findAll",Collection.class);}
@GetMapping("/findById/{id}")public Student findById(@PathVariable("id") long id){return restTemplate.getForEntity("http://localhost:8010/student/findById/{id}",Student.class,id).getBody();}
@GetMapping("/findById2/{id}")public Student findById2(@PathVariable("id") long id){return restTemplate.getForObject("http://localhost:8010/student/findById/{id}",Student.class,id);}
@PostMapping("/save")public void save(@RequestBody Student student){restTemplate.postForEntity("http://localhost:8010/student/save",student,null).getBody();}
@PostMapping("/save2")public void save2(@RequestBody Student student){restTemplate.postForObject("http://localhost:8010/student/save",student,null);}
@PutMapping("/update")public void update(@RequestBody Student student){restTemplate.put("http://localhost:8010/student/update",student);}
@DeleteMapping("/deleteById/{id}")public void deleteById(@PathVariable("id") long id){restTemplate.delete("http://localhost:8010/student/deleteById/{id}",id);}
}
4、启动类
package com.southwind;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
@SpringBootApplication
public class RestTemplateApplication {public static void main(String[] args) {SpringApplication.run(RestTemplateApplication.class,args);}
@Beanpublic RestTemplate restTemplate(){return new RestTemplate();}
}
Consumer基本介绍:
服务消费者(Consumer)是微服务架构中的一种角色,它用于调用和使用提供者服务的功能。服务消费者通常不负责实际的业务逻辑处理,而是依赖于提供者服务来获取所需的数据或执行操作。在微服务架构中,服务消费者通常使用HTTP请求或其他通信协议与提供者服务进行通信。
以下是有关服务消费者的一些关键概念和特点:
-
依赖性: 服务消费者依赖于一个或多个提供者服务,它们是整个系统中的客户端。
-
服务发现: 为了与提供者服务通信,服务消费者通常需要了解提供者服务的位置信息。这可以通过服务发现机制来实现,其中服务提供者会将自己注册到服务注册中心(如Eureka),而服务消费者可以查询注册中心来获取可用的提供者服务列表。
-
负载均衡: 微服务架构通常包含多个相同功能的提供者服务实例,服务消费者可以使用负载均衡来分发请求,以确保高可用性和性能。
-
断路器: 为了防止服务消费者在提供者服务不可用或出现故障时受到影响,可以使用断路器模式(如Hystrix)来实现容错和降级。断路器会在一段时间内监控服务提供者的响应,并在需要时停止向不可用的服务实例发送请求。
-
请求和响应处理: 服务消费者使用HTTP客户端(如
RestTemplate
)来发送请求到提供者服务,并处理来自提供者的响应。通常,响应会被解析并转换为服务消费者的领域对象。 -
容器化: 服务消费者通常是运行在容器中的,如Docker容器。这使得它们可以轻松地部署和扩展。
-
配置管理: 服务消费者需要配置和管理与提供者服务的通信方式,包括URL、端口、超时等。Spring Cloud Config等工具可以用于集中管理这些配置。
-
安全性: 通信通常需要进行安全处理,以确保数据的机密性和完整性。安全性可以通过HTTPS、OAuth2等方式来实现。
-
监控和追踪: 服务消费者可能需要监控其与提供者服务之间的通信,并记录请求和响应以进行追踪和故障排除。Spring Cloud Sleuth和Zipkin等工具可用于实现分布式跟踪。
服务消费者 consumer
结构图:
-
创建 Maven 工程,pom.xml
<dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId><version>2.0.2.RELEASE</version></dependency>
</dependencies>
-
创建配置文件 application.yml
server:port: 8020
spring:application:name: consumer
eureka:client:service-url:defaultZone: http://localhost:8761/eureka/instance:prefer-ip-address: true
-
创建启动类
package com.southwind;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
@SpringBootApplication
public class ConsumerApplication {public static void main(String[] args) {SpringApplication.run(ConsumerApplication.class,args);}
@Beanpublic RestTemplate restTemplate(){return new RestTemplate();}
}
-
Handler
package com.southwind.controller;
import com.southwind.entity.Student;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import java.util.Collection;
@RestController
@RequestMapping("/consumer")
public class ConsumerHandler {@Autowiredprivate RestTemplate restTemplate;
@GetMapping("/findAll")public Collection<Student> findAll(){return restTemplate.getForEntity("http://localhost:8010/student/findAll",Collection.class).getBody();}
@GetMapping("/findAll2")public Collection<Student> findAll2(){return restTemplate.getForObject("http://localhost:8010/student/findAll",Collection.class);}
@GetMapping("/findById/{id}")public Student findById(@PathVariable("id") long id){return restTemplate.getForEntity("http://localhost:8010/student/findById/{id}",Student.class,id).getBody();}
@GetMapping("/findById2/{id}")public Student findById2(@PathVariable("id") long id){return restTemplate.getForObject("http://localhost:8010/student/findById/{id}",Student.class,id);}
@PostMapping("/save")public void save(@RequestBody Student student){restTemplate.postForEntity("http://localhost:8010/student/save",student,null).getBody();}
@PostMapping("/save2")public void save2(@RequestBody Student student){restTemplate.postForObject("http://localhost:8010/student/save",student,null);}
@PutMapping("/update")public void update(@RequestBody Student student){restTemplate.put("http://localhost:8010/student/update",student);}
@DeleteMapping("/deleteById/{id}")public void deleteById(@PathVariable("id") long id){restTemplate.delete("http://localhost:8010/student/deleteById/{id}",id);}
}