概述
Today is 乐优商城的第二天,学习了系统架构的发展,微服务和springcloud的Eureka,每天学新东西都是多的,但是一想到我们的项目不是淘淘商城了,是一个全新的项目,就充满希望,想把这个全新的项目学好。
一.系统架构的演进
1.集中式架构,所有的模块都耦合在一起
2.垂直拆分,分家,各模块相对独立,但是每一个模块都直接和数据库打交道,产生了很多重复的工作
3.分布式服务,将系统的基础服务进行抽取,各个业务都可以调用这些服务,提高了代码服用和开发效率。但是缺乏统一管理,相当于每一个模块都是直接和那些基础服务打交道的。导致关系错综复杂。
4.SOA面向服务,有一个统一的注册中心来管理服务。
5.微服务,服务拆分的更小。
二.服务调用的方式
既然发展到微服务,那么服务之间是怎么通信的?
两种方式:1.RPC和Http
RPC远程服务调用,将请求序列化,通过网络传输,在接收端进行反序列化解析,拿到参数,执行方法,再将结果序列化返回
Http则通过http协议进行通信,信息封装在请求行,请求头,请求体中。
从三个方向比较
1.速度 RPC速度更快
2.难度 RPC更难实现,http简单
3.灵活度 http通过rest风格的链接相互调用,RPC需要更服务之间用相同的语言,因为传入的参数,方法可以接手。并且约定好序列化和反序列化的方式
我们追求自由,不喜欢收到多的限制,所以我们选择基于Http的Rest风格的服务。
三.JAVA代码如何处理HTTP请求?(Http客户端工具)
主流有三种:
OKHttp
URLConnection
客服端发送请求http请求,并接受响应。这里以HttpClient为例,看java代码中如何使用HttpClient发送http请求的
在使用HttpClient之前,需要先创建对象
CloseableHttpClient httpClient; @Before public void init() { httpClient = HttpClients.createDefault(); }
如果是get请求,发送请求request得到响应response
HttpGet request = new HttpGet("http://localhost:8081/list"); String response = this.httpClient.execute(request, new BasicResponseHandler());
就相当于用一个类进行发送请求和得到响应
这样会相当麻烦,因为不同的客户端需要编写不同的代码,而spring给我们提供了一个通用的模版,restTemplate,她是对常用客户端的一个简单封装,我们只要写通用的代码就可以实现发送请求和得到响应,用法如下:
首先将RestTemplate交给IOC管理,我们使用的是okHttp3ClientHttpRequestFactory
@Bean public RestTemplate restTemplate() { return new RestTemplate(new OkHttp3ClientHttpRequestFactory()); }
创建完对象后,restTemplate可以直接发送请求,并将响应解析成对象
得到普通对象:
User user = this.restTemplate.getForObject("http://localhost:8081/hello", User.class);
得到集合:
List<User> list = restTemplate.getForObject("http://localhost:8081/list", List.class);
四.模拟服务提供者和消费者
当我们可以在java中处理http请求后,我们就可以模拟一个服务提供者和消费者的案例。
消费者通过restTemplate发送http请求,得到响应。但是,这样会产生问题,
1.http请求都是被硬编码到消费者里面的,如果我们的请求地址发生变化,我们还得去java代码里面去更改。
2.不利于扩展,这样始终只有一个服务提供者为我服务,我想要一个集群为我服务,这个坏了,我还可以用里一个备用的,还可以达到负载均衡的目的。
因为有这样的需求,我们需要一个管理者。而这个管理者是springcloud给我们提供的eureka
五.注册中心Eureka
我们对消费者和服务进行改造,服务提供者去注册中心去注册服务,消费者去注册中心去拉取服务。这样,一切都清晰起来,消费者不需要知道服务的提供者是谁,只需要知道他需要什么服务。服务提供者也不需要知道他为谁服务,只需要把服务交个注册中心就行了。
那么,我们想实现这个逻辑,肯定先得有个注册中心,所以注册中心必须先准备好。
- 搭建服务中心
注册中心是springcloud的一个组件,我们得引入springcloud,我们可以用idea的springInitializr快速构建一个springboot项目,并引入依赖,而如果只有一个注册中心,不安全,我们为了高可用性,一般会有多个注册中新,他们互相注册,让彼此知道对方的存在。这需要在配置文件中配置,具体配置如下:
server: port: 10086 # 端口 spring: application: name: eureka-server # 应用名称,会在Eureka中显示 eureka: client: service-url: # 配置其他Eureka服务的地址,而不是自己,比如10087 defaultZone: http://127.0.0.1:10087/eureka
配置文件配置好之后,我们需要启动eureka服务,而spring并不知道我们这是一个eureka服务,于是我们需要告诉程序,我们是一个eureka服务,方式就是引入注解。
@SpringBootApplication @EnableEurekaServer在启动类上面再加一个@EnableEurekaServer注解
这样,注册中心就搭建完成了。
- 搭建服务提供者
注册中心搭建完成后,显然下一个就是搭建服务,让服务去注册中心去注册,最后才是消费者去注册中心拉取服务,那么我们开始服务的搭建。步骤跟搭建注册中心差不多,1.写配置文件,2.启动的时候,告诉启动类,去注册中心注册自己
server: port: 8081 spring: datasource: url: jdbc:mysql://localhost:3306/day0308 username: root password: 123 hikari: maximum-pool-size: 20 minimum-idle: 10 application: name: user-service # 应用名称 eureka: client: service-url: # EurekaServer地址 defaultZone: http://127.0.0.1:10086/eureka,http://127.0.0.1:10087/eureka instance: lease-expiration-duration-in-seconds: 10 # 10秒即过期 lease-renewal-interval-in-seconds: 5 # 5秒一次心跳 prefer-ip-address: true # 当调用getHostname获取实例的hostname时,返回ip而不是host名称 ip-address: 127.0.0.1 # 指定自己的ip信息,不指定的话会自己寻找 mybatis: type-aliases-package: com.cloud.pojo
主要配置了服务的id,注册中心的地址,还有心跳。
@SpringBootApplication @MapperScan("com.cloud.mapper") @EnableDiscoveryClient
启动类添加的注解
- 搭建消费者
消费者其实也相当于一个服务,也需要去注册中心注册,所以他的搭建方法跟服务提供者差不多
server: port: 8082 spring: application: name: consumer eureka: client: service-url: defaultZone: http://127.0.0.1:10086/eureka instance: prefer-ip-address: true ip-address: 127.0.0.1
@SpringBootApplication @EnableDiscoveryClient
消费者去注册中心获取服务的方法
@Autowired private DiscoveryClient discoveryClient; public User queryUserById(Long id) { List<ServiceInstance> instances = discoveryClient.getInstances("USER-SERVICE"); ServiceInstance serviceInstance = instances.get(0);通过instances可以获得instances,通过instances可以获得端口号和ip,这样就能拼接得到url,这就是eurake的作用。当然后面的负载均衡我们连instance都不需要了,直接写服务地址就好了。
其他:
1.在不用restTemlate的情况下,怎么将json转化为对象?
首先注入mapper对象
ObjectMapper mapper; @Before public void init() { mapper = new ObjectMapper(); }
对于普通java类
User users = mapper.readValue(response,User.class);
对集合
List<User> users = mapper.readValue(response, mapper.getTypeFactory().constructCollectionType(List.class, User.class));另外,对mapper类我们采取了封装工具类,在我的工具类中可以找到
2.ymal语法
server:
port: 8081
spring:
datasource:
url: jdbc:mysql://localhost:3306/mydb01
username: root
password: 123
hikari:
maximum-pool-size: 20
minimum-idle: 10
mybatis:
type-aliases-package: com.leyou.userservice.pojo
代替properties文件
3.JDK8新特性lambda表达式
ids.forEach(id -> { // 我们测试多次查询, users.add(this.restTemplate.getForObject(url + id, User.class)); // 每次间隔500毫秒 try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } });
对ids这个集合进行forech遍历,这样就代替了foreach
下面连接是大佬对lambda的理解:
https://blog.csdn.net/ioriogami/article/details/12782141/
最后
以上就是缥缈中心为你收集整理的乐优商城第二天(Springcloud上)的全部内容,希望文章能够帮你解决乐优商城第二天(Springcloud上)所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复