服务提供者与服务消费者
生活随笔
收集整理的這篇文章主要介紹了
服务提供者与服务消费者
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
服務(wù)提供者和服務(wù)消費(fèi)者,名詞非常的高大上,但是其實(shí)很簡(jiǎn)單,我們看什么是服務(wù)提供者,什么是服務(wù)消費(fèi)者,服務(wù)的被調(diào)用方是服務(wù)的提供者,服務(wù)的調(diào)用方是消費(fèi)者,以我們之前的電影系統(tǒng)為例,一個(gè)用戶發(fā)起了購(gòu)票的請(qǐng)求,發(fā)現(xiàn)滿足要求了,去查當(dāng)前用戶的信息,然后在這種場(chǎng)景下,電影微服務(wù)就是一個(gè)服務(wù)消費(fèi)者,用戶微服務(wù)就是一個(gè)服務(wù)提供者,用戶微服務(wù)提供的一個(gè)接口被他消費(fèi)了,是這個(gè)意思
編寫一個(gè)服務(wù)提供者,然后再編寫一個(gè)簡(jiǎn)單的消費(fèi)者,還是以電影銷售系統(tǒng)為例,我們來模擬這種情況,發(fā)起一個(gè)遠(yuǎn)程的調(diào)用,首先我們寫一個(gè)服務(wù)提供者,我們先寫服務(wù)提供者,microservice-simple-provider-user,國(guó)內(nèi)阿里云的鏡像,這樣下載會(huì)比較快,他的parent是spring-boot-starter-parent,首先我們寫一些建表語句,drop table user;
create table user(id bigint generated by default as identity,username varchar(40),name varchar(20),age int(3),balance decimal(10,2), primary key(id)
);balance是余額插入一些數(shù)據(jù)insert into user(id,username, name, age, balance) values(1,'user1', '張三', 20, 100.00);
insert into user(id,username, name, age, balance) values(2,'user2', '李四', 20, 100.00);
insert into user(id,username, name, age, balance) values(3,'user3', '王五', 20, 100.00);
insert into user(id,username, name, age, balance) values(4,'user4', '馬六', 20, 100.00);@GetMapping它是一個(gè)組合注解,它是在Spring4.3以后支持的,同樣還有PostMapping,PutMapping,DeleteMapping,GetMapping他其實(shí)相當(dāng)于RequestMapping,RequestMethod的Get的混合注解,/*** Annotation for mapping HTTP {@code GET} requests onto specific handler* methods.** <p>Specifically, {@code @GetMapping} is a <em>composed annotation</em> that* acts as a shortcut for {@code @RequestMapping(method = RequestMethod.GET)}.*** @author Sam Brannen* @since 4.3* @see PostMapping* @see PutMapping* @see DeleteMapping* @see PatchMapping* @see RequestMapping*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@RequestMapping(method = RequestMethod.GET)
public @interface GetMapping {@RestController其實(shí)也是一個(gè)混合注解,相當(dāng)于加了ResonseBody和Controller,/*** A convenience annotation that is itself annotated with* {@link Controller @Controller} and {@link ResponseBody @ResponseBody}.* <p>* Types that carry this annotation are treated as controllers where* {@link RequestMapping @RequestMapping} methods assume* {@link ResponseBody @ResponseBody} semantics by default.** <p><b>NOTE:</b> {@code @RestController} is processed if an appropriate* {@code HandlerMapping}-{@code HandlerAdapter} pair is configured such as the* {@code RequestMappingHandlerMapping}-{@code RequestMappingHandlerAdapter}* pair which are the default in the MVC Java config and the MVC namespace.* In particular {@code @RestController} is not supported with the* {@code DefaultAnnotationHandlerMapping}-{@code AnnotationMethodHandlerAdapter}* pair both of which are also deprecated.** @author Rossen Stoyanchev* @author Sam Brannen* @since 4.0*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Controller
@ResponseBody
public @interface RestController {
<?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>com.learn</groupId><artifactId>microservice-simple-provider-user</artifactId><version>0.0.1-SNAPSHOT</version><packaging>jar</packaging><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>1.5.12.RELEASE</version><relativePath/> </parent><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><java.version>1.8</java.version><thymeleaf.version>3.0.9.RELEASE</thymeleaf.version><thymeleaf-layout-dialect.version>2.2.2</thymeleaf-layout-dialect.version></properties><dependencies><dependency><!-- 引入web模塊 --><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- Spring Boot進(jìn)行單元測(cè)試的模塊 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jdbc</artifactId></dependency> <dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><!-- 引入druid數(shù)據(jù)源 --><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.1.8</version></dependency><dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>1.3.2</version> </dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency></dependencies><!-- 這個(gè)插件,可以將應(yīng)用打包成一個(gè)可執(zhí)行的jar包 --><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>
package com.learn.cloud.controller;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;import com.learn.cloud.entity.User;
import com.learn.cloud.mapper.UserMapper;@RestController
public class UserController {@Autowiredprivate UserMapper userMapper;@GetMapping("/simple/{id}")public User findById(@PathVariable Long id) {return this.userMapper.getUserById(id);}}
package com.learn.cloud.mapper;import org.apache.ibatis.annotations.Mapper;import com.learn.cloud.entity.User;//@Mapper或者@MapperScan將接口掃描裝配到容器中
@Mapper
public interface UserMapper {public User getUserById(Long id);
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.learn.cloud.mapper.UserMapper"><select id="getUserById" resultType="com.learn.cloud.entity.User">select * from user where id = #{id}</select></mapper>
package com.learn.cloud.entity;import java.math.BigDecimal;public class User {private Long id;private String username;private String name;private Short age;private BigDecimal balance;public Long getId() {return this.id;}public void setId(Long id) {this.id = id;}public String getUsername() {return this.username;}public void setUsername(String username) {this.username = username;}public String getName() {return this.name;}public void setName(String name) {this.name = name;}public Short getAge() {return this.age;}public void setAge(Short age) {this.age = age;}public BigDecimal getBalance() {return this.balance;}public void setBalance(BigDecimal balance) {this.balance = balance;}
}
package com.learn.cloud;import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@MapperScan(value="com.learn.cloud.mapper")
@SpringBootApplication
public class MicroserviceSimpleProviderUserApplication {public static void main(String[] args) {SpringApplication.run(MicroserviceSimpleProviderUserApplication.class, args);}
}
#debug=true
server.port=7900#server.context-path=/boot02spring.http.encoding.charset=UTF-8
spring.http.encoding.enabled=true
spring.http.encoding.force=truelogging.level.com.learn=trace
#logging.file=D:/springboot.log
logging.file=springboot.log
#logging.path=/spring/log
logging.pattern.console=%d{yyyy-MM-dd} [%thread] %-5level %logger{50} - %msg%n
logging.pattern.file=%d{yyyy-MM-dd} ==== [%thread] %-5level ==== %logger{50} ==== %msg%n
#spring.resources.static-locations=classpath:/hello,classpath:/learnspring.datasource.username=root
spring.datasource.password=123456
spring.datasource.url=jdbc:mysql://59.110.158.145:3306/SpringCloud?useSSL=false&useUnicode=true&characterEncoding=UTF-8
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.initialSize=5
spring.datasource.minIdle=5
spring.datasource.maxActive=20
spring.datasource.maxWait=60000mybatis.config-location=classpath:mybatis/mybatis-config.xml
mybatis.mapper-locations=classpath:mybatis/mapper/*.xml
http://localhost:7900/simple/1{"id":1,"username":"user1","name":"張三","age":20,"balance":100.00}
我們發(fā)現(xiàn)是可以正常訪問的,這樣一個(gè)非常簡(jiǎn)單的用戶微服務(wù)我們已經(jīng)寫完了DROP DATABASE IF EXISTS SpringCloud;
create database SpringCloud;
use SpringCloud;CREATE TABLE `user` (`id` bigint(20) NOT NULL,`username` varchar(40) DEFAULT NULL,`name` varchar(20) DEFAULT NULL,`age` int(3) DEFAULT NULL,`balance` decimal(10,2) DEFAULT NULL,PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;insert into user(id,username,name,age,balance) values(1,'user1','張三',20,100);insert into user(id,username,name,age,balance) values(2,'user2','李四',20,100);現(xiàn)在我們寫一下服務(wù)消費(fèi)者,也就是這邊的movie項(xiàng)目,我們讓他比較簡(jiǎn)單的去調(diào)用這個(gè)user,這個(gè)微服務(wù),nohup java -jar microservice-simple-provider-user-0.0.1-SNAPSHOT.jar &sudo apt-get install iptablessudo aztech aztechsudo iptables -I INPUT -p tcp --dport 7900 -j ACCEPTsudo iptables-save10.40.8.152:7900/simple/1微服務(wù)服務(wù)之間是有自治的,所以我們啟動(dòng)movie也是OK的,即使User沒有啟動(dòng)好,啟動(dòng)user也是OK的,restTemplate有問題,因?yàn)槲覀儧]有new,我們?cè)趩?dòng)類上加一點(diǎn)小小的配置@Bean
public RestTemplate restTemplate() {return new RestTemplate();
}@Bean會(huì)把實(shí)例化的RestTemplate以方法名去命名,他的名稱是restTemplate,啟動(dòng)7901,也就是movie這個(gè)微服務(wù)localhost:7901/movie/1
<?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>com.learn</groupId><artifactId>microservice-simple-consumer-movie</artifactId><version>0.0.1-SNAPSHOT</version><packaging>jar</packaging><name>microservice-simple-consumer-movie</name><description>Demo project for Spring Boot</description><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>1.5.12.RELEASE</version><relativePath/> </parent><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><java.version>1.8</java.version></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-test</artifactId><scope>test</scope></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>
#debug=true
server.port=7901user.userServicePath: http://10.40.8.152:7900/simple/
package com.learn.cloud.entity;import java.math.BigDecimal;public class User {private Long id;private String username;private String name;private Short age;private BigDecimal balance;public Long getId() {return this.id;}public void setId(Long id) {this.id = id;}public String getUsername() {return this.username;}public void setUsername(String username) {this.username = username;}public String getName() {return this.name;}public void setName(String name) {this.name = name;}public Short getAge() {return this.age;}public void setAge(Short age) {this.age = age;}public BigDecimal getBalance() {return this.balance;}public void setBalance(BigDecimal balance) {this.balance = balance;}}
package com.learn.cloud.controller;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;import com.learn.cloud.entity.User;@RestController
public class MovieController {@Autowiredprivate RestTemplate restTemplate;@Value("${user.userServicePath}")private String userServicePath;@GetMapping("/movie/{id}")public User findById(@PathVariable Long id) {return this.restTemplate.getForObject(this.userServicePath + id, User.class);}
}
package com.learn.cloud;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 MicroserviceSimpleConsumerMovieApplication {@Beanpublic RestTemplate restTemplate() {return new RestTemplate();}public static void main(String[] args) {SpringApplication.run(MicroserviceSimpleConsumerMovieApplication.class, args);}
}
是可以正常請(qǐng)求到user服務(wù)的,是可以用到user服務(wù)的接口的,同時(shí)寫了一個(gè)服務(wù)消費(fèi)者,我們總結(jié)一下需要注意點(diǎn),首先是服務(wù)提供者,第一個(gè)是@GetMapping,它是一個(gè)組合注解,是Spring4.3給我們提供的一個(gè)注解,yml是有嚴(yán)格的縮進(jìn)的,可以是兩個(gè)空格縮進(jìn),也可以是四個(gè)空格縮進(jìn),然后回到movie這個(gè)項(xiàng)目,@Bean注解,我們用方法名稱,作為實(shí)例化后的Bean的名稱@Bean
public RestTemplate restTemplate() {return new RestTemplate();
}相當(dāng)于RestTemplate restTemplate = new RestTemplate();目前這個(gè)架構(gòu)其實(shí)是存在很多問題的,我現(xiàn)在是在消費(fèi)的這一側(cè),把這個(gè)硬編碼了,在傳統(tǒng)的一些項(xiàng)目里面,大概沒有太多的問題了,因?yàn)檫@些環(huán)境都是比較固定的,IP端口都是比較固定的,但是在現(xiàn)在這種新式的環(huán)境下,就不一樣了,比如說docker,在一些云環(huán)境里面,IP和端口往往是動(dòng)態(tài)的,當(dāng)我把provider-user部署好了之后,他的IP和端口往往是動(dòng)態(tài)的,那這個(gè)時(shí)候我們?cè)趺慈ミM(jìn)行一個(gè)配置呢,加上我provider重新的進(jìn)行上限,他的IP進(jìn)行了變更,那這邊怎么樣去玩呢,所以硬編碼是行不通的,但是即使這樣也不行@Value("${user.userServicePath}")
private String userServicePath;user.userServicePath: http://10.40.8.152:7900/simple/當(dāng)然變得好維護(hù)了一些,當(dāng)他的IP和端口發(fā)生了變化的時(shí)候,我這邊也要重新的配置,重新的啟動(dòng),當(dāng)他又為其它的服務(wù)提供服務(wù),那別的服務(wù)是不是也得改配置,這種維護(hù)量是很大的,這是第一個(gè)問題,第二個(gè)問題,movie微服務(wù)調(diào)用user微服務(wù),當(dāng)然它是提供者,現(xiàn)在這種情況是直接調(diào),但是他有一定的問題,當(dāng)我有多個(gè)提供的節(jié)點(diǎn)的時(shí)候,我怎么做到負(fù)載,中間加Nginx,由Nginx完成轉(zhuǎn)發(fā),但是我們要知道,在一個(gè)復(fù)雜的項(xiàng)目里面,幾百個(gè)微服務(wù),甚至上萬個(gè),這都是有可能的,像亞馬遜光首頁,700個(gè)微服務(wù),那是不是只要有服務(wù)調(diào)用的時(shí)候,就加個(gè)nginx,那這個(gè)也是非常的難管理,那怎么去解決目前的這種問題呢
?
總結(jié)
以上是生活随笔為你收集整理的服务提供者与服务消费者的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 开始使用Spring Cloud实战微服
- 下一篇: MYBATIS 批量update 报错的