小程序 graphql_GraphQL应用程序中的五个常见问题(以及如何解决)-程序员宅基地

技术标签: python  java  编程语言  mysql  数据库  

小程序 graphql

by Sacha Greif

由Sacha Greif

GraphQL应用程序中的五个常见问题(以及如何解决) (Five Common Problems in GraphQL Apps (And How to Fix Them))

了解如何释放GraphQL的强大功能而不会遭受缺点 (Learn to unlock the power of GraphQL without suffering its drawbacks)

GraphQL is all the rage these days, and for good reason: it’s an elegant approach that solves many of the problems associated with traditional REST APIs.

GraphQL如今风靡一时,这是有充分理由的:这是一种优雅的方法,可以解决与传统REST API相关的许多问题。

Yet I’d be lying if I told you that GraphQL doesn’t come with its own set of issues. And if you’re not careful, these issues might not only lead to a bloated codebase, but even to a dramatically slowed-down app.

但是,如果我告诉您GraphQL没有它自己的问题,那我会撒谎。 而且,如果您不小心,这些问题可能不仅会导致代码库过大,甚至会导致应用程序速度大大降低。

I’m talking about problems such as:

我说的是诸如以下的问题:

  • Schema duplication

    模式复制

  • Server/client data mismatch

    服务器/客户端数据不匹配

  • Superfluous database calls

    多余的数据库调用

  • Poor performance

    表现不佳

  • Boilerplate overdose

    样板过量

I’m willing to bet your app suffers from at least one of them. Good news is, none of them are incurable!

我敢打赌,您的应用至少会遭受其中之一的困扰。 好消息是,没有一个是无法治愈的!

For each issue, I’ll describe the problem, and then explain how I’m addressing it inside Vulcan, a React/GraphQL open-source framework I’ve been working on over the past year (you should check it out!). But hopefully, you’ll be able to apply the same strategies to your own codebase whether you use Vulcan or not.

对于每个问题,我将描述问题,然后解释如何在过去一年来一直在致力于的React / GraphQL开源框架Vulcan中解决它(您应该检查一下!)。 但是希望无论您是否使用Vulcan,您都可以将相同的策略应用于自己的代码库。

问题:模式复制 (Problem: Schema Duplication)

One of the first things you realize when coding a GraphQL back-end from scratch is that it involves a lot of similar-but-not-quite-identical code, especially when it comes to schemas.

从头开始编写GraphQL后端时,您会意识到的第一件事是,它涉及许多相似但不完全相同的代码,尤其是涉及架构时。

Namely, you need one schema for your database, and another one for your GraphQL endpoint. Not only is it frustrating to have to write more or less the same thing twice, but you now have two independent sources of truths that you need to constantly keep in sync.

即,您需要一个数据库架构,另一个需要GraphQL端点。 不得不多写或少写两次相同的东西不仅令人沮丧,而且您现在拥有两个独立的真理来源,需要不断保持同步。

解决方案:GraphQL模式生成 (Solution: GraphQL Schema Generation)

A number of solutions to this problem have emerged in the GraphQL ecosystem. For example, PostGraphile generates a GraphQL schema from your PostgreSQL database, and Prisma will also help you generate types for your queries and mutations.

GraphQL生态系统中出现了许多解决此问题的方法。 例如, PostGraphile从PostgreSQL数据库生成GraphQL模式, Prisma也将帮助您生成查询和变异的类型。

I also remember hearing Laney Zamore & Adam Kramer from the GraphQL team describe how they directly generated their GraphQL schema from their PHP type definitions.

我还记得GraphQL团队的Laney Zamore和Adam Kramer讲述了他们如何直接从PHP类型定义中生成GraphQL模式。

For Vulcan, I independently stumbled on a very similar solution. I was using SimpleSchema to describe my schemas as JavaScript objects, and I started simply by converting JavaScript’s String type into a GraphQL String, Number into Int or Float, and so on.

对于Vulcan,我独立地偶然发现了一个非常相似的解决方案。 我当时使用SimpleSchema将模式描述为JavaScript对象,然后开始将JavaScript的String类型转换为GraphQL String ,将Number转换为IntFloat ,等等。

So this JavaScript field:

所以这个JavaScript字段:

title: {  type: String}

Would become this GraphQL field:

将成为此GraphQL字段:

title: String

But of course, a GraphQL schema can also have custom types: User, Comment, Event, and so on.

但是,当然,GraphQL架构也可以具有自定义类型: UserCommentEvent等等。

I didn’t want to add too much magic to the schema generation step, so I came up with field resolvers, a simple way to let you specify these custom types. So that this JavaScript field:

我不想在架构生成步骤中添加太多的魔力,所以我想出了字段解析器 ,这是一种让您指定这些自定义类型的简单方法。 这样这个JavaScript字段:

userId{  type: String,  resolveAs: {    fieldName: 'user',    type: 'User',    resolver: document => {      return Users.findOne(document.userId)    }  }}

Becomes:

成为:

user: User

As you can see, we’re defining the actual resolver function on the field as well, since it’s also directly related to the GraphQL field.

如您所见,由于它也与GraphQL字段直接相关,因此我们也在该字段上定义了实际的解析程序功能。

So whether you use something like PostGraphile or write your own schema generation code, I encourage you to avoid schema duplication in your own app.

因此,无论您使用PostGraphile之类的东西还是编写自己的模式生成代码,我都建议您避免在自己的应用程序中重复模式。

Or of course, you can also use a hosted service such as Graphcool to manage your schema using their dashboard and bypass that issue entirely.

或者,当然,您也可以使用诸如Graphcool之类的托管服务通过其仪表板管理您的架构,并完全绕开该问题。

问题:服务器/客户端数据不匹配 (Problem: Server/Client Data Mismatch)

As we’ve just seen, your database and GraphQL API will have different schemas, which translate into different document shapes.

如我们所见,您的数据库和GraphQL API将具有不同的架构,这些架构将转换为不同的文档形状。

So while a post fresh out of the database will have a userId property, the same post as fetched through your API will instead have a user property.

因此,虽然从数据库中重新post将具有userId属性,但与通过您的API提取的post相同,将具有一个user属性。

This means that getting a post author’s name on the client will look like:

这意味着在客户端上获得帖子作者的姓名将类似于:

const getPostNameClient = post => {  return post.user.name}

But on the server, it’ll be a different story altogether:

但是在服务器上,这将是完全不同的故事:

const getPostNameServer = post => {  const postAuthor = Users.findOne(post.userId)  return postAuthor.name}

This can be a problem anytime you’re trying to share code between client and server to simplify your codebase. And even beyond that, it means you’re missing out on GraphQL’s great approach to data querying on the server.

每当您尝试在客户端和服务器之间共享代码以简化代码库时,这都是一个问题。 甚至除此之外,这意味着您会错过GraphQL在服务器上进行数据查询的出色方法。

I recently felt that pain when trying to build a system to generate weekly newsletters: each newsletter was composed of multiple posts and comments, along with info about their authors; in other words, a perfect use case for GraphQL. But this newsletter generation was happening on the server, meaning I didn’t have a way to query my GraphQL endpoint…

最近,当我尝试构建一个每周新闻通讯系统时,我感到非常痛苦:每个新闻通讯由多个帖子和评论以及有关作者的信息组成; 换句话说,是GraphQL的完美用例。 但是,此新闻通讯正在服务器上发生,这意味着我无法查询GraphQL端点…

解决方案:服务器到服务器的GraphQL查询 (Solution: Server-to-Server GraphQL Queries)

Or did I? It turns out that you can run server-to-server GraphQL queries just fine! Just pass your GraphQL executable schema to the graphql function, along with your GraphQL query:

还是我? 事实证明,您可以运行服务器对服务器的GraphQL查询! 只需将您的GraphQL可执行模式与GraphQL查询一起传递给graphql函数

const result = await graphql(executableSchema, query, {}, context, variables);

In Vulcan, I generalized this pattern into a runQuery helper, and I also added queryOne functions to each collection. These act just like MongoDB’s findOne except they return the document as fetched through the GraphQL API:

在Vulcan中, 我将此模式概括为runQuery helper ,并且还向每个集合添加了queryOne函数。 这些行为与MongoDB的findOne除了它们返回通过GraphQL API获取的文档:

const user = await Users.queryOne(userId, {  fragmentText: `    fragment UserFragment on User {      _id      username      createdAt      posts{        _id        title      }    }  `});

Server-to-server GraphQL queries have helped me drastically simplify my code. It let me refactor my newsletter generation call from a mess of successive database calls and loops to a single GraphQL query:

服务器到服务器的GraphQL查询帮助我极大地简化了代码。 它使我可以从一堆连续的数据库调用和循环中重构我的新闻通讯生成调用,以循环到单个GraphQL查询:

query NewsletterQuery($terms: JSON){  SiteData{    title  }  PostsList(terms: $terms){    _id    title    url    pageUrl    linkUrl    domain    htmlBody    thumbnailUrl    commentsCount    postedAtFormatted    user{      pageUrl      displayName    }    comments(limit: 3){      user{        displayName        avatarUrl        pageUrl      }      htmlBody      postedAt    }  }}

The takeaway here: don’t see GraphQL as just a pure client-server protocol. GraphQL can be used to query data in any situation, including client-to-client with Apollo Link State or even during a static build process with Gatsby.

这里的要点:不要将GraphQL视为纯粹的客户端-服务器协议。 GraphQL可用于在任何情况下查询数据,包括具有Apollo链接状态的客户端到客户端,甚至在使用Gatsby的静态构建过程中。

问题:多余的数据库调用 (Problem: Superfluous Database Calls)

Imagine a list of posts, each of which has a user attached to it. You now want to display 10 of these posts, along with the name of their author.

想象一下一个帖子列表,每个帖子都具有一个用户。 现在,您要显示其中的10条帖子,以及其作者的姓名。

With a typical implementation, this would mean two database calls. One to get the 10 posts, and one to get the 10 users corresponding to these posts.

对于典型的实现,这将意味着两个数据库调用。 一个获得10个帖子,一个获得10个与这些帖子对应的用户。

But what about GraphQL? Assuming our posts have a user field with its own resolver, we still have one initial database call to get the list of posts. But we now have an extra call to fetch each user per resolver, for a total of 11 database calls!

但是GraphQL呢? 假设我们的帖子有一个带有自己的解析程序的user字段,我们仍然有一个初始数据库调用来获取帖子列表。 但是我们现在有一个额外的调用来为每个解析器获取每个用户,总共有11个数据库调用!

Now imagine that each post also has 5 comments, each of which has an author. Our number of calls has now ballooned to:

现在想象每个帖子也有5条评论,每个评论都有一位作者。 我们的电话数量现已激增至:

  • 1 for the list of posts

    帖子列表1
  • 10 for the post authors

    帖子作者10个
  • 10 for each sub-list of 5 comments

    每5则评论的子清单10个
  • 50 for the comment authors

    评论作者50个

For a grand total of 71 database calls to display a single view!

共显示71个数据库调用,以显示单个视图

Nobody wants to have to explain to their boss why the homepage is taking 25 seconds to load. Thankfully, there’s a solution: Dataloader.

没人愿意向老板解释为什么首页要花25秒钟来加载。 幸运的是,有一个解决方案: Dataloader

解决方案:数据加载器 (Solution: Dataloader)

Dataloader will let you batch and cache database calls.

Dataloader使您可以批处理和缓存数据库调用。

  • Batching means that if Dataloader figures out that you’re hitting the same database table multiple times, it’ll batch all calls together. In our example, the 10 post authors’ and 50 comment authors’ calls would all be batched into a single call.

    批处理意味着,如果Dataloader发现您多次访问同一数据库表,则它将所有调用一起批处理。 在我们的示例中,10个帖子作者的呼叫和50个评论作者的呼叫将全部合并为一个呼叫。

  • Caching means that if Dataloader detects that two posts (or a post and a comment) have the same author, it will reuse the user object it already has in memory instead of making a new database call.

    缓存意味着,如果Dataloader检测到两个帖子(或一个帖子和一个评论)具有相同的作者,它将重用它已经在内存中拥有的用户对象,而不是进行新的数据库调用。

In practice you don’t always achieve perfect caching and batching, but Dataloader is still a huge help.

在实践中,您并不总是能够实现完美的缓存和批处理,但是Dataloader仍然是一个巨大的帮助。

And Vulcan makes using Dataloader extra easy. Out of the box, every Vulcan model includes Dataloader functions as alternatives to the “normal” MongoDB query functions.

Vulcan使得使用Dataloader变得异常容易。 开箱即用, 每个Vulcan模型都包含Dataloader函数,以替代“常规” MongoDB查询函数。

So in addition to collection.findOne and collection.find, you can use collection.loader.load and collection.loader.loadMany.

因此,除了collection.findOnecollection.find ,您还可以使用collection.loader.loadcollection.loader.loadMany

The one limitation is that Dataloader only works when querying using document IDs. So you can use it to query for a document whose ID is already known, but you’ll still need to hit your database if you want to ask for, say, the most recently created post.

一个限制是Dataloader仅在使用文档ID查询时才起作用。 因此,您可以使用它来查询ID已知的文档,但是如果您要查询(例如)最近创建的帖子,仍然需要打数据库。

问题:性能不佳 (Problem: Poor Performance)

Even with Dataloader enabled, complex views can still trigger multiple database calls, which in turn can make for slow loading times.

即使启用了Dataloader,复杂的视图仍然可以触发多个数据库调用,这又会导致加载时间变慢。

This can be frustrating: on one hand you want to take full advantage of GraphQL’s graph traversal features (“show me the authors of the comments of the author of the post of…” etc.). But on the other hand, you don’t want your app to become slow and unresponsive.

这可能令人沮丧:一方面,您想充分利用GraphQL的图遍历功能(例如,“向我显示...帖子作者的评论的作者”等)。 但另一方面,您不希望您的应用变慢且无响应。

解决方案:查询缓存 (Solution: Query Caching)

There is a solution though, which is to cache the entire GraphQL query response. Unlike Dataloader, whose scope is limited to the current request (meaning it will only cache documents within the same query), I’m talking here about caching the whole query for a period of time.

但是,有一个解决方案,就是缓存整个 GraphQL查询响应。 不同的DataLoader,其范围仅限于当前请求(这意味着它只会缓存在同一查询的文件),我在这里谈论缓存整个查询一段时间。

Apollo Engine is a great way to do just that. It’s a hosted service that provides analytics about your GraphQL queries, but it also has a very useful caching feature.

Apollo Engine是做到这一点的好方法。 它是一项托管服务,可提供有关GraphQL查询的分析,但它也具有非常有用的缓存功能

Vulcan comes with a built-in Engine integration, you just need to add your API key to your settings file. You can then add the enableCache: true argument to your GraphQL queries to cache them using Engine.

Vulcan带有内置的Engine集成,您只需要将API密钥添加到设置文件中即可。 然后,您可以向您的GraphQL查询添加enableCache: true参数,以使用Engine对其进行缓存。

Or, using Vulcan’s built-in data-loading higher-order components:

或者,使用Vulcan的内置数据加载高阶组件

withList({  collection: Posts,   enableCache: true})(PostsList)

The beauty of this approach is that you can easily control which queries are cached and which aren’t, even for the same resolver. For example, you might want to cache the list of recent posts featured on your frequently-accessed homepage, but not the full list of posts available on your archives page.

这种方法的优点在于,即使对于同一个解析器,您也可以轻松控制哪些查询被缓存,哪些不缓存。 例如,您可能想缓存您经常访问的主页上的最新帖子列表,而不是存档页面上可用帖子的完整列表。

A final note: caching might not always be possible. For example, it’s not advisable for data that changes frequently, or for data that depends on the currently logged-in user.

最后一点:并非总是可能进行缓存。 例如,对于频繁更改的数据或依赖于当前登录用户的数据,建议不要这样做。

问题:样板过量 (Problem: Boilerplate Overdose)

This is by no means an issue exclusive to GraphQL apps, but it’s true that they generally require you to write a lot of similar boilerplate code.

这绝不是GraphQL应用程序独有的问题,但确实,它们通常需要您编写很多类似的样板代码。

Typically, adding a new model (e.g. Comments) to your app will involve the following steps:

通常,向您的应用添加新模型(例如Comments )将涉及以下步骤:

  • Writing a resolver to get a list of comments.

    编写解析器以获取评论列表。
  • Writing a higher-order component (a.k.a. container) to load that list of comments.

    编写一个高阶组件(也称为容器)以加载该评论列表。
  • Optionally, writing a resolver to get a single comment by ID or slug along with the corresponding higher-order component.

    (可选)编写解析器以获取ID或Slug以及相应的高阶组件的单个注释。
  • Writing mutations for inserting a new comment, editing a comment, and deleting a comment.

    编写用于插入新注释,编辑注释和删除注释的变体。
  • Adding the corresponding forms and form-handling code.

    添加相应的表单和表单处理代码。

That’s a whole lot of CRUD!

这是很多CRUD!

解决方案:通用解析器,突变和高阶组件 (Solution: Generic Resolvers, Mutations, and Higher-Order Components)

Vulcan’s approach is to give you smart, easy-to-use generic options for each of these. You’ll get:

Vulcan的方法是为每个选项提供智能,易于使用的通用选项。 你会得到:

These are all written in a generic enough way that they’ll work with any new model out of the box.

这些都以足够通用的方式编写,可以与任何新模型一起使用。

To be sure, this “one-size-fits-all” approach is not without its downsides. For example, because queries are generated dynamically by the generic higher-order components, it’s a bit harder to use static queries.

可以肯定的是,这种“千篇一律”的方法并非没有缺点。 例如,由于查询是由通用的高阶组件动态生成的,因此使用静态查询会有点困难。

But this strategy is still a great way to get started, at least until you have time to refactor each part of your app to a more tailor-made solution.

但是,至少在您有时间将应用程序的每个部分重构为更量身定制的解决方案之前,这种策略仍然是入门的好方法。

GraphQL is still relatively new, which means that while everybody is busy extolling its virtues, it’s easy to overlook the very real challenges involved with building GraphQL apps.

GraphQL还是一个​​相对较新的概念,这意味着尽管每个人都在忙于赞美自己的优点,但很容易忽略构建GraphQL应用程序所涉及的真正挑战。

Thankfully these challenges all have solutions, and the more we discuss them (the Vulcan Slack is a great place for that by the way!), the better these solutions will become!

值得庆幸的是,这些挑战都有解决方案,而我们讨论的内容越多(顺便说一下, Vulcan Slack是一个绝佳的选择!),这些解决方案将变得更好!

翻译自: https://www.freecodecamp.org/news/five-common-problems-in-graphql-apps-and-how-to-fix-them-ac74d37a293c/

小程序 graphql

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/cumi7754/article/details/108159302

智能推荐

什么是内部类?成员内部类、静态内部类、局部内部类和匿名内部类的区别及作用?_成员内部类和局部内部类的区别-程序员宅基地

文章浏览阅读3.4k次,点赞8次,收藏42次。一、什么是内部类?or 内部类的概念内部类是定义在另一个类中的类;下面类TestB是类TestA的内部类。即内部类对象引用了实例化该内部对象的外围类对象。public class TestA{ class TestB {}}二、 为什么需要内部类?or 内部类有什么作用?1、 内部类方法可以访问该类定义所在的作用域中的数据,包括私有数据。2、内部类可以对同一个包中的其他类隐藏起来。3、 当想要定义一个回调函数且不想编写大量代码时,使用匿名内部类比较便捷。三、 内部类的分类成员内部_成员内部类和局部内部类的区别

分布式系统_分布式系统运维工具-程序员宅基地

文章浏览阅读118次。分布式系统要求拆分分布式思想的实质搭配要求分布式系统要求按照某些特定的规则将项目进行拆分。如果将一个项目的所有模板功能都写到一起,当某个模块出现问题时将直接导致整个服务器出现问题。拆分按照业务拆分为不同的服务器,有效的降低系统架构的耦合性在业务拆分的基础上可按照代码层级进行拆分(view、controller、service、pojo)分布式思想的实质分布式思想的实质是为了系统的..._分布式系统运维工具

用Exce分析l数据极简入门_exce l趋势分析数据量-程序员宅基地

文章浏览阅读174次。1.数据源准备2.数据处理step1:数据表处理应用函数:①VLOOKUP函数; ② CONCATENATE函数终表:step2:数据透视表统计分析(1) 透视表汇总不同渠道用户数, 金额(2)透视表汇总不同日期购买用户数,金额(3)透视表汇总不同用户购买订单数,金额step3:讲第二步结果可视化, 比如, 柱形图(1)不同渠道用户数, 金额(2)不同日期..._exce l趋势分析数据量

宁盾堡垒机双因素认证方案_horizon宁盾双因素配置-程序员宅基地

文章浏览阅读3.3k次。堡垒机可以为企业实现服务器、网络设备、数据库、安全设备等的集中管控和安全可靠运行,帮助IT运维人员提高工作效率。通俗来说,就是用来控制哪些人可以登录哪些资产(事先防范和事中控制),以及录像记录登录资产后做了什么事情(事后溯源)。由于堡垒机内部保存着企业所有的设备资产和权限关系,是企业内部信息安全的重要一环。但目前出现的以下问题产生了很大安全隐患:密码设置过于简单,容易被暴力破解;为方便记忆,设置统一的密码,一旦单点被破,极易引发全面危机。在单一的静态密码验证机制下,登录密码是堡垒机安全的唯一_horizon宁盾双因素配置

谷歌浏览器安装(Win、Linux、离线安装)_chrome linux debian离线安装依赖-程序员宅基地

文章浏览阅读7.7k次,点赞4次,收藏16次。Chrome作为一款挺不错的浏览器,其有着诸多的优良特性,并且支持跨平台。其支持(Windows、Linux、Mac OS X、BSD、Android),在绝大多数情况下,其的安装都很简单,但有时会由于网络原因,无法安装,所以在这里总结下Chrome的安装。Windows下的安装:在线安装:离线安装:Linux下的安装:在线安装:离线安装:..._chrome linux debian离线安装依赖

烤仔TVの尚书房 | 逃离北上广?不如押宝越南“北上广”-程序员宅基地

文章浏览阅读153次。中国发达城市榜单每天都在刷新,但无非是北上广轮流坐庄。北京拥有最顶尖的文化资源,上海是“摩登”的国际化大都市,广州是活力四射的千年商都。GDP和发展潜力是衡量城市的数字指...

随便推点

java spark的使用和配置_使用java调用spark注册进去的程序-程序员宅基地

文章浏览阅读3.3k次。前言spark在java使用比较少,多是scala的用法,我这里介绍一下我在项目中使用的代码配置详细算法的使用请点击我主页列表查看版本jar版本说明spark3.0.1scala2.12这个版本注意和spark版本对应,只是为了引jar包springboot版本2.3.2.RELEASEmaven<!-- spark --> <dependency> <gro_使用java调用spark注册进去的程序

汽车零部件开发工具巨头V公司全套bootloader中UDS协议栈源代码,自己完成底层外设驱动开发后,集成即可使用_uds协议栈 源代码-程序员宅基地

文章浏览阅读4.8k次。汽车零部件开发工具巨头V公司全套bootloader中UDS协议栈源代码,自己完成底层外设驱动开发后,集成即可使用,代码精简高效,大厂出品有量产保证。:139800617636213023darcy169_uds协议栈 源代码

AUTOSAR基础篇之OS(下)_autosar 定义了 5 种多核支持类型-程序员宅基地

文章浏览阅读4.6k次,点赞20次,收藏148次。AUTOSAR基础篇之OS(下)前言首先,请问大家几个小小的问题,你清楚:你知道多核OS在什么场景下使用吗?多核系统OS又是如何协同启动或者关闭的呢?AUTOSAR OS存在哪些功能安全等方面的要求呢?多核OS之间的启动关闭与单核相比又存在哪些异同呢?。。。。。。今天,我们来一起探索并回答这些问题。为了便于大家理解,以下是本文的主题大纲:[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JCXrdI0k-1636287756923)(https://gite_autosar 定义了 5 种多核支持类型

VS报错无法打开自己写的头文件_vs2013打不开自己定义的头文件-程序员宅基地

文章浏览阅读2.2k次,点赞6次,收藏14次。原因:自己写的头文件没有被加入到方案的包含目录中去,无法被检索到,也就无法打开。将自己写的头文件都放入header files。然后在VS界面上,右键方案名,点击属性。将自己头文件夹的目录添加进去。_vs2013打不开自己定义的头文件

【Redis】Redis基础命令集详解_redis命令-程序员宅基地

文章浏览阅读3.3w次,点赞80次,收藏342次。此时,可以将系统中所有用户的 Session 数据全部保存到 Redis 中,用户在提交新的请求后,系统先从Redis 中查找相应的Session 数据,如果存在,则再进行相关操作,否则跳转到登录页面。此时,可以将系统中所有用户的 Session 数据全部保存到 Redis 中,用户在提交新的请求后,系统先从Redis 中查找相应的Session 数据,如果存在,则再进行相关操作,否则跳转到登录页面。当数据量很大时,count 的数量的指定可能会不起作用,Redis 会自动调整每次的遍历数目。_redis命令

URP渲染管线简介-程序员宅基地

文章浏览阅读449次,点赞3次,收藏3次。URP的设计目标是在保持高性能的同时,提供更多的渲染功能和自定义选项。与普通项目相比,会多出Presets文件夹,里面包含着一些设置,包括本色,声音,法线,贴图等设置。全局只有主光源和附加光源,主光源只支持平行光,附加光源数量有限制,主光源和附加光源在一次Pass中可以一起着色。URP:全局只有主光源和附加光源,主光源只支持平行光,附加光源数量有限制,一次Pass可以计算多个光源。可编程渲染管线:渲染策略是可以供程序员定制的,可以定制的有:光照计算和光源,深度测试,摄像机光照烘焙,后期处理策略等等。_urp渲染管线

推荐文章

热门文章

相关标签