Spring Cloud – 간단 한 서비스 프로 세 스 (서비스 발견 및 API 호출) 를 어떻게 사용 합 니까?
67363 단어 필기 하 다.
스프링 클 라 우 드 의 전체 작업 절 차 를 소개 해 야 한다.우선 Spring Cloud 의 작업 절 차 를 살 펴 보고,
Service Consumer -> Proxy Server -> Client(Load Balancer) -> Servie Discovery -> Target Service
여기 가 바로 간단 한 Service API 호출 프로 세 스 입 니 다.다음은 Spring Cloud 의 구성 요소 와 위의 절차 의 대응 관 계 를 살 펴 보 겠 습 니 다.
Spring Cloud
Module
Restful API (Spring Boot)
Target Service
Eureka
Servie Discovery
Client & Load Balancer
Spring RestTemplate & Ribbon
Proxy(Edge) Server
Zuul
Service Consumer
Browser,Curl,Other Apps,etc
이상 의 간단 한 demo 를 소개 하 겠 습 니 다.
데이터 구조 및 기초 서비스:
여기 서 Spring Boot 를 사용 하여 세 개의 기초 서 비 스 를 신속하게 만 들 고 그 중에서 세 가지 논리 적 의존 관계 가 존재 합 니 다.
Company Service
Java
public class Company {
private Long id;
private String name;
// Constructor、Getter、Setter
}
@RestControllerpublic class CompanyService {
@RequestMapping("/company/{id}")public Company getCompanyById(@PathVariable("id") Long id){
sleep();
return new Company(id, "Company");
}
// Serivce private void sleep() {
Random rand = new Random();
int time = rand.nextInt(2000);
try {
Thread.sleep(time);
} catch (Exception e) {
e.printStackTrace();
}
}
}
public class Company {
private Long id;
private String name;
// Constructor、Getter、Setter
}
@RestControllerpublic class CompanyService {
@RequestMapping("/company/{id}")public CompanygetCompanyById(@PathVariable("id") Long id){
sleep();
return new Company(id, "Company");
}
// Serivce private void sleep() {
Randomrand = new Random();
int time = rand.nextInt(2000);
try {
Thread.sleep(time);
} catch (Exception e) {
e.printStackTrace();
}
}
}
Employee Service
Java
public class Employee {
private Long id;
private Long companyId;
private String name;
// Constructor、Getter、Setter
}
@RestControllerpublic class EmployeeService {
@RequestMapping("/employee/{id}")public Employee getEmployeeById(@PathVariable("id") Long id) {
sleep();
return new Employee(id,1L," ");
}
@RequestMapping("/employee")public List getEmployeesByCompanyId(@RequestParam("companyId") Long companyId){
List employees = new ArrayList<>();
employees.add(new Employee(1L, companyId, " "));
employees.add(new Employee(2L, companyId, " "));
employees.add(new Employee(3L, companyId, " "));
sleep();
return employees;
}
private void sleep() {
Random rand = new Random();
int time = rand.nextInt(2000);
try {
Thread.sleep(time);
} catch (Exception e) {
e.printStackTrace();
}
}
}
public class Employee {
private Long id;
private Long companyId;
private String name;
// Constructor、Getter、Setter
}
@RestControllerpublic class EmployeeService {
@RequestMapping("/employee/{id}")public EmployeegetEmployeeById(@PathVariable("id") Long id) {
sleep();
return new Employee(id,1L," ");
}
@RequestMapping("/employee")public List getEmployeesByCompanyId(@RequestParam("companyId") Long companyId){
List employees = new ArrayList<>();
employees.add(new Employee(1L, companyId, " "));
employees.add(new Employee(2L, companyId, " "));
employees.add(new Employee(3L, companyId, " "));
sleep();
return employees;
}
private void sleep() {
Randomrand = new Random();
int time = rand.nextInt(2000);
try {
Thread.sleep(time);
} catch (Exception e) {
e.printStackTrace();
}
}
}
Product Service
Java
public class Product {
private Long id;
private Long companyId;
private String sku;
// Constructor、Getter、Setter
}
@RestControllerpublic class ProductService {
private static final Logger LOG = LoggerFactory.getLogger(ProductService.class);
@RequestMapping("/product/{id}")public Product getProductById(@PathVariable("id") Long id) {
sleep();
return new Product(id, 1L, "T001");
}
@RequestMapping("/product")public List getProductsByCompanyId(@RequestParam("companyId") Long companyId) {
List products = new ArrayList<>();
products.add(new Product(1L, companyId, "T001"));
products.add(new Product(2L, companyId, "T002"));
products.add(new Product(3L, companyId, "T003"));
return products;
}
private void sleep() {
Random rand = new Random();
int time = rand.nextInt(3000);
try {
Thread.sleep(time);
} catch (Exception e) {
e.printStackTrace();
}
}
}
public class Product {
private Long id;
private Long companyId;
private String sku;
// Constructor、Getter、Setter
}
@RestControllerpublic class ProductService {
private static final LoggerLOG = LoggerFactory.getLogger(ProductService.class);
@RequestMapping("/product/{id}")public ProductgetProductById(@PathVariable("id") Long id) {
sleep();
return new Product(id, 1L, "T001");
}
@RequestMapping("/product")public List getProductsByCompanyId(@RequestParam("companyId") Long companyId) {
List products = new ArrayList<>();
products.add(new Product(1L, companyId, "T001"));
products.add(new Product(2L, companyId, "T002"));
products.add(new Product(3L, companyId, "T003"));
return products;
}
private void sleep() {
Randomrand = new Random();
int time = rand.nextInt(3000);
try {
Thread.sleep(time);
} catch (Exception e) {
e.printStackTrace();
}
}
}
이 세 가지 서 비 스 는 모두 정상 적 인 독립 서비스 여야 한다.
모든 서 비 스 는 등록 센터 에서 현재 서 비 스 를 등록 해 야 하기 때문에 세 서비스의 시작 프로그램 에 주 해 를 추가 해 야 합 니 다 @ EnableDiscoveryClient
설정 파일 boottstrap. yml 에 다음 설정 을 추가 합 니 다.
YAML
spring: application: name: company-service
cloud: config: uri: ${vcap.services.${PREFIX:}configserver.credentials.uri:http://user:password@localhost:8888}
spring: application: name: company-service
cloud: config: uri: ${vcap.services.${PREFIX:}configserver.credentials.uri:http://user:password@localhost:8888}
서비스 센터
등록 센터 는 데모 에서 가장 간단 한 서비스 발견 과 등록 에 만 사용 되 며, 시작 프로그램 에 주석 을 달 아야 합 니 다 @ EnableEureka Server
@EnableDiscoveryClient
application. yml 에서 등록 서 비 스 를 설정 합 니 다.
YAML
server: port: 8761security: user: password: ${eureka.password}
eureka: client: registerWithEureka: false fetchRegistry: false server: waitTimeInMsWhenSyncEmpty: 0 password: ${SECURITY_USER_PASSWORD:password}
server:
port: 8761security:
user:
password: ${eureka.password}
eureka:
client:
registerWithEureka: false
fetchRegistry: false
server:
waitTimeInMsWhenSyncEmpty: 0
password: ${SECURITY_USER_PASSWORD:password}
\ # \ # \ # 원 격 호출 클 라 이언 트 어댑터
서비스 발견 을 사용 하여 실제 서비스 주 소 를 찾 고 API 가 되 돌아 오 는 데 이 터 를 가 져 옵 니 다.
API 구 조 를 바 꾸 기 위해 서 는 세 개의 model 을 만들어 야 합 니 다.
Java
public class CompanyAll {
private Long id;
private String name;
private List productList;
private List employeeList;
public CompanyAll(Company company, List productList, List employeeList) {
this.id = company.getId();
this.name = company.getName();
if (employeeList != null) {
this.productList = productList.stream().map(product ->
new ProductDetail(product.getId(), product.getSku())
).collect(Collectors.toList());
}
if (employeeList != null) {
this.employeeList = employeeList.stream().map(employee ->
new EmployeeDetail(employee.getId(), employee.getName())
).collect(Collectors.toList());
}
}
//Getter、Setter
}
public class EmployeeDetail {
private Long id;
private String name;
// Constructor、Getter、Setter
}
public class ProductDetail {
private Long id;
private String sku;
// Constructor、Getter、Setter
}
public class CompanyAll {
private Long id;
private String name;
private List productList;
private List employeeList;
public CompanyAll(Companycompany, List productList, List employeeList) {
this.id = company.getId();
this.name = company.getName();
if (employeeList != null) {
this.productList = productList.stream().map(product ->
new ProductDetail(product.getId(), product.getSku())
).collect(Collectors.toList());
}
if (employeeList != null) {
this.employeeList = employeeList.stream().map(employee ->
new EmployeeDetail(employee.getId(), employee.getName())
).collect(Collectors.toList());
}
}
//Getter、Setter
}
public class EmployeeDetail {
private Long id;
private String name;
// Constructor、Getter、Setter
}
public class ProductDetail {
private Long id;
private String sku;
// Constructor、Getter、Setter
}
도구 클래스 AppUtil 만 들 기
도구 클래스 에서 LoadBalancer Client 로 호출 됩 니 다. 이것 이 바로 넷 플 릭 스 리본 이 제공 하 는 Client 입 니 다.그 는 ServiceId (프로필 에 있 는 Service Name) 에 따라 Eureka (등록 서버) 에 서비스 주 소 를 가 져 옵 니 다.여기 서도 잘못 사용 하 는 체 제 를 제공 할 수 있 습 니 다. 극한 상황 에서 모든 지연 시 fallback Uri 를 사용 할 수 있 습 니 다.
Java
@Component
public class AppUtil {
@Autowired
private LoadBalancerClient loadBalancer;
public URI getRestUrl(String serviceId, String fallbackUri) {
URI uri = null;
try {
ServiceInstance instance = loadBalancer.choose(serviceId);
uri = instance.getUri();
} catch (RuntimeException e) {
uri = URI.create(fallbackUri);
}
return uri;
}
public ResponseEntity createOkResponse(T body) {
return createResponse(body, HttpStatus.OK);
}
public ResponseEntity createResponse(T body, HttpStatus httpStatus) {
return new ResponseEntity<>(body, httpStatus);
}
public T json2Object(ResponseEntity response, Class<T> clazz) {
try {
return (T) JSON.parseObject(response.getBody(), clazz);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public List json2Objects(ResponseEntity response, Class<T> clazz) {
try {
return JSON.parseArray(response.getBody(), clazz);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
@Component
public class AppUtil {
@Autowired
private LoadBalancerClientloadBalancer;
public URIgetRestUrl(String serviceId, String fallbackUri) {
URIuri = null;
try {
ServiceInstanceinstance = loadBalancer.choose(serviceId);
uri = instance.getUri();
} catch (RuntimeException e) {
uri = URI.create(fallbackUri);
}
return uri;
}
public ResponseEntity createOkResponse(T body) {
return createResponse(body, HttpStatus.OK);
}
public ResponseEntity createResponse(T body, HttpStatushttpStatus) {
return new ResponseEntity<>(body, httpStatus);
}
public T json2Object(ResponseEntity response, Class<T> clazz) {
try {
return (T) JSON.parseObject(response.getBody(), clazz);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public List json2Objects(ResponseEntity response, Class<T> clazz) {
try {
return JSON.parseArray(response.getBody(), clazz);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
물론 Api 에 대한 접근 및 Response 데이터 처리 클 라 이언 트 가 필요 합 니 다.
Java
@Component
public class RemoteServiceClient {
@Autowired
AppUtil appUtil;
private RestTemplate restTemplate = new RestTemplate();
public ResponseEntity getCompanyById(Long id) {
URI uri = appUtil.getRestUrl("COMPANY-SERVICE", "http://localhost:57773/");
String url = uri.toString() + "/company/" + id;
ResponseEntity<String> resultStr = restTemplate.getForEntity(url, String.class);
Company company = appUtil.json2Object(resultStr, Company.class);
return appUtil.createOkResponse(company);
}
public ResponseEntity<List> getEmployeesByCompanyId(Long id) {
try {
URI uri = appUtil.getRestUrl("EMPLOYEE-SERVICE", "http://localhost:58017");
String url = uri.toString() + "/employee?companyId=" + id;
ResponseEntity<String> resultStr = restTemplate.getForEntity(url, String.class);
List employees = appUtil.json2Objects(resultStr, Employee.class);
return appUtil.createOkResponse(employees);
} catch (Throwable t) {
throw t;
}
}
public ResponseEntity<List> getProductsByCompanyId(Long id) {
try {
URI uri = appUtil.getRestUrl("PRODUCT-SERVICE", "http://localhost:57750");
String url = uri.toString() + "/product?companyId=" + id;
ResponseEntity<String> resultStr = restTemplate.getForEntity(url, String.class);
List employees = appUtil.json2Objects(resultStr, Product.class);
return appUtil.createOkResponse(employees);
} catch (Throwable t) {
throw t;
}
}
}
@Component
public class RemoteServiceClient {
@Autowired
AppUtilappUtil;
private RestTemplaterestTemplate = new RestTemplate();
public ResponseEntity getCompanyById(Long id) {
URIuri = appUtil.getRestUrl("COMPANY-SERVICE", "http://localhost:57773/");
String url = uri.toString() + "/company/" + id;
ResponseEntity<String> resultStr = restTemplate.getForEntity(url, String.class);
Companycompany = appUtil.json2Object(resultStr, Company.class);
return appUtil.createOkResponse(company);
}
public ResponseEntity<List> getEmployeesByCompanyId(Long id) {
try {
URIuri = appUtil.getRestUrl("EMPLOYEE-SERVICE", "http://localhost:58017");
String url = uri.toString() + "/employee?companyId=" + id;
ResponseEntity<String> resultStr = restTemplate.getForEntity(url, String.class);
List employees = appUtil.json2Objects(resultStr, Employee.class);
return appUtil.createOkResponse(employees);
} catch (Throwable t) {
throw t;
}
}
public ResponseEntity<List> getProductsByCompanyId(Long id) {
try {
URIuri = appUtil.getRestUrl("PRODUCT-SERVICE", "http://localhost:57750");
String url = uri.toString() + "/product?companyId=" + id;
ResponseEntity<String> resultStr = restTemplate.getForEntity(url, String.class);
List employees = appUtil.json2Objects(resultStr, Product.class);
return appUtil.createOkResponse(employees);
} catch (Throwable t) {
throw t;
}
}
}
결국 외부 에 포트 를 노출 하여 데 이 터 를 되 돌려 야 합 니 다. 여기 도 Restful 인터페이스 입 니 다.
Java
@RestControllerpublic class RemoteAdapter {
private static final Logger LOG = LoggerFactory.getLogger(RemoteAdapter.class);
@Autowired
RemoteServiceClient client;
@Autowired
AppUtil appUtil;
@RequestMapping("/")public String welcome() {
return "welcome to use my demo";
}
@RequestMapping("/company/{id}")public ResponseEntity getCompany(@PathVariable("id") Long id) {
ResponseEntity companyResult = client.getCompanyById(id);
if (!companyResult.getStatusCode().is2xxSuccessful()) {
return appUtil.createResponse(null, companyResult.getStatusCode());
}
List products = null;
try {
ResponseEntity> productsResult = client.getProductsByCompanyId(id);
if (!productsResult.getStatusCode().is2xxSuccessful()) {
LOG.error(" Product API ");
} else {
products = productsResult.getBody();
}
} catch (Throwable t) {
LOG.error(" Product API ", t);
throw t;
}
List employees = null;
try {
ResponseEntity> employeeResult = null;
employeeResult = client.getEmployeesByCompanyId(id);
if (!employeeResult.getStatusCode().is2xxSuccessful()) {
LOG.error(" Employee API ");
} else {
employees = employeeResult.getBody();
}
} catch (Throwable t) {
LOG.error(" Employee API ");
throw t;
}
return appUtil.createOkResponse(new CompanyAll(companyResult.getBody(), products, employees));
}
}
@RestControllerpublic class RemoteAdapter {
private static final LoggerLOG = LoggerFactory.getLogger(RemoteAdapter.class);
@Autowired
RemoteServiceClientclient;
@Autowired
AppUtilappUtil;
@RequestMapping("/")public String welcome() {
return "welcome to use my demo";
}
@RequestMapping("/company/{id}")public ResponseEntity getCompany(@PathVariable("id") Long id) {
ResponseEntity companyResult = client.getCompanyById(id);
if (!companyResult.getStatusCode().is2xxSuccessful()) {
return appUtil.createResponse(null, companyResult.getStatusCode());
}
List products = null;
try {
ResponseEntity> productsResult = client.getProductsByCompanyId(id);
if (!productsResult.getStatusCode().is2xxSuccessful()) {
LOG.error(" Product API ");
} else {
products = productsResult.getBody();
}
} catch (Throwable t) {
LOG.error(" Product API ", t);
throw t;
}
List employees = null;
try {
ResponseEntity> employeeResult = null;
employeeResult = client.getEmployeesByCompanyId(id);
if (!employeeResult.getStatusCode().is2xxSuccessful()) {
LOG.error(" Employee API ");
} else {
employees = employeeResult.getBody();
}
} catch (Throwable t) {
LOG.error(" Employee API ");
throw t;
}
return appUtil.createOkResponse(new CompanyAll(companyResult.getBody(), products, employees));
}
}
Ok, 여 기 는 마지막 으로 application. yml 설정 파일 이 필요 합 니 다.물론 boottstrap. yml 의 등록 설정 은 빠 질 수 없습니다.
YAML
server: port: 0eureka: instance: leaseRenewalIntervalInSeconds: 10 metadataMap: instanceId: ${vcap.application.instance_id:${spring.application.name}:${spring.application.instance_id:${random.value}}}
client: registryFetchIntervalSeconds: 5
server:
port: 0
eureka:
instance:
leaseRenewalIntervalInSeconds: 10
metadataMap:
instanceId: ${vcap.application.instance_id:${spring.application.name}:${spring.application.instance_id:${random.value}}}
client:
registryFetchIntervalSeconds: 5
\ # \ # # 프 록 시 (경계) 서비스
경계 서 비 스 는 여기 서도 demo 에서 많은 기능 을 사용 하지 않 았 습 니 다. 여 기 는 퍼 가기 역할 만 사 용 했 기 때문에 너무 많은 설정 을 하지 않 아 도 됩 니 다.시작 프로그램 에 주석 @ Controller @ EnableZuulProxy 만 추가 하면 됩 니 다.
application. yml 에 서 는 서 비 스 를 설정 해 야 합 니 다. 상기 코드 에서 스 레 드 대기 시간 을 언급 하여 API 호출 시간 을 모 의 하기 때문에 ribbon 의 TimeOut 시간 을 60 초 로 설정 해 야 합 니 다.zuul 설정 에 가장 많이 사용 되 는 것 은 경로 입 니 다. Client 가 누 출 된 서비스 인터페이스 에 대해 경로 전송 을 하 는 것 입 니 다.
YAML
info: component: Zuul Server
endpoints: restart: enabled: true shutdown: enabled: true health: sensitive: falsehystrix: command: default: execution: timeout: enabled: falseribbon: ReadTimeout: 60000 ConnectTimeout: 6000zuul: ignoredServices: "*" routes: service-adapter: path: /app/**
server: port: 8765logging: level: ROOT: INFO
org.springframework.web: INFO
info:
component: Zuul Server
endpoints:
restart:
enabled: true
shutdown:
enabled: true
health:
sensitive: false
hystrix:
command:
default:
execution:
timeout:
enabled: false
ribbon:
ReadTimeout: 60000ConnectTimeout: 6000zuul:
ignoredServices: "*"routes:
service-adapter:
path: /app/**
server:
port: 8765
logging:
level:
ROOT: INFO
org.springframework.web: INFO
결과 미리 보기
원본: http://www.tuicool.com/articles/VbURJzQ
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Flutter 는 kotlin 프로젝트 에서 자바 방법 으로 데 이 터 를 제공 합 니 다.최근 안 드 로 이 드 프로젝트 를 쓸 때 다음 과 같은 문제 가 발생 했 습 니 다. Flutter 는 kotlin 프로젝트 에서 자바 방법 으로 데 이 터 를 제공 합 니 다. 이 수 요 는 정말 복잡 합 니 다...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.